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}"); } }
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}"); } }
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; } } }