Beispiel #1
0
        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"));
            }
        }