private TokenParser ConstructParser(string configuration)
        {
            var config = new LexicalConfigurationFile(configuration.Split("\r\n"), "config");
            var nfa    = new TokenParserTableGenerator(config).NFATable;

            return(new TokenParser(nfa));
        }
        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"));
            }
        }