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; }
private static void ParseLogicBlock(string type, string template, ref int i, StringBuilder buffer, StringBuilder output, CodeGeneratorResult result) { int openParen = SearchAhead(template, i, "("); if (openParen == -1) throw new MacheteException(string.Format("Expected ( while parsing {0}.", type)); int closeParen = FindClosingParen(template, openParen); if (closeParen == -1) throw new MacheteException(string.Format("Matching ) not found while parsing {0}.", type)); int openCurlyBrace = SearchAhead(template, closeParen, "{"); if (openCurlyBrace == -1) throw new MacheteException(string.Format("Expected { while parsing {0}.", type)); int closeCurlyBrace = FindClosingCurlyBrace(template, openCurlyBrace); if (closeCurlyBrace == -1) throw new MacheteException(string.Format("Matching } not found while parsing {0}.", type)); AppendLine(output, template, i, openCurlyBrace); int startCode = openCurlyBrace + 1; int endCode = closeCurlyBrace - 1; if (startCode < endCode) GenerateMethodBody(output, template, startCode, endCode, result); output.AppendLine("}"); i = closeCurlyBrace + 1; }
private static void GenerateMethodBody(StringBuilder output, string template, int start, int end, CodeGeneratorResult result) { StringBuilder buffer = new StringBuilder(); int i = start; while (i <= end) { if (template[i] == '@') { if (LookAhead(template, i, "@@")) { buffer.Append("@"); i += 2; continue; } FlushBuffer(BufferContents.Literal, buffer, output); i++; if (LookAhead(template, i, "{")) { ParseCodeBlock(template, ref i, buffer, output); } else if (LookAhead(template, i, "for")) { ParseLogicBlock("for", template, ref i, buffer, output, result); } else if (LookAhead(template, i, "foreach")) { ParseLogicBlock("foreach", template, ref i, buffer, output, result); } else if (LookAhead(template, i, "if")) { ParseLogicBlock("if", template, ref i, buffer, output, result); } else if (LookAhead(template, i, "property")) { ParseDeclaration("property", template, ref i, buffer, output, (x) => result.Properties.Add(x)); } else if (LookAhead(template, i, "using")) { ParseDeclaration("using", template, ref i, buffer, output, (x) => result.Usings.Add(x)); } else if (LookAhead(template, i, "var")) { ParseDeclaration("var", template, ref i, buffer, output, (x) => output.AppendLine("{0};", x)); } else if (LookAhead(template, i, "while")) { ParseLogicBlock("while", template, ref i, buffer, output, result); } else { ParseExpression(template, ref i, buffer, output); } } else { buffer.Append(template[i]); i++; } } FlushBuffer(BufferContents.Literal, buffer, output); }
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("}"); }