public static LRParsingTable From(CLRStateGenerator stateMachine, ProductionTable productionTable) { var table = new LRParsingTable(stateMachine.States.Count, productionTable); var kernelLookup = new Dictionary <Kernel, int>(); var ruleLookup = new Dictionary <Rule, int>(); // Create rule lookup table int ptr = 0; foreach (var production in productionTable.Productions) { foreach (var rule in production.Rules) { table.Productions[ptr] = rule; ruleLookup[rule] = ptr++; } } // Create state lookup table ptr = 0; foreach (var entry in stateMachine.States) { kernelLookup[entry.Key] = ptr++; } foreach (var stateEntry in stateMachine.States) { var tableRow = table.Rows[kernelLookup[stateEntry.Key]]; foreach (var groupEntry in stateEntry.Value.GroupRulesBySymbolAfter()) { var symbol = groupEntry.Key; // SHIFT? if (symbol.Type == SymbolType.Token) { var action = new LRParsingTableAction(ActionType.Shift, kernelLookup[groupEntry.Value]); Debug.Assert(!tableRow.Actions.ContainsKey(symbol.ID) || tableRow.Actions[symbol.ID].Type != ActionType.Reduce, $"Shift/reduce conflict in the syntax grammar"); tableRow.Actions.Add(symbol.ID, action); } // GOTO? if (symbol.Type == SymbolType.Production) { int stateID = kernelLookup[groupEntry.Value]; tableRow.GOTO.Add(symbol.ID, stateID); } } // REDUCE? foreach (var itemset in stateEntry.Value.Closure.Where(s => s.SymbolAfter == null)) { foreach (var lookahead in itemset.Lookahead) { if (tableRow.Actions.ContainsKey(lookahead.ID)) { Debug.Assert(false, $"{tableRow.Actions[lookahead.ID].Type.ToString()}/Reduce conflict in the syntax grammar"); } tableRow.Actions.Add(lookahead.ID, new LRParsingTableAction(ActionType.Reduce, ruleLookup[itemset.Rule])); } } } table.Rows[1].Actions[Symbol.EndStream.ID] = new LRParsingTableAction(ActionType.Accept, -1); return(table); }
public ExampleLangTest(string program, [CallerMemberNameAttribute] string testName = "unknown") { string cwd = Directory.GetCurrentDirectory(); string localDirectory; using (var md5 = System.Security.Cryptography.MD5.Create()) { var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(program)); localDirectory = Path.Combine(cwd, $"{testName}_{BitConverter.ToString(hash).Replace("-", "")}"); } if (Directory.Exists(localDirectory)) { Directory.Delete(localDirectory, true); } Directory.CreateDirectory(localDirectory); try { SymbolTable.Reset(); // Lexical analysis var tokenConfigurationFile = new LexicalConfigurationFile(TokenPath); var tokenParserTableGenerator = new TokenParserTableGenerator(tokenConfigurationFile); var tokenParser = new TokenParser(tokenParserTableGenerator.NFATable); var tokenStream = tokenParser.ParseString(program); // Syntactic analysis var syntaxConfigurationFile = new SyntacticConfigurationFile(SyntaxPath); var productionTable = new ProductionTable(syntaxConfigurationFile); var clrStates = new CLRStateGenerator(productionTable, syntaxConfigurationFile); var lrTable = LRParsingTable.From(clrStates, productionTable); var syntaxParser = new LRParser(syntaxConfigurationFile, tokenStream); var ast = syntaxParser.Parse(lrTable, tokenStream); foreach (var file in Directory.GetFiles(SemanticVisitorsPath, "*.py")) { new SemanticVisitor(file).Traverse(ast); } var instructionStream = new InstructionStream(); foreach (var file in Directory.GetFiles(CodeGeneratorVisitorsPath, "*.py")) { new CodeGeneratorVisiter(file, instructionStream).Traverse(ast); } File.WriteAllText(Path.Combine(localDirectory, InstructionStreamFileName), instructionStream.ToString()); File.Copy(PostBuildScript, Path.Combine(localDirectory, new FileInfo(PostBuildScript).Name)); File.Copy(STDIO_D, Path.Combine(localDirectory, new FileInfo(STDIO_D).Name)); var process = new System.Diagnostics.Process(); process.StartInfo = new System.Diagnostics.ProcessStartInfo() { FileName = "powershell", Arguments = PostBuildScript, WorkingDirectory = localDirectory, RedirectStandardOutput = true }; process.Start(); process.WaitForExit(); Log.WriteLineVerbose(process.StandardOutput.ReadToEnd()); string exePath = Path.Combine(localDirectory, "program.exe"); if (!File.Exists(exePath)) { throw new BuildFailureException("Program.exe did not build. Likely a problem in the IR when building using GCC"); } this.OutputPath = Path.Combine(localDirectory, "debug_output.out"); process = new System.Diagnostics.Process(); process.StartInfo = new System.Diagnostics.ProcessStartInfo() { FileName = exePath, WorkingDirectory = localDirectory }; process.Start(); process.WaitForExit(); } catch (Exception e) { throw e; } finally { Log.Dump(Path.Combine(localDirectory, "dmp.log")); } }