// Opens the testing namespace/class public static string unitSpaceOpen(string spce) { string testNameSpace = Boilerplate.GetNamespace(spce); string parentClass = Boilerplate.GetClass(spce); return ("\r\nnamespace " + testNameSpace + "\r\n" + "{\r\n" + " [TestFixture]\r\n" + " public partial class Test_" + spce.Replace(".", "") + " : " + parentClass + "\r\n" + " {\r\n"); }
/// <summary> /// Assembles the text that goes at the top of the .cs file /// </summary> public static string InitialBoilerplate(string file, string space) { // Read the file and extract the "namespace" and "using" data StreamReader stream = new StreamReader(file); string line = "", refs = ""; for (int i = 0; i < 5; i++) { line = stream.ReadLine(); if (line.Contains("References:")) { refs = Util.Clean(line, "References:"); } } // Assemble the result string nspace = GetNamespace(space); return(Boilerplate.license + Boilerplate.Using(refs, nspace) + "namespace " + nspace + "\r\n{\r\n" + ClassDecl(GetClass(space))); }
/// <summary> /// Iterates through the .akk file line by line and converts it to C#. /// </summary> public static string CompilerOutput(string file) { // Mutable variables int ruleCount = 0; int lastLineDepth = 0; int parenCount = 0; bool isCommentBlock = false; bool isRulePart = false; string rulePart = ""; List <string> subrules = new List <string>(); string previousLine = ""; // Keeps track of the previous .akk line string tableMatchLine = ""; // Rule input that must be matched in a table string currentRuleType = ""; // For main rules and subrule string mainRuleType = ""; // For main rules string methodCacheLine = ""; // Creates line that caches method results bool cacheRule = false; // Should method results be cached? string unitTests = ""; // Accumulates lines as they are processed // First pass: get the document namespace string docNameSpace = Boilerplate.GetDocNameSpace(file); // Second pass: get the file metadata string result = Boilerplate.InitialBoilerplate(file, docNameSpace); // Third pass: parse the rules, line by line StreamReader stream = new StreamReader(file); string line; while ((line = stream.ReadLine()) != null) { line = line.Replace("\t", " "); int depth = Util.Depth(line); // Handle commented lines, comment blocks, and mid-line comments if (!isCommentBlock && Util.IsCommentBlockLine(line)) { isCommentBlock = true; } else if (isCommentBlock && Util.IsCommentBlockLine(line)) { isCommentBlock = false; continue; } if (isCommentBlock || Util.IsComment(line)) { previousLine = line; // Get previous line, to capture any question text continue; } line = Util.DeComment(line); // Create unit test from .akk if (Tests.IsTestLine(line)) { unitTests += Tests.ProcessTestLine(line); continue; } // Process the line if (Util.IsMainRule(line)) // Begin a new rule { // Close previous rule if (ruleCount != 0) { result += Util.ReorderSubrules(subrules, mainRuleType, cacheRule, methodCacheLine); result += Util.EndRule; } subrules.Clear(); // Process current line cacheRule = false; result += Convert(line, previousLine, file, tableMatchLine, currentRuleType, docNameSpace); // Detect whether this is a function that needs to be cached const string wrd = TransformMethod.wrd; const string typs = TransformMethod.typs; if (Regex.Match(line, @"(?<typ>" + typs + @")(?<sym>Sym)?(?<quest>\?)? (?<fcn>" + wrd + @")\((?<argtyp1>" + wrd + @" )(?<arg1>" + wrd + @")(?<comma1>, ?)?(?<argtyp2>" + wrd + @" )?(?<arg2>" + wrd + @")?(?<comma2>, ?)?(?<argtyp3>" + wrd + @" )?(?<arg3>" + wrd + @")?\) =").Success) { cacheRule = true; methodCacheLine = TransformMethod.MethodCacheLine(line, docNameSpace); } // Set flag variables ruleCount++; parenCount = 0; currentRuleType = Util.ExtractRuleType(line); mainRuleType = currentRuleType; totalRuleCount++; } else // Add ordinary rule conditions { string snippet = ""; if (depth > 0) { isRulePart = true; } // Identify return type of subrule if (depth == 1 && Util.IsDeclaration(line)) { currentRuleType = Util.ExtractRuleType(line); } // Deal with parentheses if (line.Trim() == "...") { parenCount++; } int closingParensNeeded = Math.Min(lastLineDepth - depth, parenCount); if (parenCount > 0 && closingParensNeeded > 0) { parenCount = parenCount - closingParensNeeded; snippet += Util.ClosingParens(closingParensNeeded, lastLineDepth); } // Handle rule tables if (line.Trim().StartsWith("match")) { tableMatchLine = line; } // Convert the line items (to main rule or subrule) snippet += " " + Convert(line, previousLine, file, tableMatchLine, currentRuleType, docNameSpace) + "\r\n"; if (isRulePart) { rulePart += snippet; } else { result += snippet; } } if (Util.IsBlank(line)) // Blank lines { // Reset subrule flag and add subrule to subrule list isRulePart = false; if (rulePart != "") { subrules.Add(rulePart); } rulePart = ""; } else { SlocCount++; // Doesn't count test case lines (by design) } lastLineDepth = depth; } stream.Close(); // Close the final method result += Util.ReorderSubrules(subrules, mainRuleType, cacheRule, methodCacheLine); result += Util.EndRule; // Close the class/namespace, and add the unit tests result += Boilerplate.ClassAndNamespaceClose; string unitTestNameSpace = docNameSpace; result += Tests.WriteUnitTests(unitTests, unitTestNameSpace); return(result); }