예제 #1
0
        public void Run()
        {
            ASTVisualizer visualizer = SheInfo.Visualize ? new ASTVisualizer() : null;

            using (var reader = new StreamReader(filePath))
            {
                Lexer             l   = new Lexer(reader);
                SheParser         sp  = new SheParser();
                NestedEnvironment env = new NestedEnvironment();
                Natives.AppendNatives(env);
                while (l.Peek(0) != Token.EOF)
                {
                    ASTree ast = sp.Parse(l);
                    // Console.WriteLine(ast);
                    Console.WriteLine(ast.Eval(env));
                    if (SheInfo.Visualize)
                    {
                        visualizer.Push(ast);
                    }
                }
            }
            if (SheInfo.Visualize)
            {
                visualizer.Visualize($"INTPRT_{SheInfo.StartTime:yyyy-MM-dd-HH-mm-ss}");
            }
        }
예제 #2
0
        public void Start()
        {
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine(startMessage);
            ASTVisualizer visualizer = SheInfo.Visualize ? new ASTVisualizer() : null;

            while (true)
            {
                WriteSystemMessage(prompt);
                string input = ReadSource();
                if (input == null)
                {
                    break;
                }
                Lexer lexer = new Lexer(new StringReader(input));

                /*while (lexer.Peek(0) != Token.EOF)
                 * {
                 *  Console.WriteLine($"{lexer.Peek(0).GetType()}:{lexer.Read()}");
                 * }*/

                SheParser parser = new SheParser();
                ASTree    ast    = parser.Parse(lexer);

                if (SheInfo.Visualize)
                {
                    visualizer.Push(ast);
                }
                //Console.WriteLine(ast);
                Console.WriteLine(ast.Eval(replEnvironment));
                Console.WriteLine();
            }
            if (SheInfo.Visualize)
            {
                visualizer.Visualize($"REPL_{SheInfo.StartTime:yyyy-MM-dd-HH-mm-ss}");
            }
        }
예제 #3
0
        public static void AssertTemplate(string expected, string input, ScriptLang lang = ScriptLang.Default, bool isRoundtripTest = false, bool supportExactRoundtrip = true, object model = null, bool specialLiquid = false, bool expectParsingErrorForRountrip = false, bool supportRoundTrip = true, bool testASTInstead = false)
        {
            bool isLiquid = lang == ScriptLang.Liquid;

            var parserOptions = new ParserOptions()
            {
                LiquidFunctionsToScriban = isLiquid,
            };
            var lexerOptions = new LexerOptions()
            {
                Lang = lang
            };

            if (isRoundtripTest)
            {
                lexerOptions.KeepTrivia = true;
            }

            if (specialLiquid)
            {
                parserOptions.ExpressionDepthLimit = 500;
            }

#if EnableTokensOutput
            {
                Console.WriteLine("Tokens");
                Console.WriteLine("======================================");
                var lexer = new Lexer(input, options: lexerOptions);
                foreach (var token in lexer)
                {
                    Console.WriteLine($"{token.Type}: {token.GetText(input)}");
                }
                Console.WriteLine();
            }
#endif
            string roundtripText = null;

            // We loop first on input text, then on roundtrip
            while (true)
            {
                bool isRoundtrip  = roundtripText != null;
                bool hasErrors    = false;
                bool hasException = false;
                if (isRoundtrip)
                {
                    Console.WriteLine("Roundtrip");
                    Console.WriteLine("======================================");
                    Console.WriteLine(roundtripText);
                    lexerOptions.Lang = lang == ScriptLang.Scientific ? lang : ScriptLang.Default;

                    if (!isLiquid && supportExactRoundtrip)
                    {
                        Console.WriteLine("Checking Exact Roundtrip - Input");
                        Console.WriteLine("======================================");
                        TextAssert.AreEqual(input, roundtripText);
                    }
                    input = roundtripText;
                }
                else
                {
                    Console.WriteLine("Input");
                    Console.WriteLine("======================================");
                    Console.WriteLine(input);
                }

                var template = Template.Parse(input, "text", parserOptions, lexerOptions);

                var result      = string.Empty;
                var resultAsync = string.Empty;
                if (template.HasErrors)
                {
                    hasErrors = true;
                    for (int i = 0; i < template.Messages.Count; i++)
                    {
                        var message = template.Messages[i];
                        if (i > 0)
                        {
                            result += "\n";
                        }
                        result += message;
                    }
                    if (specialLiquid && !isRoundtrip)
                    {
                        throw new InvalidOperationException("Parser errors: " + result);
                    }
                }
                else
                {
                    if (isRoundtripTest)
                    {
                        result = template.ToText();
                    }
                    else
                    {
                        Assert.NotNull(template.Page);

                        if (!isRoundtrip)
                        {
                            // Dumps the roundtrip version
                            var lexerOptionsForTrivia = lexerOptions;
                            lexerOptionsForTrivia.KeepTrivia = true;
                            var templateWithTrivia = Template.Parse(input, "input", parserOptions, lexerOptionsForTrivia);
                            roundtripText = templateWithTrivia.ToText();
                        }

                        try
                        {
                            // Setup a default model context for the tests
                            if (model == null)
                            {
                                var scriptObj = new ScriptObject
                                {
                                    ["page"] = new ScriptObject {
                                        ["title"] = "This is a title"
                                    },
                                    ["user"] = new ScriptObject {
                                        ["name"] = "John"
                                    },
                                    ["product"] = new ScriptObject {
                                        ["title"] = "Orange", ["type"] = "fruit"
                                    },
                                    ["products"] = new ScriptArray()
                                    {
                                        new ScriptObject {
                                            ["title"] = "Orange", ["type"] = "fruit"
                                        },
                                        new ScriptObject {
                                            ["title"] = "Banana", ["type"] = "fruit"
                                        },
                                        new ScriptObject {
                                            ["title"] = "Apple", ["type"] = "fruit"
                                        },
                                        new ScriptObject {
                                            ["title"] = "Computer", ["type"] = "electronics"
                                        },
                                        new ScriptObject {
                                            ["title"] = "Mobile Phone", ["type"] = "electronics"
                                        },
                                        new ScriptObject {
                                            ["title"] = "Table", ["type"] = "furniture"
                                        },
                                        new ScriptObject {
                                            ["title"] = "Sofa", ["type"] = "furniture"
                                        },
                                    }
                                };
                                scriptObj.Import(typeof(SpecialFunctionProvider));
                                model = scriptObj;
                            }

                            // Render sync
                            {
                                var context = NewTemplateContext(lang);
                                context.PushOutput(new TextWriterOutput(new StringWriter()
                                {
                                    NewLine = "\n"
                                }));
                                var contextObj = new ScriptObject();
                                contextObj.Import(model);
                                context.PushGlobal(contextObj);
                                result = template.Render(context);
                            }

                            // Render async
                            {
                                var asyncContext = NewTemplateContext(lang);
                                asyncContext.PushOutput(new TextWriterOutput(new StringWriter()
                                {
                                    NewLine = "\n"
                                }));
                                var contextObj = new ScriptObject();
                                contextObj.Import(model);
                                asyncContext.PushGlobal(contextObj);
                                resultAsync = template.RenderAsync(asyncContext).Result;
                            }
                        }
                        catch (Exception exception)
                        {
                            hasException = true;
                            if (specialLiquid)
                            {
                                throw;
                            }
                            else
                            {
                                result = GetReason(exception);
                            }
                        }
                    }

                    if (testASTInstead)
                    {
                        var astVisualizer = new ASTVisualizer();
                        template.Page.Accept(astVisualizer);
                        result      = astVisualizer.output.ToString();
                        resultAsync = result;
                    }
                }

                var testContext = isRoundtrip ? "Roundtrip - " : String.Empty;
                Console.WriteLine($"{testContext}Result");
                Console.WriteLine("======================================");
                Console.WriteLine(result);
                Console.WriteLine($"{testContext}Expected");
                Console.WriteLine("======================================");
                Console.WriteLine(expected);

                if (isRoundtrip && expectParsingErrorForRountrip)
                {
                    Assert.True(hasErrors, "The roundtrip test is expecting an error");
                    Assert.AreNotEqual(expected, result);
                }
                else
                {
                    TextAssert.AreEqual(expected, result);
                }

                if (!isRoundtrip && !isRoundtripTest && !hasErrors && !hasException)
                {
                    Console.WriteLine("Checking async");
                    Console.WriteLine("======================================");
                    TextAssert.AreEqual(expected, resultAsync);
                }

                if (!supportRoundTrip || isRoundtripTest || isRoundtrip || hasErrors)
                {
                    break;
                }
            }
        }