Beispiel #1
0
        public Generator.Translation.Data.Translator ParseTranslator(IEnumerator <Generator.Translation.Data.Token> tokens)
        {
            Generator.Translation.Data.Translator node = new Generator.Translation.Data.Translator()
            {
                Name = "Translator"
            };
            switch (tokens.Current.Name)
            {
            case "goto":
            case "<=>":
            case "</>":
            case "[":
            case "symbol":
            case "escapedSymbol":
            case "newline":
            case "eof":
                node.Add(ParseSystems(tokens));
                node.Add(ParseRules(tokens));
                node.Add(ParseTerminal(tokens, "eof"));
                return(node);

            default:
                throw new UnexpectedTokenException(tokens.Current);
            }
        }
        static void Main(string[] args)
        {
            IClassGenerator  classGenerator  = new ClassGenerator();
            IBNFAnalyzer     bnfAnalyzer     = new BNFAnalyzer();
            IBNFParser       bnfParser       = new BNFParser();
            IParserGenerator parserGenerator = new ParserGenerator(bnfAnalyzer);

#if GENERATEGENERATOR
            Console.WriteLine("Generating generator...");
            BNF         bnf = bnfParser.Parse("../../docs/translator.bnf");
            string      translatorParserName  = "TranslatorParser";
            string      translatorVisitorName = "TranslatorVisitor";
            string      dataNamespace         = "Generator.Translation.Data";
            string      parsingNamespace      = "Generator.Translation.Parsing";
            string      visitorNamespace      = "Generator.Translation.Visitors";
            ClassType[] translatorParser      = parserGenerator.GenerateParserClasses(bnf, translatorParserName, dataNamespace, parsingNamespace);
            ClassType[] translatorVisitors    = parserGenerator.GenerateVisitorClasses(bnf, translatorVisitorName, dataNamespace, visitorNamespace);
            ClassType[] translatorData        = parserGenerator.GenerateSyntaxTreeClasses(bnf, translatorVisitorName, dataNamespace, visitorNamespace);
            var         classTypes            = translatorData.Union(translatorVisitors).Union(translatorParser);
            foreach (ClassType classType in classTypes)
            {
                string folder = $"../{string.Join("/", classType.NameSpace.Split('.'))}";
                Directory.CreateDirectory(folder);
                classGenerator.Generate(classType, $"{folder}/{classType.Identifier.Split('<')[0]}.cs");
            }
            Console.WriteLine($"...DONE {2 + classTypes.Count()} classes generated.");
#else
            ITranslatorGenerator translatorGenerator = new TranslatorGenerator();
            Console.WriteLine("Generating compiler...");
            Console.WriteLine("\tGenerating parser...");
            BNF                     bnf = bnfParser.Parse("../../docs/tang.bnf");
            string                  programParserName    = "ProgramParser";
            string                  programVisitorName   = "ProgramVisitor";
            string                  dataNamespace        = "Compiler.Parsing.Data";
            string                  parsingNamespace     = "Compiler.Parsing";
            string                  visitorNamespace     = "Compiler.Parsing.Visitors";
            ClassType[]             programParserClasses = parserGenerator.GenerateParserClasses(bnf, programParserName, dataNamespace, parsingNamespace);
            ClassType[]             programVisitors      = parserGenerator.GenerateVisitorClasses(bnf, programVisitorName, dataNamespace, visitorNamespace);
            ClassType[]             programData          = parserGenerator.GenerateSyntaxTreeClasses(bnf, programVisitorName, dataNamespace, visitorNamespace);
            IEnumerable <ClassType> classesToGenerate    = programData.Union(programVisitors).Union(programParserClasses);
            Console.WriteLine("\tGenerating Translators...");
            Lexer lexer = new Lexer("../../docs/translator.tokens.json");

            try
            {
                IEnumerator <Translation.Data.Token> tokens = lexer.Analyse(File.ReadAllText("../../docs/tang-ast.translator"), "ast-c.translator").Select(t => new Translation.Data.Token()
                {
                    FileName = "tang-ast.translator",
                    Name     = t.Name,
                    Value    = t.Value,
                    Row      = t.Row,
                    Column   = t.Column
                }).GetEnumerator();
                tokens.MoveNext();

                IEnumerator <Translation.Data.Token> toCTranslatorTokens = lexer.Analyse(File.ReadAllText("../../docs/ast-c.translator"), "ast-c.translator").Select(t => new Translation.Data.Token()
                {
                    FileName = "ast-c.translator",
                    Name     = t.Name,
                    Value    = t.Value,
                    Row      = t.Row,
                    Column   = t.Column
                }).GetEnumerator();
                toCTranslatorTokens.MoveNext();

                TranslatorParser translatorParser = new TranslatorParser();

                Translation.Data.Translator astTranslator = translatorParser.ParseTranslator(tokens);

                Translation.Data.Translator cTranslator = translatorParser.ParseTranslator(toCTranslatorTokens);

                string translatorName             = "ProgramToASTTranslator";
                string translatorNamespace        = "Compiler.Translation.ProgramToAST";
                string cTranslatorName            = "ASTToCTranslator";
                string cTranslatorNamespace       = "Compiler.Translation.ASTToC";
                string symbolTableDataNamspace    = "Compiler.Translation.SymbolTable.Data";
                string symbolTableVisitorNamspace = "Compiler.Translation.SymbolTable.Visitors";
                string symbolTableVisitorName     = "SymbolTableVisitor";
                string astDataNamspace            = "Compiler.AST.Data";
                string astVisitorNamespace        = "Compiler.AST.Visitors";
                string astVisitorName             = "ASTVisitor";
                string cDataNamspace     = "Compiler.C.Data";
                string cVisitorNamespace = "Compiler.C.Visitors";
                string cVisitorName      = "CVisitor";

                BNF cGrammar           = bnfParser.Parse("../../docs/c.bnf");
                BNF astGrammar         = bnfParser.Parse("../../docs/ast.bnf");
                BNF symbolTableGrammar = bnfParser.Parse("../../docs/symboltable.bnf");

                classesToGenerate = classesToGenerate.Union(parserGenerator.GenerateVisitorClasses(symbolTableGrammar, symbolTableVisitorName, symbolTableDataNamspace, symbolTableVisitorNamspace));
                classesToGenerate = classesToGenerate.Union(parserGenerator.GenerateSyntaxTreeClasses(symbolTableGrammar, symbolTableVisitorName, symbolTableDataNamspace, symbolTableVisitorNamspace));
                classesToGenerate = classesToGenerate.Union(parserGenerator.GenerateVisitorClasses(astGrammar, astVisitorName, astDataNamspace, astVisitorNamespace));
                classesToGenerate = classesToGenerate.Union(parserGenerator.GenerateSyntaxTreeClasses(astGrammar, astVisitorName, astDataNamspace, astVisitorNamespace));
                classesToGenerate = classesToGenerate.Union(parserGenerator.GenerateVisitorClasses(cGrammar, cVisitorName, cDataNamspace, cVisitorNamespace));
                classesToGenerate = classesToGenerate.Union(parserGenerator.GenerateSyntaxTreeClasses(cGrammar, cVisitorName, cDataNamspace, cVisitorNamespace));

                List <RelationDomain> relationDomains = new List <RelationDomain>()
                {
                    new RelationDomain()
                    {
                        Identifier = "Program", Grammar = bnf, DataNamespace = dataNamespace, VisitorNamespace = visitorNamespace
                    },
                    new RelationDomain()
                    {
                        Identifier = "AST", Grammar = astGrammar, DataNamespace = astDataNamspace, VisitorNamespace = astVisitorNamespace
                    },
                    new RelationDomain()
                    {
                        Identifier = "SymbolTable", Grammar = symbolTableGrammar, DataNamespace = symbolTableDataNamspace, VisitorNamespace = symbolTableVisitorNamspace
                    },
                };

                ClassType toASTTranslator = translatorGenerator.GenerateTranslatorClass(astTranslator, translatorName, relationDomains, translatorNamespace);

                classesToGenerate = classesToGenerate.Append(toASTTranslator);

                List <RelationDomain> cRelationDomains = new List <RelationDomain>()
                {
                    new RelationDomain()
                    {
                        Identifier = "AST", Grammar = astGrammar, DataNamespace = astDataNamspace, VisitorNamespace = astVisitorNamespace
                    },
                    new RelationDomain()
                    {
                        Identifier = "C", Grammar = cGrammar, DataNamespace = cDataNamspace, VisitorNamespace = cVisitorNamespace
                    },
                };

                ClassType toCTranslator = translatorGenerator.GenerateTranslatorClass(cTranslator, cTranslatorName, cRelationDomains, cTranslatorNamespace);

                classesToGenerate = classesToGenerate.Append(toCTranslator);

                foreach (ClassType classType in classesToGenerate)
                {
                    string folder = $"../{string.Join("/", classType.NameSpace.Split('.'))}";
                    Directory.CreateDirectory(folder);
                    classGenerator.Generate(classType, $"{folder}/{classType.Identifier.Split('<')[0]}.cs");
                }
                Console.WriteLine($"...Done {classesToGenerate.Count()} classes generated. Approximately {classesToGenerate.Sum(c => c.Methods.Sum(m => m.Body.Count + 3) + c.Usings.Count + c.Fields.Count)} lines of code. Thank You.");
            }
            catch (LexicalException exception)
            {
                Console.WriteLine($"Unexpected symbol near {exception.Symbol} in {exception.FileName} line {exception.Row + 1} column {exception.Column + 1}.");
            }
            catch (UnexpectedTokenException exception)
            {
                if (exception.Token.Name == exception.Token.Value)
                {
                    if (exception.Token.FileName != null)
                    {
                        Console.WriteLine($"Unexpected '{exception.Token.Name}' in {exception.Token.FileName} line {exception.Token.Row + 1} column {exception.Token.Column + 1}.");
                    }
                    else
                    {
                        Console.WriteLine($"Unexpected '{exception.Token.Name}' at line {exception.Token.Row + 1} column {exception.Token.Column + 1}.");
                    }
                }
                else
                {
                    Console.WriteLine($"Unexpected {exception.Token.Name} '{exception.Token.Value}' in {exception.Token.FileName} line {exception.Token.Row + 1} column {exception.Token.Column + 1}.");
                }
            }
#endif
        }