Exemplo n.º 1
0
        public void AddExpressionSpecialTestCodeGenerator()
        {
            Lexer lexer           = new Lexer(File.ReadAllText(AppContext.BaseDirectory + "/../../../../../docs/tang.tokens.json"));
            var   tokens          = lexer.Analyse("int8 a = 1 + 2 + 3");
            var   tokenEnumerator = tokens.Select(t => new Parsing.Data.Token()
            {
                Name = t.Name, Value = t.Value
            }).GetEnumerator();

            tokenEnumerator.MoveNext();
            Preprocessor preprocessor = new Preprocessor();

            tokens = preprocessor.Process(lexer, null, tokens);
            ProgramParser parser        = new ProgramParser();
            var           parseTree     = parser.ParseProgram(tokenEnumerator);
            var           astTranslator = new Translation.ProgramToAST.ProgramToASTTranslator();

            AST.Data.AST ast         = astTranslator.TranslatetoAST(parseTree) as AST.Data.AST;
            var          cTranslator = new Translation.ASTToC.ASTToCTranslator();

            C.Data.C c = cTranslator.Translate(ast) as C.Data.C;

            // c is the autogenerated tree, we have to manually create one and assert their equality

            var cExpected = new C.Data.C(true)
            {
                new C.Data.Declaration(true)
                {
                    new C.Data.CompoundDeclaration(true)
                    {
                        new C.Data.Declaration(true)
                        {
                            new C.Data.CompoundDeclaration(true)
                            {
                                new C.Data.Declaration(true)
                                {
                                    new C.Data.Token()
                                    {
                                        Name = "EPSILON"
                                    }
                                },
                                new C.Data.Declaration(true)
                                {
                                    new C.Data.IntegerDeclaration(true)
                                    {
                                        new C.Data.IntType(true)
                                        {
                                            new C.Data.Token()
                                            {
                                                Name = "signed"
                                            },
                                            new C.Data.Token()
                                            {
                                                Name = "char"
                                            }
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = "identifier"
                                        }
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = ";"
                                    }
                                }
                            }
                        },
                        new C.Data.Declaration(true)
                        {
                            new C.Data.CompoundDeclaration(true)
                            {
                                new C.Data.Declaration(true)
                                {
                                    new C.Data.FunctionPrototype(true)
                                    {
                                        new C.Data.Token()
                                        {
                                            Name = "signed"
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = "long"
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = "Pow"
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = "("
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = "signed"
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = "long"
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = "a"
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = ","
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = "signed"
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = "long"
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = "b"
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = ")"
                                        }
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = ";"
                                    }
                                },
                                new C.Data.Declaration(true)
                                {
                                    new C.Data.FunctionPrototype(true)
                                    {
                                        new C.Data.Type(true)
                                        {
                                            new C.Data.Token()
                                            {
                                                Name = "void"
                                            }
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = "main"
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = "("
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = ")"
                                        }
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = ";"
                                    }
                                }
                            }
                        }
                    }
                },
                new C.Data.Function(true)
                {
                    new C.Data.CompoundFunction(true)
                    {
                        new C.Data.Function(true)
                        {
                            new C.Data.CompoundFunction(true)
                            {
                                new C.Data.Function(true)
                                {
                                    new C.Data.Token()
                                    {
                                        Name = "signed"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "long"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "Pow"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "("
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "signed"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "long"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "a"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = ","
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "signed"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "long"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "b"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = ")"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "{"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "signed"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "long"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "r"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "="
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "1"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = ","
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "i"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = ";"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "for"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "("
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "i"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "="
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "0"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = ";"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "i"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "<"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "b"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = ";"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "i"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "++"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = ")"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "{"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "r"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "*="
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "a"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = ";"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "}"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "return"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "r"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = ";"
                                    },
                                    new C.Data.Token()
                                    {
                                        Name = "}"
                                    }
                                },
                                new C.Data.Function(true)
                                {
                                    new C.Data.Token()
                                    {
                                        Name = "EPSILON"
                                    }
                                }
                            }
                        },
                        new C.Data.Function(true)
                        {
                            new C.Data.Type(true)
                            {
                                new C.Data.Token()
                                {
                                    Name = "void"
                                }
                            },
                            new C.Data.Token()
                            {
                                Name = "main"
                            },
                            new C.Data.Token()
                            {
                                Name = "("
                            },
                            new C.Data.Token()
                            {
                                Name = ")"
                            },
                            new C.Data.Token()
                            {
                                Name = "{"
                            },
                            new C.Data.Declaration(true)
                            {
                                new C.Data.Token()
                                {
                                    Name = "EPSILON"
                                }
                            },
                            new C.Data.Statement(true)
                            {
                                new C.Data.CompoundStatement(true)
                                {
                                    new C.Data.Statement(true)
                                    {
                                        new C.Data.Token()
                                        {
                                            Name = "EPSILON"
                                        }
                                    },
                                    new C.Data.Statement(true)
                                    {
                                        new C.Data.IntegerAssignment(true)
                                        {
                                            new C.Data.Token()
                                            {
                                                Name = "identifier"
                                            },
                                            new C.Data.Token()
                                            {
                                                Name = "="
                                            },
                                            new C.Data.IntegerExpression(true)
                                            {
                                                new C.Data.AddExpression(true)
                                                {
                                                    new C.Data.Token()
                                                    {
                                                        Name = "("
                                                    },
                                                    new C.Data.IntegerExpression(true)
                                                    {
                                                        new C.Data.AddExpression(true)
                                                        {
                                                            new C.Data.Token()
                                                            {
                                                                Name = "("
                                                            },
                                                            new C.Data.IntegerExpression(true)
                                                            {
                                                                new C.Data.Token()
                                                                {
                                                                    Name = "numeral"
                                                                }
                                                            },
                                                            new C.Data.Token()
                                                            {
                                                                Name = "+"
                                                            },
                                                            new C.Data.IntegerExpression(true)
                                                            {
                                                                new C.Data.Token()
                                                                {
                                                                    Name = "numeral"
                                                                }
                                                            },
                                                            new C.Data.Token()
                                                            {
                                                                Name = ")"
                                                            }
                                                        }
                                                    },
                                                    new C.Data.Token()
                                                    {
                                                        Name = "+"
                                                    },
                                                    new C.Data.IntegerExpression(true)
                                                    {
                                                        new C.Data.Token()
                                                        {
                                                            Name = "numeral"
                                                        }
                                                    },
                                                    new C.Data.Token()
                                                    {
                                                        Name = ")"
                                                    }
                                                }
                                            }
                                        },
                                        new C.Data.Token()
                                        {
                                            Name = ";"
                                        }
                                    }
                                }
                            },
                            new C.Data.Token()
                            {
                                Name = "}"
                            }
                        }
                    }
                }
            };


            // Use this to print the actual tree
            //var CCC = c.Accept(new C.Visitors.TreePrintVisitor());
            //foreach (var line in CCC)
            //{
            //    Debug.WriteLine(line);
            //}

            // Call a method to walk the tree's nodes and test if their names are equal
            TreeAsserter(c, cExpected);
        }
        public string Compile(string source, string path, string tokensJson, int DebugLevel = 0)
        {
            /*
             * System.Console.WriteLine("SOURCE: \n\n\n" + source);
             * System.Console.WriteLine("PATH: \n\n\n" + path);
             * System.Console.WriteLine("TOKENSJSON: \n\n\n" + tokensJson);
             * System.Console.WriteLine("DEBUGLEVEL: \n\n\n" + DebugLevel);
             */
            if (DebugLevel >= 1)
            {
                Console.WriteLine("Compiler running");
            }
            DateTime tStart = DateTime.Now;
            DateTime t1     = DateTime.Now;
            Lexer    lexer  = new Lexer(tokensJson);

            if (DebugLevel >= 1)
            {
                Console.WriteLine("Running Lexer");
            }
            var tokens = lexer.Analyse(source);

            if (DebugLevel >= 1)
            {
                foreach (Token t in tokens)
                {
                    Console.WriteLine(t.Name);
                }
            }

            if (DebugLevel >= 1)
            {
                Console.WriteLine("Lexer on main: " + DateTime.Now.Subtract(t1).TotalMilliseconds + " ms");
            }
            t1 = DateTime.Now;
            if (DebugLevel >= 2)
            {
                Console.WriteLine(string.Join(" ", tokens.Select(t => t.Name)));

                Console.WriteLine("");
                Console.WriteLine("--------------------------------------");
                Console.WriteLine("");
            }

            if (DebugLevel >= 1)
            {
                Console.WriteLine("Running Preprocessor");
            }
            Preprocessor preprocessor = new Preprocessor();

            tokens = preprocessor.Process(lexer, path, tokens);

            if (DebugLevel >= 1)
            {
                Console.WriteLine("Preprocessor: " + DateTime.Now.Subtract(t1).TotalMilliseconds + " ms");
            }
            t1 = DateTime.Now;
            if (DebugLevel >= 2)
            {
                Console.WriteLine("Tokens with imports:");
                Console.WriteLine(string.Join(" ", tokens.Select(t => t.Name)));

                Console.WriteLine("");
                Console.WriteLine("--------------------------------------");
                Console.WriteLine("");
            }

            if (DebugLevel >= 1)
            {
                Console.WriteLine("Running Parser");
            }
            ProgramParser parser          = new ProgramParser();
            var           tokenEnumerator = tokens.Select(t => new Parsing.Data.Token()
            {
                Name = t.Name, Value = t.Value, FileName = t.FileName, Row = t.Row, Column = t.Column
            }).GetEnumerator();

            tokenEnumerator.MoveNext();
            var parseTree = parser.ParseProgram(tokenEnumerator);

            if (DebugLevel >= 1)
            {
                Console.WriteLine("Parser: " + DateTime.Now.Subtract(t1).TotalMilliseconds + " ms");
            }
            t1 = DateTime.Now;
            var parseTreeLines = parseTree.Accept(new Parsing.Visitors.TreePrintVisitor());

            if (DebugLevel >= 2)
            {
                foreach (var line in parseTreeLines)
                {
                    Console.WriteLine(line);
                }

                Console.WriteLine("");
                Console.WriteLine("--------------------------------------");
                Console.WriteLine("");
            }
            if (DebugLevel >= 1)
            {
                Console.WriteLine("Running Ast Translator");
            }
            var astTranslator = new Translation.ProgramToAST.ProgramToASTTranslator();

            AST.Data.AST ast = astTranslator.TranslatetoAST(parseTree) as AST.Data.AST;
            if (ast == null)
            {
                throw new Translation.TranslationException(astTranslator.RuleError);
            }
            if (DebugLevel >= 1)
            {
                Console.WriteLine("tangToAST: " + DateTime.Now.Subtract(t1).TotalMilliseconds + " ms");
            }
            t1 = DateTime.Now;
            var astLines = ast.Accept(new AST.Visitors.TreePrintVisitor());

            if (DebugLevel >= 2)
            {
                foreach (var line in astLines)
                {
                    Console.WriteLine(line);
                }

                Console.WriteLine("");
                Console.WriteLine("--------------------------------------");
                Console.WriteLine("");
            }

            if (DebugLevel >= 1)
            {
                Console.WriteLine("Running C Translator");
            }
            var cTranslator = new Translation.ASTToC.ASTToCTranslator();

            C.Data.C c = cTranslator.Translate(ast) as C.Data.C;
            if (DebugLevel >= 1)
            {
                Console.WriteLine("astToC: " + DateTime.Now.Subtract(t1).TotalMilliseconds + " ms");
            }
            t1 = DateTime.Now;

            var cLines = c.Accept(new C.Visitors.TreePrintVisitor());

            if (DebugLevel >= 2)
            {
                foreach (var line in cLines)
                {
                    Console.WriteLine(line);
                }

                Console.WriteLine("");
                Console.WriteLine("--------------------------------------");
                Console.WriteLine("");
            }

            var cStr = c.Accept(new C.Visitors.TextPrintVisitor());

            if (DebugLevel >= 1)
            {
                foreach (var term in cStr)
                {
                    Console.WriteLine(term);
                }

                Console.WriteLine();
            }

            if (DebugLevel >= 1)
            {
                Console.WriteLine("Compiler run-time: " + DateTime.Now.Subtract(tStart).TotalMilliseconds + " ms");
            }
            return(string.Join("\n", cStr));

            /*// File path relative to where the debug file is located which is in a land far, far away
             * Lexer lexer = new Lexer(AppContext.BaseDirectory + "/../../../../../docs/tang.tokens.json");
             *
             * var tokens = lexer.Analyse(source);
             * Preprocessor preprocessor = new Preprocessor();
             * tokens = preprocessor.Process(lexer, tokens);
             * ProgramParser parser = new ProgramParser();
             * var tokenEnumerator = tokens.Select(t => new Parsing.Data.Token() { Name = t.Name, Value = t.Value }).GetEnumerator();
             * tokenEnumerator.MoveNext();
             * var parseTree = parser.ParseProgram(tokenEnumerator);
             * var astTranslator = new Translation.ProgramToAST.ProgramToASTTranslator();
             * AST.Data.AST ast = astTranslator.Translatep(parseTree) as AST.Data.AST;
             * var cTranslator = new Translation.ASTToC.ASTToCTranslator();
             * C.Data.C c = cTranslator.Translate(ast) as C.Data.C;
             * var cStr = c.Accept(new C.Visitors.TextPrintVisitor());
             *
             * return string.Join("\n", cStr);*/
        }