private static void GenerateScript(
            StringBuilder output,
            string template,
            CodeGeneratorParameters parameters)
        {
            StringBuilder methodOutput = new StringBuilder(1024);

            int lineNumber = 1;

            GenerateMethodBody(
                methodOutput,
                template,
                parameters,
                0,
                template.Length - 1,
                ref lineNumber);

            output.AppendLine($@"class ScriptTemplate : TemplateBase<{parameters.TemplateContextType.FullName}> {{");
            output.AppendLine($"\tpublic ScriptTemplate(TextWriter output, {parameters.TemplateContextType.FullName} context) : base(output, context) {{ }}");

            foreach (var property in GetTypeProperties(parameters.TemplateContextType))
            {
                output.Append($"\tprivate {GetTypeString(property.PropertyType)} {property.Name} {{ get => _Context.{property.Name}; ");

                if (property.SetMethod?.IsPublic ?? false)
                {
                    output.Append($"set => _Context.{property.Name} = value; ");
                }

                output.AppendLine("}");
            }

            foreach (var method in GetTypeMethods(parameters.TemplateContextType))
            {
                var methodParams            = method.GetParameters();
                var methodParamsDeclaration = string.Join(", ", method.GetParameters().Select(x => $"{GetTypeString(x.ParameterType)} {x.Name}"));
                var methodParamsList        = string.Join(", ", method.GetParameters().Select(x => x.Name));

                if (!method.IsStatic)
                {
                    output.AppendLine($"\tprivate {GetTypeString(method.ReturnType)} {method.Name}({methodParamsDeclaration}) => _Context.{method.Name}({methodParamsList});");
                }
                else
                {
                    output.AppendLine($"\tprivate static {GetTypeString(method.ReturnType)} {method.Name}({methodParamsDeclaration}) => {GetTypeString(method.DeclaringType)}.{method.Name}({methodParamsList});");
                }
            }

            output.AppendLine("\tpublic void _Run() {");
            output.Append(methodOutput.ToString());
            output.AppendLine("\t}");
            output.AppendLine("}");

            output.AppendLine();

            output.AppendLine($"return new Action<TextWriter, {parameters.TemplateContextType.FullName}>((output, context) => {{");
            output.AppendLine("\tvar template = new ScriptTemplate(output, context);");
            output.AppendLine("\ttemplate._Run();");
            output.AppendLine("});");
        }
        private static void FlushBuffer(
            CodeGeneratorParameters parameters,
            BufferContents contents,
            StringBuilder buffer,
            StringBuilder output,
            int lineNumber)
        {
            if (parameters.IncludeLineDirectives)
            {
                output.AppendLine($"#line {lineNumber}");
            }

            if (buffer.Length > 0)
            {
                switch (contents)
                {
                case BufferContents.Literal:
                    string literal = buffer.ToString().Replace("\"", "\"\"");
                    output.AppendLine($"_WriteLiteral(@\"{literal}\");");
                    break;

                case BufferContents.Expression:
                    output.AppendLine($"_Write({buffer.ToString()});");
                    break;
                }

                buffer.Clear();
            }
        }
        private static void ParseCodeBlock(
            string template,
            CodeGeneratorParameters parameters,
            ref int i,
            ref int lineNumber,
            StringBuilder output)
        {
            if (parameters.IncludeLineDirectives)
            {
                output.AppendLine($"#line {lineNumber}");
            }

            int closeCurlyBrace = FindClosingCurlyBrace(template, i);

            if (closeCurlyBrace == -1)
            {
                throw new TextDecoratorDotNetException("Matching } not found while parsing code block.");
            }

            int startCode = i + 1;
            int endCode   = closeCurlyBrace - 1;

            if (startCode < endCode)
            {
                AppendLine(output, template, startCode, endCode);
            }

            i = closeCurlyBrace + 1;
        }
Beispiel #4
0
        public void Construct()
        {
            var buildSystem   = new FakeBuildSystem();
            var codeNamespace = new CodeNamespace(_sampleNamespace);
            ICodeGeneratorParameters configuration = new CodeGeneratorParameters(_outputDirectory);
            var testBuilders = MemberBuilderFactory.Default;

            Assert.Throws <ArgumentNullException>(() => new CSharpCodeGenerator(null, codeNamespace, testBuilders, configuration));
            Assert.Throws <ArgumentNullException>(() => new CSharpCodeGenerator(buildSystem, null, testBuilders, configuration));
            new CSharpCodeGenerator(buildSystem, codeNamespace, null, configuration);
            Assert.Throws <ArgumentException>(() => new CSharpCodeGenerator(buildSystem, codeNamespace, testBuilders, null));


            configuration = MockRepository.GenerateStub <ICodeGeneratorParameters>();
            configuration.Expect((e) => e.OutputDirectory).Return(null);
            Assert.Throws <ArgumentNullException>(() => new CSharpCodeGenerator(buildSystem, codeNamespace, testBuilders, configuration));
            configuration.Expect((e) => e.OutputDirectory).Return(string.Empty);
            Assert.Throws <ArgumentException>(() => new CSharpCodeGenerator(buildSystem, codeNamespace, testBuilders, configuration));

            configuration = new CodeGeneratorParameters(_outputDirectory);
            buildSystem   = new FakeBuildSystem()
            {
                FakeDirectoryExists = false
            };
            Assert.Throws <ApplicationException>(() => new CSharpCodeGenerator(buildSystem, codeNamespace, testBuilders, configuration));
        }
Beispiel #5
0
 public void ConstructWithParametersOutputDirectoryTest()
 {
     this.outputDirectory = "Value of outputDirectory";
     this.testObject      = new CodeGeneratorParameters(this.outputDirectory);
     Assert.Throws <ArgumentException>(() => new CodeGeneratorParameters(string.Empty));
     Assert.Throws <ArgumentNullException>(() => new CodeGeneratorParameters(null));
 }
Beispiel #6
0
        private void BtnGoClick(object sender, EventArgs e)
        {
            Dumper();

            string outputFolder = this._outputDirectoryTextBox.Text;

            var para = new CodeGeneratorParameters(outputFolder)
            {
                MethodGeneratorLevelOfDetail = MemberVisibility.Internal
            };
            // bg.CustomGeneratorParameters = para;

            /*var bg = new LoadAssemblyWorker(sbs, this.buildData, this)
             * {
             * BrowseInputAssemblyButton = this._browseInputAssemblyButton,
             * BrowseOutputDirectoryButton = this._browseOutputDirectoryButton,
             * GoButton = this._goButton,
             *  Logger = Log,
             * };*/

            Type                 generatorType        = (Type)cbGenerators.SelectedItem;
            string               inputAssemblyPath    = this._inputAssemblyTextBox.Text;
            IList <TreeNode>     mainNodes            = this._assemblyGraphTreeView.Nodes.Cast <TreeNode>().ToList();
            IList <AssemblyName> referencedAssemblies = this._referencedAssemblies;
            //var data = new GeneratorRunnerData(outputFolder, generatorType, inputAssemblyPath, mainNodes.MapToNodes(), referencedAssemblies);
            var data = GeneratorRunnerData.Create(outputFolder, generatorType, inputAssemblyPath, mainNodes.MapToNodes(), referencedAssemblies);


            bg.RunWorkerAsync(data, para);
        }
Beispiel #7
0
        public void SetUp()
        {
            var codeNamespace = new CodeNamespace(_sampleNamespace);
            var configuration = new CodeGeneratorParameters(_outputDirectory);
            // Todo: Mock this.
            var testBuilders = MemberBuilderFactory.Default;
            var buildSystem  = new FakeBuildSystem();

            _cSharpCodeGenerator =
                new CSharpCodeGenerator(buildSystem, codeNamespace, testBuilders, configuration);
        }
        private static void ParseExpression(
            string template,
            CodeGeneratorParameters parameters,
            ref int i,
            ref int lineNumber,
            StringBuilder buffer,
            StringBuilder output)
        {
            bool finished = false;

            while (!finished)
            {
                if (!char.IsLetterOrDigit(template[i]))
                {
                    finished = true;

                    if (template[i] == '.')
                    {
                        buffer.Append(template[i]);
                        i++;
                        finished = false;
                    }
                    else if (template[i] == '(')
                    {
                        ParseExpressionBlock(template, ref i, buffer, '(', ')');
                        finished = false;
                    }
                    else if (template[i] == '[')
                    {
                        ParseExpressionBlock(template, ref i, buffer, '[', ']');
                        finished = false;
                    }
                }
                else
                {
                    buffer.Append(template[i]);
                    i++;
                }

                if (i >= template.Length)
                {
                    finished = true;
                }
            }

            FlushBuffer(
                parameters,
                BufferContents.Expression,
                buffer,
                output,
                lineNumber);
        }
Beispiel #9
0
        public CodeGeneratorResult Generate(string template, CodeGeneratorParameters parameters)
        {
            if (template == null)
                throw new ArgumentNullException("template");

            StringBuilder output = new StringBuilder();
            CodeGeneratorResult result = new CodeGeneratorResult();

            GenerateClass(output, template, parameters, result);

            result.Code = output.ToString();

            return result;
        }
        public static string Generate(string template, CodeGeneratorParameters parameters)
        {
            if (template == null)
            {
                throw new ArgumentNullException(nameof(template));
            }

            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            StringBuilder output = new StringBuilder(1024);

            GenerateScript(output, template, parameters);

            return(output.ToString());
        }
Beispiel #11
0
        static void Main(string[] args)
        {
            string templateSource = @"@using System.Diagnostics
            @property int Count
            @property string Name
            <html>
            <head>
            </head>
            <body>
            @for (int i = 0; i < Count; i++) {
            <p>Hello @Name!</p>
            }
            </body>
            </html>";

            CodeGenerator codeGenerator = new CodeGenerator();

            var codeGeneratorParameters = new CodeGeneratorParameters();
            codeGeneratorParameters.ClassName = "Foo";

            var codeGeneratorResult = codeGenerator.Generate(templateSource, codeGeneratorParameters);

            //Console.WriteLine(codeGeneratorResult.Code);

            Compiler compiler = new Compiler();

            var compilerParameters = new CompilerParameters();

            var template = compiler.CompileTemplate(templateSource, compilerParameters);
            template.SetPropertyValue("Count", 20);
            template.SetPropertyValue("Name", "Bob Freeman");

            Console.WriteLine(template.Run());

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }
        private static void ParseLogicBlock(
            string type,
            string template,
            CodeGeneratorParameters parameters,
            ref int i,
            ref int lineNumber,
            StringBuilder output)
        {
            if (parameters.IncludeLineDirectives)
            {
                output.AppendLine($"#line {lineNumber}");
            }

            int openParen = FindNext(template, i, "(");

            if (openParen == -1)
            {
                throw new TextDecoratorDotNetException(string.Format("Expected ( while parsing {0}.", type));
            }

            int closeParen = FindClosingParen(template, openParen);

            if (closeParen == -1)
            {
                throw new TextDecoratorDotNetException(string.Format("Matching ) not found while parsing {0}.", type));
            }

            int openCurlyBrace = FindNext(template, closeParen, "{");

            if (openCurlyBrace == -1)
            {
                throw new TextDecoratorDotNetException(string.Format("Expected {{ while parsing {0}.", type));
            }

            int closeCurlyBrace = FindClosingCurlyBrace(template, openCurlyBrace);

            if (closeCurlyBrace == -1)
            {
                throw new TextDecoratorDotNetException(string.Format("Matching }} not found while parsing {0}.", type));
            }

            output.Append(' '); // Append a single space to compensate for the @ sign.
            AppendLine(output, template, i, openCurlyBrace);

            int startCode = openCurlyBrace + 1;
            int endCode   = closeCurlyBrace - 1;

            while (startCode < template.Length && LookAhead(template, startCode, Environment.NewLine))
            {
                startCode += Environment.NewLine.Length;
                lineNumber++;
            }

            if (startCode < endCode)
            {
                GenerateMethodBody(
                    output,
                    template,
                    parameters,
                    startCode,
                    endCode,
                    ref lineNumber);
            }

            output.AppendLine("}");

            i = closeCurlyBrace + 1;
        }
Beispiel #13
0
 public void SetUp()
 {
     this.outputDirectory = "Value of outputDirectory";
     this.testObject      = new CodeGeneratorParameters(this.outputDirectory);
 }
Beispiel #14
0
        private static void GenerateClass(StringBuilder output, string template, CodeGeneratorParameters parameters, CodeGeneratorResult result)
        {
            StringBuilder methodOutput = new StringBuilder();
            GenerateMethodBody(methodOutput, template, 0, template.Length - 1, result);

            output.AppendLine("using System;");

            foreach (var usingString in result.Usings)
                output.AppendLine("using {0};", usingString);

            output.AppendLine();

            output.AppendLine("namespace Machete.Templates");
            output.AppendLine("{");
            output.AppendLine("\tpublic class {0} : {1}", parameters.ClassName, parameters.BaseClassName);
            output.AppendLine("\t{");

            foreach (var propertyString in result.Properties)
                output.AppendLine("\t\tpublic {0} {{ get; set; }}", propertyString);

            output.AppendLine();
            output.AppendLine("\t\tprotected override void Execute()");
            output.AppendLine("\t\t{");

            output.Append(methodOutput);

            output.AppendLine("\t\t}");
            output.AppendLine("\t}");
            output.AppendLine("}");
        }
Beispiel #15
0
 public void TearDown()
 {
     this.testObject = null;
 }
Beispiel #16
0
        public void GenerateWithAssemblyAndModuleAndClassesAndMethod()
        {
            //expected = false;
            var  outputFolder        = "Value ? of ou$tputFol*der";
            var  generatorType       = typeof(object);
            var  inputAssemblyPath   = "Value of inputAssemblyPath";
            char directorySeparator  = '\\';
            var  firstModuleName     = "TheTestNode";
            var  firstModuleTag      = "FirstModule";
            var  className1Namespace = "The.Namespace";
            var  className1          = "VeryPrettyFactory";
            var  className1FullName  = className1Namespace + "." + className1;
            var  classTag            = this.GetType();
            var  methodName          = "MyMethod";
            var  methodTag           = this.GetType().GetMethod("FakeMethod");

            var assemblyNode = new TestNode(firstModuleName + ".dll", TestNodeType.Assembly, null)
            {
                Checked = true
            };
            var moduleNode = new TestNode(firstModuleName + ".dll", TestNodeType.Module, firstModuleTag)
            {
                Checked = true
            };
            var classNode = new TestNode(className1FullName, TestNodeType.Class, classTag)
            {
                Checked = true
            };
            var methodNode = new TestNode(methodName, TestNodeType.Method, methodTag)
            {
                Checked = true
            };

            assemblyNode.Nodes.Add(moduleNode);
            moduleNode.Nodes.Add(classNode);
            classNode.Nodes.Add(methodNode);
            var mainNodes = new[] { assemblyNode };

            var referencedAssemblies = typeof(CSharpTestProjectBuilderTest).Assembly.GetReferencedAssemblies();
            var para       = new CodeGeneratorParameters(outputFolder);
            var runnerData = GeneratorRunnerData.Create(
                outputFolder, generatorType, inputAssemblyPath, mainNodes, referencedAssemblies);

            Expect.Call(sbs.DirectorySeparatorChar).Return(directorySeparator).Repeat.Any();
            Expect.Call(sbs.GetFileNameWithoutExtension(firstModuleName + ".dll")).Return(firstModuleName);
            var expectedDirectory = outputFolder + directorySeparator + firstModuleName + ".Tests";

            Expect.Call(sbs.CreateDirectory(expectedDirectory)).Return(null);
            Expect.Call(sbs.DirectoryExists(expectedDirectory)).Return(true);

            var prjReferencedAssemblies = new List <AssemblyName>();

            Expect.Call(projectGenerator.ReferencedAssemblies).Return(prjReferencedAssemblies).Repeat.Any();
            Expect.Call(projectGenerator.GenerateProjectFile).Repeat.Once();
            var classFilesList = new List <string>();

            Expect.Call(projectGenerator.ClassFiles).Return(classFilesList).Repeat.Once();

            var                  codeGenerator          = mocks.StrictMock <ICodeGenerator>();
            CodeNamespace        generatorCodeNamespace = null;
            IBuildDataDictionary generatorBuildData     = null;

            Expect.Call(createGeneratorCallback(sbs, null, null, null))
            //.Constraints(Is.Same(sbs), Is.TypeOf<CodeGeneratorParameters>(), Is.TypeOf<CodeNamespace>())
            .Constraints(
                Is.Same(sbs),
                Is.TypeOf <IBuildDataDictionary>() && Is.NotNull(),
                Is.TypeOf <CodeGeneratorParameters>() && Property.Value("OutputDirectory", expectedDirectory),
                Is.TypeOf <CodeNamespace>())
            //.Return(codeGenerator)
            .Do((Func <IBuildSystem, IBuildDataDictionary, ICodeGeneratorParameters, CodeNamespace, ICodeGenerator>)
                delegate(IBuildSystem buildSys, IBuildDataDictionary data, ICodeGeneratorParameters cgp, CodeNamespace cn)
            {
                Assert.AreEqual(expectedDirectory, cgp.OutputDirectory);
                Assert.IsFalse(cgp.UseSetupAndTearDown);

                generatorBuildData     = data;
                generatorCodeNamespace = cn;
                return(codeGenerator);
            });

            Expect.Call(codeGenerator.CodeNamespace   = null).PropertyBehavior();
            Expect.Call(codeGenerator.OutputDirectory = expectedDirectory);
            Expect.Call(codeGenerator.GenerateCode);

            // logging
            Expect.Call(delegate { this.logger(null); }).Constraints(Is.NotNull()).Repeat.AtLeastOnce();
            Expect.Call(projectGenerator.ProjectName).Return(firstModuleName).Repeat.Any();

            mocks.ReplayAll();

            testObject.GenerateTests(runnerData);
            //Assert.AreEqual(expected, actual);

            Assert.IsNotEmpty(generatorBuildData);
            Assert.Count(1, generatorBuildData);
            Assert.IsTrue(generatorBuildData.Contains(this.buildDataItem));

            Assert.IsNotEmpty(prjReferencedAssemblies);
            Assert.IsNotEmpty(classFilesList);

            Assert.IsEmpty(generatorCodeNamespace.Comments);
            Assert.IsEmpty(generatorCodeNamespace.Imports);
            Assert.AreEqual(className1Namespace, generatorCodeNamespace.Name);
            Assert.IsNotEmpty(generatorCodeNamespace.Types);
            Assert.IsEmpty(generatorCodeNamespace.UserData);

            var classDefinition1 = generatorCodeNamespace.Types[0];

            Assert.AreEqual(MemberAttributes.Private | MemberAttributes.Final, classDefinition1.Attributes);
            Assert.IsEmpty(classDefinition1.BaseTypes);
            Assert.IsEmpty(classDefinition1.Comments);
            Assert.IsEmpty(classDefinition1.CustomAttributes);

            Assert.AreEqual(className1FullName, classDefinition1.Name);
            Assert.IsTrue(classDefinition1.IsClass);
            Assert.IsEmpty(classDefinition1.StartDirectives);
            Assert.IsEmpty(classDefinition1.TypeParameters);

            Assert.IsNotEmpty(classDefinition1.UserData);
            Assert.Count(1, classDefinition1.UserData);
            Assert.AreEqual(classTag, classDefinition1.UserData[NStubConstants.UserDataClassTypeKey]);

            Assert.IsNotEmpty(classDefinition1.Members);
            var class1Members = classDefinition1.Members;

            // Todo: More checks on the generated types.
            mocks.VerifyAll();
        }
Beispiel #17
0
        /// <summary>
        /// Generates the edit page.
        /// </summary>
        /// <param name="entityName">Name of the entity.</param>
        /// <param name="generateContentPlaceholder">if set to <c>true</c> [generate content placeholder].</param>
        /// <param name="columns">The columns.</param>
        /// <param name="namespaceName">Name of the namespace.</param>
        /// <param name="outputPath">The output path.</param>
        /// <param name="relations">The relations.</param>
        private void GenerateEditPage(string entityName, bool generateContentPlaceholder, DatabaseColumn[] columns, string namespaceName, string outputPath, List <TableRelation> relations)
        {
            #region generate edit page

            FileStream   fileStreamEditPage = null;
            StreamWriter writeEditPage      = null;

            FileStream   fileStreamEditCodeBehind = null;
            StreamWriter writerEditCodeBehind     = null;


            FileStream   fileStreamEditControldCodeBehind = null;
            StreamWriter writerControlsCodeBehind         = null;

            Dictionary <string, string> dict = null;


            FileStream   fileStreamPresenter = null;
            StreamWriter writerPresenter     = null;

            try
            {
                parameters            = new CodeGeneratorParameters();
                parameters.Columns    = columns;
                parameters.EntityName = entityName;
                parameters.GenerateContentPlaceholder = generateContentPlaceholder;
                parameters.NamespaceName = namespaceName;
                parameters.OutputPath    = outputPath;
                parameters.Relations     = relations;


                fileStreamEditPage = new FileStream(outputPath + @"\" + entityName + "Edit.aspx", this.GetStreamOpenMode(outputPath + @"\" + entityName + "Edit.aspx"));
                writeEditPage      = new StreamWriter(fileStreamEditPage);

                dict = new Dictionary <string, string>();

                this.WriteEditPageHeader(writeEditPage);
                this.WriteEditPageContent(writeEditPage, out dict);
                this.WriteEditPageFooter(writeEditPage);

                //write edit page code behind
                writeEditPage.Flush();

                fileStreamEditCodeBehind = new FileStream(outputPath + @"\" + entityName + "Edit.aspx.cs", this.GetStreamOpenMode(outputPath + @"\" + entityName + "Edit.aspx.cs"));
                writerEditCodeBehind     = new StreamWriter(fileStreamEditCodeBehind);

                this.WriteEditPageCodeBehind(writerEditCodeBehind);

                writerEditCodeBehind.Flush();

                fileStreamEditControldCodeBehind = new FileStream(outputPath + @"\" + entityName + "Edit.aspx.designer.cs", this.GetStreamOpenMode(outputPath + @"\" + entityName + "Edit.aspx.designer.cs"));
                writerControlsCodeBehind         = new StreamWriter(fileStreamEditControldCodeBehind);

                this.WriteEditPageDesignerCode(writerControlsCodeBehind, dict);

                writerControlsCodeBehind.Flush();

                fileStreamPresenter = new FileStream(outputPath + @"\" + entityName + "EditPresenter.cs", this.GetStreamOpenMode(outputPath + @"\" + entityName + "Presenter.cs"));
                writerPresenter     = new StreamWriter(fileStreamPresenter);

                this.WriteEditPagePresenter(writerPresenter);

                writerPresenter.Flush();
            }
            finally
            {
                if (fileStreamEditPage != null)
                {
                    fileStreamEditPage.Close();
                }

                if (fileStreamEditCodeBehind != null)
                {
                    fileStreamEditCodeBehind.Close();
                }

                if (fileStreamEditControldCodeBehind != null)
                {
                    fileStreamEditControldCodeBehind.Close();
                }

                if (fileStreamPresenter != null)
                {
                    fileStreamPresenter.Close();
                }
            }
            #endregion
        }
        private static void GenerateMethodBody(
            StringBuilder output,
            string template,
            CodeGeneratorParameters parameters,
            int start,
            int end,
            ref int lineNumber)
        {
            StringBuilder buffer = new StringBuilder(1024);

            int i = start;

            while (i <= end)
            {
                if (template[i] == '@')
                {
                    if (LookAhead(template, i, "@@"))
                    {
                        buffer.Append("@");
                        i += 2;
                        continue;
                    }

                    if (buffer.Length != 0)
                    {
                        string bufferContents = buffer.ToString();

                        FlushBuffer(
                            parameters,
                            BufferContents.Literal,
                            buffer,
                            output,
                            lineNumber);

                        lineNumber += CountOccurences(bufferContents, 0, bufferContents.Length, Environment.NewLine);
                    }

                    i++;
                    int beforePos = i;

                    if (LookAhead(template, i, "("))
                    {
                        ParseExpressionBlock(template, ref i, buffer, '(', ')');

                        FlushBuffer(
                            parameters,
                            BufferContents.Expression,
                            buffer,
                            output,
                            lineNumber);
                    }
                    else if (LookAhead(template, i, "{"))
                    {
                        ParseCodeBlock(template, parameters, ref i, ref lineNumber, output);
                    }
                    else if (LookAhead(template, i, "for"))
                    {
                        ParseLogicBlock("for", template, parameters, ref i, ref lineNumber, output);
                    }
                    else if (LookAhead(template, i, "foreach"))
                    {
                        ParseLogicBlock("foreach", template, parameters, ref i, ref lineNumber, output);
                    }
                    else if (LookAhead(template, i, "if"))
                    {
                        ParseLogicBlock("if", template, parameters, ref i, ref lineNumber, output);
                    }
                    else if (LookAhead(template, i, "while"))
                    {
                        ParseLogicBlock("while", template, parameters, ref i, ref lineNumber, output);
                    }
                    else
                    {
                        ParseExpression(template, parameters, ref i, ref lineNumber, buffer, output);
                    }

                    lineNumber += CountOccurences(template, beforePos, i, Environment.NewLine);
                }
                else
                {
                    buffer.Append(template[i]);
                    i++;
                }
            }

            FlushBuffer(
                parameters,
                BufferContents.Literal,
                buffer,
                output,
                lineNumber);
        }