protected override MessageHolder Test(Mode mode, int errorsExpected, LNodePrinterOptions printerOptions, string text, params LNode[] expected) { var messages = new MessageHolder(); var les3 = Les3LanguageService.Value; var results = les3.Parse(text, messages, mode == Mode.Expr ? ParsingMode.Expressions : ParsingMode.Statements, true).ToList(); if (messages.List.Count != System.Math.Max(errorsExpected, 0)) { messages.WriteListTo(ConsoleMessageSink.Value); int errorCount = messages.List.Count(msg => msg.Severity >= Severity.Error); AreEqual(errorsExpected, errorCount, "Error count was {0} for «{1}»", errorCount, text); // fail } for (int i = 0; i < expected.Length; i++) { LNode expect = expected[i], actual = results.TryGet(i, null); if (!expect.Equals(actual, LNode.CompareMode.TypeMarkers)) { var options = new Les3PrinterOptions { PrintTriviaExplicitly = true, IndentString = " " }; AreEqual(les3.Print(expect, null, null, options), les3.Print(actual, null, null, options)); AreEqual(expect, actual); Fail("{0} has a different type marker than {1}", expect, actual); } } AreEqual(expected.Length, results.Count, "Got more result nodes than expected"); return(messages); }
public virtual LNode VisitInput(LNode stmt, IMessageSink sink) { LNode aliasSet; if ((stmt.Calls(_alias, 1) || stmt.CallsMin(S.Alias, 1)) && (aliasSet = stmt.Args[0]).Calls(S.Assign, 2)) { IEnumerable <KeyValuePair <LNode, LNode> > q; LNode alias = aliasSet.Args[0], replacement = aliasSet.Args[1], old; if (_definedAliases.TryGetValue(alias, out old)) { if (stmt.AttrNamed(S.Partial) == null || !old.Equals(replacement)) { sink.Warning(alias, "Redefinition of alias '{0}'", alias); } } else if ((q = _definedAliases.Where(pair => replacement.Equals(pair.Value))).Any()) { sink.Warning(replacement, "Aliases '{0}' and '{1}' have the same replacement value", q.First().Key, alias); } _definedAliases[alias] = replacement; return(LNode.Call(S.Splice, VList <LNode> .Empty)); // erase alias from output } return(null); }
public void Comparisons() { IsTrue(F.Attr(Foo, zero).Equals(F.Attr(Foo, zero))); IsFalse(F.Attr(Foo, zero).Equals(F.Attr(a, zero))); IsFalse(zero.Equals(F.Attr(Foo, zero))); IsTrue(F.Attr(Foo, a).Equals(F.Attr(Foo, a))); IsFalse(F.Attr(Foo, a).Equals(F.Attr(Foo, b))); IsFalse(a.Equals(F.Attr(Foo, a))); }
protected override void Stmt(string text, LNode expected, Action <EcsPrinterOptions> configure = null, Mode mode = Mode.Both) { bool exprMode = (mode & Mode.Expression) != 0; if ((mode & (Mode.ParserTest | Mode.ExpectAndDropParserError)) == 0) { return; } var sink = (mode & Mode.ExpectAndDropParserError) != 0 ? new MessageHolder() : (IMessageSink)ConsoleMessageSink.Value; using (Token.SetToStringStrategy(TokenExt.ToString)) // debugging aid { // This is the easy way: // LNode result = EcsLanguageService.Value.ParseSingle(text, sink, exprMode ? ParsingMode.Expressions : ParsingMode.Statements, preserveComments: true); // But to make debugging easier, I'll do it the long way: ILexer <Token> lexer = EcsLanguageService.Value.Tokenize(new UString(text), "", sink); var preprocessed = new EcsPreprocessor(lexer, true); var treeified = new TokensToTree(preprocessed, false); var parser = new EcsParser(treeified.Buffered(), lexer.SourceFile, sink, null); LNodeList results = exprMode ? LNode.List(parser.ExprStart(false)) : LNode.List(parser.ParseStmtsGreedy()); // Inject comments var injector = new EcsTriviaInjector(preprocessed.TriviaList, preprocessed.SourceFile, (int)TokenType.Newline, "/*", "*/", "//", (mode & Mode.Expression) == 0); results = LNode.List(injector.Run(results.GetEnumerator()).ToList()); LNode result = results.AsLNode(S.Splice); AreEqual(TokenType.EOF, parser.LT0.Type(), string.Format("Parser stopped before EOF at [{0}] in {1}", parser.LT0.StartIndex, text)); if ((mode & Mode.IgnoreTrivia) != 0) { result = result.ReplaceRecursive(n => n.IsTrivia ? Maybe <LNode> .NoValue : n, LNode.ReplaceOpt.ProcessAttrs).Value; } if (sink is MessageHolder) { ((MessageHolder)sink).WriteListTo(TraceMessageSink.Value); GreaterOrEqual(((MessageHolder)sink).List.Count(m => m.Severity >= Severity.Error), 1, "Expected an error but got none for " + text); if (expected == null) { return; } } if (!expected.Equals(result, LNode.CompareMode.TypeMarkers)) { if ((mode & Mode.CompareAsLes) != 0) { using (LNode.SetPrinter(Syntax.Les.Les3LanguageService.Value)) AreEqual(expected.ToString(), result.ToString()); } else { AreEqual(expected, result); } Fail("{0} has a different type marker than {1}", expected, result); } } }
private void ExpectSavedRange(List <Triplet <ILNode, IndexRange, int> > ranges, string output, LNode node, string expectedSubstring) { foreach (var pair in ranges) { // Subtlety: if(node==pair.A) doesn't work for typical Target nodes, which // are regenerated each time Target is called; use Equals instead if (node.Equals(pair.A)) { AreEqual(expectedSubstring, output.Substring(pair.B.StartIndex, pair.B.Length)); return; } } Fail("Saved range not found for {0}", node); }
public static LNode TreeEqual(LNode node, IMessageSink sink) { var a = node.Args; if (a.Count < 2) { return(null); } LNode left = a[0]; for (int i = 1; i < a.Count; i++) { if (!left.Equals(a[i])) { return(F.Literal(G.BoxedFalse)); } } return(F.Literal(G.BoxedTrue)); }
public static LNode TreeEqual(LNode node, IMacroContext context) { if (node.ArgCount < 2) { return(null); } node = context.PreProcessChildren(); var args = node.Args; LNode left = args[0]; for (int i = 1; i < args.Count; i++) { if (!left.Equals(args[i])) { return(F.Literal(G.BoxedFalse)); } } return(F.Literal(G.BoxedTrue)); }
public override Pred CodeToPred(LNode expr, ref string errorMsg) { Debug.Assert(!expr.IsIdNamed(EOF.Name) || expr.Equals(EOF)); if (expr.IsCall && expr.Name != S.Dot && expr.Name != S.Of) { errorMsg = "Unrecognized expression. Treating this as a terminal: " + expr.ToString(); // warning } expr = ResolveAlias(expr); PGNodeSet set; if (expr.IsIdNamed(_underscore)) { set = PGNodeSet.AllExceptEOF; } else { set = new PGNodeSet(expr); } return(new TerminalPred(expr, set, true)); }
public override Pred CodeToTerminalPred(LNode expr, ref string errorMsg) { Debug.Assert(!expr.IsIdNamed(EOF.Name) || expr.Equals(EOF)); if (expr.IsCall && expr.Name != S.Dot && expr.Name != S.Of) { errorMsg = "Unrecognized expression. Treating this as a terminal: " + expr.ToString(); // warning } var expr2 = ResolveAlias(expr); PGNodeSet set; if (expr2.IsIdNamed(_underscore)) { set = PGNodeSet.AllExceptEOF; } else { set = new PGNodeSet(expr2); } // bug fix 2015-07: must use expr, not expr2, as TerminalPred's Basis // (wrong Basis breaks error locations, and $A in code blocks if A is an alias) return(new TerminalPred(expr, set, true)); }
public static LNode QuoteOne(LNode node, bool substitutions) { if (node.Equals(LNode.InParensTrivia)) { return(LNode_InParensTrivia); } if (node.Equals(LNode.Missing)) { return(LNode_Missing); } VList <LNode> creationArgs = new VList <LNode>(); // Translate attributes (if any) var attrList = MaybeQuoteList(node.Attrs, substitutions); if (attrList != null) { creationArgs.Add(attrList); } LNode result; switch (node.Kind) { case LNodeKind.Literal: // => F.Literal(value) creationArgs.Add(node.WithoutAttrs()); result = F.Call(LNode_Literal, creationArgs); break; case LNodeKind.Id: // => F.Id(string), F.Id(CodeSymbols.Name) creationArgs.Add(QuoteSymbol(node.Name)); result = F.Call(LNode_Id, creationArgs); break; default: // NodeKind.Call => F.Dot(...), F.Of(...), F.Call(...), F.Braces(...) if (substitutions && node.Calls(S.Substitute, 1)) { result = node.Args[0]; if (attrList != null) { if (result.IsCall) { result = LNode.InParens(result); } result = F.Call(F.Dot(result, Id_PlusAttrs), attrList); } } /*else if (node.Calls(S.Braces)) // F.Braces(...) * result = F.Call(LNode_Braces, node.Args.SmartSelect(arg => QuoteOne(arg, substitutions))); * else if (node.Calls(S.Dot) && node.ArgCount.IsInRange(1, 2)) * result = F.Call(LNode_Dot, node.Args.SmartSelect(arg => QuoteOne(arg, substitutions))); * else if (node.Calls(S.Of)) * result = F.Call(LNode_Of, node.Args.SmartSelect(arg => QuoteOne(arg, substitutions)));*/ else // General case: F.Call(<Target>, <Args>) { if (node.Target.IsId) { creationArgs.Add(QuoteSymbol(node.Name)); } else { creationArgs.Add(QuoteOne(node.Target, substitutions)); } var argList = MaybeQuoteList(node.Args, substitutions); if (argList != null) { creationArgs.Add(argList); } result = F.Call(LNode_Call, creationArgs); } // Note: don't preserve prefix notation because if $op is +, // we want $op(x, y) to generate code for x + y (there is no // way to express this with infix notation.) if (node.BaseStyle != NodeStyle.Default && node.BaseStyle != NodeStyle.PrefixNotation) { result = F.Call(F.Dot(result, F.Id("SetStyle")), F.Dot(F.Id("NodeStyle"), F.Id(node.BaseStyle.ToString()))); } break; } return(result); }
public LNode Quote(LNode node) { // TODO: When quoting, ignore injected trivia (trivia with the TriviaInjected flag) if (node.Equals(LNode.InParensTrivia)) { return(LNode_InParensTrivia); } if (node.Equals(LNode.Missing)) { return(LNode_Missing); } LNodeList creationArgs = new LNodeList(); // Translate attributes (if any) var attrList = MaybeQuoteList(node.Attrs, isAttributes: true); if (attrList != null) { creationArgs.Add(attrList); } LNode result; switch (node.Kind) { case LNodeKind.Literal: // => F.Literal(value) creationArgs.Add(node.WithoutAttrs()); result = F.Call(LNode_Literal, creationArgs); break; case LNodeKind.Id: // => F.Id(string), F.Id(CodeSymbols.Name) creationArgs.Add(QuoteSymbol(node.Name)); result = F.Call(LNode_Id, creationArgs); break; default: // NodeKind.Call => F.Dot(...), F.Of(...), F.Call(...), F.Braces(...) bool preserveStyle = true; if (_doSubstitutions && node.Calls(S.Substitute, 1)) { preserveStyle = false; result = node.Args[0]; if (attrList != null) { if (result.IsCall) { result = result.InParens(); } result = F.Call(F.Dot(result, Id_PlusAttrs), attrList); } } else if (!_ignoreTrivia && node.ArgCount == 1 && node.TriviaValue != NoValue.Value && node.Target.IsId) { // LNode.Trivia(Symbol, object) result = F.Call(LNode_Trivia, QuoteSymbol(node.Name), F.Literal(node.TriviaValue)); } /*else if (node.Calls(S.Braces)) // F.Braces(...) * result = F.Call(LNode_Braces, node.Args.SmartSelect(arg => QuoteOne(arg, substitutions))); * else if (node.Calls(S.Dot) && node.ArgCount.IsInRange(1, 2)) * result = F.Call(LNode_Dot, node.Args.SmartSelect(arg => QuoteOne(arg, substitutions))); * else if (node.Calls(S.Of)) * result = F.Call(LNode_Of, node.Args.SmartSelect(arg => QuoteOne(arg, substitutions)));*/ else { // General case: F.Call(<Target>, <Args>) if (node.Target.IsId) { creationArgs.Add(QuoteSymbol(node.Name)); } else { creationArgs.Add(Quote(node.Target)); } var argList = MaybeQuoteList(node.Args); if (argList != null) { creationArgs.Add(argList); } result = F.Call(LNode_Call, creationArgs); } // Note: don't preserve prefix notation because if $op is +, // we want $op(x, y) to generate code for x + y (there is no // way to express this with infix notation.) if (preserveStyle && node.BaseStyle != NodeStyle.Default && node.BaseStyle != NodeStyle.PrefixNotation) { result = F.Call(F.Dot(result, F.Id("SetStyle")), F.Dot(F.Id("NodeStyle"), F.Id(node.BaseStyle.ToString()))); } break; } return(result); }