LNode ReplaceSubstitutionsIn(LNode code) { if (code == null) { return(null); } return(code.ReplaceRecursive(node => { if (node.Calls(S.Substitute, 1)) { // found $subst_expr var label = node.Args[0]; if (label.IsId) { if (_data.ProperLabels.ContainsKey(label.Name)) { return label; } else if (_rules.ContainsKey(label.Name)) { return F.Id(PickVarNameForRuleName(label.Name)); } } if (_data.OtherReferences.TryGetValue(label, -1) > 0) { return F.Id(PickVarNameForLNode(label)); } // Do not change the code in other cases (e.g. the code // block might contain $LI/$LA, handled in a later stage) } return null; })); }
private static Dictionary <Symbol, LNode> ScanForVariables(LNode code) { var nameTable = new Dictionary <Symbol, LNode>(); code.ReplaceRecursive(n => { if (n.IsId) { nameTable[n.Name] = n; } else { LNode id = LNodeExt.GetCaptureIdentifier(n); if (id != null) { if (!nameTable.ContainsKey(n.Name)) { nameTable[id.Name] = n; } return(n); } } return(null); }); return(nameTable); }
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 Pred Translate_any_in_Expr(LNode expr, Context ctx) { // The user typed something of the form "any idNode in subExpr" LNode idNode = expr.Args[0], subExpr = expr.Args[1]; Symbol id = idNode.Name, id2 = (Symbol)("#" + id.Name); any_in_HashLabels.Add(id2); if (id.Name.StartsWith("#")) { any_in_HashLabels.Add(id); } bool isToken = id.Name == "#token" || id2.Name == "#token"; // Scan the rules looking for ones marked with the specified ID. LNode newExpr = null; foreach (var rul in _rules.Values) { if (isToken ? rul.IsToken : rul.Basis.Attrs.Any(attr => attr.Name == id || attr.Name == id2)) { // Given "any foo in (A foo B)", suppose we find rules Foo1, // Foo2 & Foo3 having the attribute 'foo'. We're constructing // the grammar fragment (A Foo1 B | A Foo2 B | A Foo3 B) // i.e. ((A, Foo1, B) | (A, Foo2, B)) | (A, Foo3, B) in LES. bool found = false; LNode subExpr2 = subExpr.ReplaceRecursive(node => { if (node.Equals(idNode)) { found = true; return(node.WithName(rul.Name)); } return(null); }); if (!found) { _sink.Error(subExpr, "'any': expected '{0}' somewhere in the expression following 'in'", id); break; } if (newExpr == null) { newExpr = subExpr2; } else { newExpr = F.Call(S.Div, newExpr, subExpr2); } } } if (newExpr == null) { _sink.Warning(expr, "'any': there are no rules marked with the attribute '{0}', so this item has no effect", id); newExpr = F.Tuple(); } return(NodeToPred(newExpr, ctx)); }
internal static Symbol DecodeSubstitutionExpr(LNode expr, out LNode condition, out bool isParams, out bool refExistingVar) { condition = null; isParams = false; refExistingVar = false; if (expr.Calls(S.Substitute, 1)) { LNode id = expr.Args[0]; if (id.AttrNamed(S.Params) != null) { isParams = true; } else if (id.Calls(S.DotDotDot, 1) || id.Calls(S.DotDot, 1)) { isParams = true; id = id.Args[0]; } if (id.AttrNamed(S.Ref) != null) { refExistingVar = true; } if (id.Calls(S.IndexBracks, 2)) { // very old style condition = id.Args[1]; id = id.Args[0]; } else { while (id.Calls(S.And, 2) || id.Calls(S.When, 2)) { // old style `&&` and new style `when` condition = condition == null ? id.Args[1] : LNode.Call(CodeSymbols.And, LNode.List(id.Args[1], condition)).SetStyle(NodeStyle.Operator); id = id.Args[0]; } } if (condition != null) { condition = condition.ReplaceRecursive(n => n.IsIdNamed(S._HashMark) ? id : null); } if (!id.IsId) { return(null); } return(id.Name); } return(null); }
static bool ReplaceContractUnderscore(ref LNode condition, LNode variableName) { bool hasUnderscore = false; LNode old = condition; condition = condition.ReplaceRecursive(n => { if (n.IsIdNamed(__) || n.IsIdNamed(_hash)) { hasUnderscore = true; return(variableName); } return(null); }); return(hasUnderscore); }
static LNode ReplaceCaptures(LNode node, MMap <Symbol, LNode> captures) { if (captures.Count != 0) { // TODO: EXPAND SPLICES! Generally it works anyway though because // the macro processor has built-in support for #splice. return(node.ReplaceRecursive(n => { LNode sub, cap; if (n.Calls(S.Substitute, 1) && (sub = n.Args.Last).IsId && captures.TryGetValue(sub.Name, out cap)) { return cap; } return null; })); } return(node); }
internal static Symbol GetSubstitutionVar(LNode expr, out LNode condition, out bool isParams, out bool refExistingVar) { condition = null; isParams = false; refExistingVar = false; if (expr.Calls(S.Substitute, 1)) { LNode id = expr.Args[0]; if (id.AttrNamed(S.Params) != null) { isParams = true; } else if (id.Calls(S.DotDot, 1)) { isParams = true; id = id.Args[0]; } if (id.AttrNamed(S.Ref) != null) { refExistingVar = true; } if (id.Calls(S.IndexBracks, 2)) { condition = id.Args[1]; id = id.Args[0]; } else if (id.ArgCount == 1) { condition = id.Args[0]; id = id.Target; } if (condition != null) { condition = condition.ReplaceRecursive(n => n.IsIdNamed(S._HashMark) ? id : null); } if (!id.IsId) { return(null); } return(id.Name); } return(null); }
/// <summary>Finds capture variables like <c>$x</c> and replaces them with values /// from <c>captures</c> (e.g. <c>captures[(Symbol)"x"]</c> for <c>$x</c>)</summary> public static LNode ReplaceCaptures(LNode outputSpec, MMap <Symbol, LNode> captures) { if (captures.Count != 0) { // TODO: EXPAND SPLICES! Generally it works anyway though because // the macro processor has built-in support for #splice. return(outputSpec.ReplaceRecursive(n => { LNode id, cap; if ((id = LNodeExt.GetCaptureIdentifier(n)) != null) { if (captures.TryGetValue(id.Name, out cap)) { return cap; } } return null; })); } return(outputSpec); }
void VisitCode(Pred pred, LNode code) { if (code == null) { return; } code.ReplaceRecursive(node => { if (node.Calls(S.Substitute, 1)) { var arg = node.Args[0]; PredsUsingSubstitution.Add(pred); if (arg.IsId && _rules.ContainsKey(arg.Name)) { RulesReferenced.Add(_rules[arg.Name]); } else { OtherReferences[arg] = 0; } } return(null); // search only, no replace }); }
LNode GetAndPredCode(AndPred pred, int lookaheadAmt, LNode laVar) { if (pred.Pred is LNode) { LNode code = (LNode)pred.Pred; // replace $LI and $LA return(code.ReplaceRecursive(arg => { if (arg.Equals(AndPred.SubstituteLA)) // $LA { return (LNode)laVar; } if (arg.Equals(AndPred.SubstituteLI)) // $LI { return (LNode)F.Literal(lookaheadAmt); } return null; })); } else { Pred synPred = (Pred)pred.Pred; // Buffalo sumBuffalo = (Buffalo)buffalo.Buffalo; Rule recogRule = LLPG.GetRecognizerRule(synPred); recogRule.TryWrapperNeeded(); if (synPred is RuleRef) { return(CGH.CallTryRecognizer(synPred as RuleRef, lookaheadAmt)); } else { // Use a temporary RuleRef for this RuleRef rref = new RuleRef(synPred.Basis, recogRule); return(CGH.CallTryRecognizer(rref, lookaheadAmt)); } } }
static LNode ReplaceCaptures(LNode node, MMap<Symbol, LNode> captures) { if (captures.Count != 0) { // TODO: EXPAND SPLICES! Generally it works anyway though because // the macro processor has built-in support for #splice. return node.ReplaceRecursive(n => { LNode sub, cap; if (n.Calls(S.Substitute, 1) && (sub = n.Args.Last).IsId && captures.TryGetValue(sub.Name, out cap)) return cap; return null; }); } return node; }
LNode ReplaceSubstitutionsIn(LNode code) { if (code == null) return null; return code.ReplaceRecursive(node => { if (node.Calls(S.Substitute, 1)) { // found $subst_expr var label = node.Args[0]; if (label.IsId) { if (_data.ProperLabels.ContainsKey(label.Name)) return label; else if (_rules.ContainsKey(label.Name)) return F.Id(PickVarNameForRuleName(label.Name)); } if (_data.OtherReferences.TryGetValue(label, -1) > 0) { return F.Id(PickVarNameForLNode(label)); } // Do not change the code in other cases (e.g. the code // block might contain $LI/$LA, handled in a later stage) } return null; }); }
internal static Symbol GetSubstitutionVar(LNode expr, out LNode condition, out bool isParams, out bool refExistingVar) { condition = null; isParams = false; refExistingVar = false; if (expr.Calls(S.Substitute, 1)) { LNode id = expr.Args[0]; if (id.AttrNamed(S.Params) != null) isParams = true; else if (id.Calls(S.DotDotDot, 1) || id.Calls(S.DotDot, 1)) { isParams = true; id = id.Args[0]; } if (id.AttrNamed(S.Ref) != null) refExistingVar = true; if (id.Calls(S.IndexBracks, 2)) { condition = id.Args[1]; id = id.Args[0]; } else while (id.Calls(S.And, 2)) { condition = condition == null ? id.Args[1] : LNode.Call(CodeSymbols.And, LNode.List(id.Args[1], condition)).SetStyle(NodeStyle.Operator); id = id.Args[0]; } if (condition != null) condition = condition.ReplaceRecursive(n => n.IsIdNamed(S._HashMark) ? id : null); if (!id.IsId) return null; return id.Name; } return null; }
void VisitCode(Pred pred, LNode code) { if (code == null) return; code.ReplaceRecursive(node => { if (node.Calls(S.Substitute, 1)) { var arg = node.Args[0]; PredsUsingSubstitution.Add(pred); if (arg.IsId && _rules.ContainsKey(arg.Name)) RulesReferenced.Add(_rules[arg.Name]); else OtherReferences[arg] = 0; } return null; // search only, no replace }); }
public static LNode SetOrCreateMember(LNode fn, IMessageSink sink) { // Expecting #fn(Type, Name, #(args), {body}) if (fn.ArgCount < 3 || !fn.Args[2].Calls(S.AltList)) { return(null); } var args = fn.Args[2].Args; LNodeList propOrFieldDecls = LNodeList.Empty; Dictionary <Symbol, LNode> assignments = null; for (int i = 0; i < args.Count; i++) { var arg = args[i]; Symbol relevantAttribute, fieldName, paramName; LNode plainArg, propOrFieldDecl; if (DetectSetOrCreateMember(arg, out relevantAttribute, out fieldName, out paramName, out plainArg, out propOrFieldDecl)) { if (fn.ArgCount < 4) { return(Reject(sink, arg, Localize.Localized("'{0}': to set or create a field or property, the method must have a body in braces {{}}.", relevantAttribute))); } args[i] = plainArg; assignments = assignments ?? new Dictionary <Symbol, LNode>(); assignments[fieldName] = F.Id(paramName); if (propOrFieldDecl != null) { propOrFieldDecls.Add(propOrFieldDecl); } } } if (assignments != null) // if this macro has been used... { var parts = fn.Args; parts[2] = parts[2].WithArgs(args); var body = parts[3]; // Ensure the method has a normal braced body if (!body.Calls(S.Braces)) { if (parts[0].IsIdNamed(S.Void)) { body = F.Braces(body); } else { body = F.Braces(F.Call(S.Return, body)); } } // In case one constructor calls another, we have to ensure that the // assignments are inserted _after_ that call, and if the constructor // call refers to properties or fields that will be set, we must remap // those references onto parameters, e.g. // this(public int X) { base(X); } => this(int x) { base(x); X = x; } var bodyStmts = body.Args; int indexAtWhichToDoAssignments = 0; if (fn.Calls(S.Constructor)) { LNode baseCall = bodyStmts[0, LNode.Missing]; if (baseCall.Calls(S.Base) || baseCall.Calls(S.This)) { bodyStmts[0] = baseCall.ReplaceRecursive(n => { LNode param; if (n.IsId && assignments.TryGetValue(n.Name, out param)) { return(param); } return(null); }); indexAtWhichToDoAssignments = 1; } } // Insert assignment statements parts[3] = body.WithArgs(bodyStmts.InsertRange(indexAtWhichToDoAssignments, assignments.Select(p => { if (p.Key == p.Value.Name) { return(F.Call(S.Assign, F.Dot(F.@this, F.Id(p.Key)), p.Value)); } else { return(F.Call(S.Assign, F.Id(p.Key), p.Value)); } }).ToList())); // Return output code fn = fn.WithArgs(parts); if (propOrFieldDecls.IsEmpty) { return(fn); } else { propOrFieldDecls.Add(fn); return(F.Call(S.Splice, propOrFieldDecls)); } } return(null); }
internal static Symbol GetSubstitutionVar(LNode expr, out LNode condition, out bool isParams, out bool refExistingVar) { condition = null; isParams = false; refExistingVar = false; if (expr.Calls(S.Substitute, 1)) { LNode id = expr.Args[0]; if (id.AttrNamed(S.Params) != null) isParams = true; else if (id.Calls(S.DotDot, 1)) { isParams = true; id = id.Args[0]; } if (id.AttrNamed(S.Ref) != null) refExistingVar = true; if (id.Calls(S.IndexBracks, 2)) { condition = id.Args[1]; id = id.Args[0]; } else if (id.ArgCount == 1) { condition = id.Args[0]; id = id.Target; } if (condition != null) condition = condition.ReplaceRecursive(n => n.IsIdNamed(S._HashMark) ? id : null); if (!id.IsId) return null; return id.Name; } return null; }
/// <summary>Finds capture variables like <c>$x</c> and replaces them with values /// from <c>captures</c> (e.g. <c>captures[(Symbol)"x"]</c> for <c>$x</c>)</summary> public static LNode ReplaceCaptures(LNode outputSpec, MMap<Symbol, LNode> captures) { if (captures.Count != 0) { // TODO: EXPAND SPLICES! Generally it works anyway though because // the macro processor has built-in support for #splice. return outputSpec.ReplaceRecursive(n => { LNode id, cap; if ((id = LNodeExt.GetCaptureIdentifier(n)) != null) { if (captures.TryGetValue(id.Name, out cap)) return cap; } return null; }); } return outputSpec; }
private static Dictionary<Symbol, LNode> ScanForVariables(LNode code) { var nameTable = new Dictionary<Symbol, LNode>(); code.ReplaceRecursive(n => { if (n.IsId) nameTable[n.Name] = n; else { LNode id = LNodeExt.GetCaptureIdentifier(n); if (id != null) { if (!nameTable.ContainsKey(n.Name)) nameTable[id.Name] = n; return n; } } return null; }); return nameTable; }