public LNode GenerateParserCode() { _pg = new LLParserGenerator(new GeneralCodeGenHelper(F.Id("TT"), true) { MatchType = F.Int32 }, MessageSink.Console); // Just do whitespace-agnostic LES at first #if false int *$ int?$ int[]
private static void ApplyOptions(LNode node, LLParserGenerator lllpg, IMacroContext sink, IEnumerable <Rule> rules) { foreach (var pair in MacroContext.GetOptions(node.Attrs)) { LNode key = pair.Key; object value = pair.Value != null ? pair.Value.Value : null; switch (key.Name.Name) { case "FullLLk": SetOption <bool>(sink, key, value ?? G.BoxedTrue, v => lllpg.FullLLk = v); break; case "Verbosity": SetOption <int>(sink, key, value, v => lllpg.Verbosity = v); break; case "NoDefaultArm": SetOption <bool>(sink, key, value ?? G.BoxedTrue, v => lllpg.NoDefaultArm = v); break; case "LL": case "DefaultK": case "k": case "K": // [LL(k)] is preferred SetOption <int>(sink, key, value, v => lllpg.DefaultK = v); break; case "AddComments": SetOption <bool>(sink, key, value ?? G.BoxedTrue, v => lllpg.AddComments = v); break; case "AddCsLineDirectives": SetOption <bool>(sink, key, value ?? G.BoxedTrue, v => lllpg.AddCsLineDirectives = v); break; case "PrematchByDefault": SetOption <bool>(sink, key, value ?? G.BoxedTrue, v => lllpg.PrematchByDefault = v); break; default: if (!key.IsTrivia) { sink.Error(key, "Unrecognized attribute. LLLPG supports the following options: " + "FullLLk(bool), Verbosity(0..3), NoDefaultArm(bool), DefaultK(1..9), AddComments(bool), AddCsLineDirectives(bool), and PrematchByDefault(bool)"); } break; } } }
private static void ApplyOptions(LNode node, LLParserGenerator lllpg, IMessageSink sink) { for (int i = 0; i < node.Attrs.Count; i++) { var attr = node.Attrs[i]; switch (attr.Name.Name) { case "FullLLk": ReadOption <bool>(sink, attr, v => lllpg.FullLLk = v, true); break; case "Verbosity": ReadOption <int>(sink, attr, v => lllpg.Verbosity = v, null); break; case "NoDefaultArm": ReadOption <bool>(sink, attr, v => lllpg.NoDefaultArm = v, true); break; case "DefaultK": case "k": case "K": case "LL": ReadOption <int>(sink, attr, v => lllpg.DefaultK = v, null); break; case "AddComments": ReadOption <bool>(sink, attr, v => lllpg.AddComments = v, true); break; case "AddCsLineDirectives": ReadOption <bool>(sink, attr, v => lllpg.AddCsLineDirectives = v, true); break; default: sink.Write(Severity.Error, attr, "Unrecognized attribute. LLLPG supports the following options: " + "FullLLk(bool), Verbosity(0..3), NoDefaultArm(bool), DefaultK(1..9), AddComments(bool), and AddCsLineDirectives(bool)"); break; } } }
public GenerateCodeVisitor(LLParserGenerator llpg) { LLPG = llpg; F = new LNodeFactory(llpg._sourceFile); _classBody = llpg._classBody; }
public void SetUp() { LNode.Printer = EcsNodePrinter.Printer; _pg = new LLParserGenerator(new IntStreamCodeGenHelper()); _pg.Sink = new MessageSinkFromDelegate(OutputMessage); _messageCounter = 0; _expectingOutput = false; _file = new EmptySourceFile("LlpgTests.cs"); }
public static LNode run_LLLPG(LNode node, IMacroContext context) { node = context.PreProcessChildren(); IPGCodeGenHelper helper; LNode body; bool hasBraces = true; if (node.ArgCount != 2 || (helper = node.Args[0].Value as IPGCodeGenHelper) == null || !(hasBraces = (body = node.Args[1]).Calls(S.Braces))) { string msg = Localize.Localized("Expected run_LLLPG(helper_object, {...})."); if (hasBraces) { msg = " " + Localize.Localized("An auxiliary macro is required to supply the helper object."); } context.Write(Severity.Note, node, msg); return(null); } helper = helper ?? new GeneralCodeGenHelper(); var rules = new List <Pair <Rule, LNode> >(); var stmts = new List <LNode>(); // Let helper preprocess the code if it wants to foreach (var stmt in body.Args) { var stmt2 = helper.VisitInput(stmt, context) ?? stmt; if (stmt2.Calls(S.Splice)) { stmts.AddRange(stmt2.Args); } else { stmts.Add(stmt2); } } // Find rule definitions, create Rule objects for (int i = 0; i < stmts.Count; i++) { LNode stmt = stmts[i]; bool isToken; if ((isToken = stmt.Calls(_hash_token, 4)) || stmt.Calls(_hash_rule, 4)) { LNode basis = stmt.WithTarget(S.Fn); LNode methodBody = stmt.Args.Last; // basis has the form #fn(ReturnType, Name, #(Args)) var rule = MakeRuleObject(isToken, ref basis, context); if (rule != null) { var prev = rules.FirstOrDefault(pair => pair.A.Name == rule.Name); if (prev.A != null) { context.Sink.Error(rule.Basis, "The rule name «{0}» was used before at {1}", rule.Name, prev.A.Basis.Range.Start); } else { rules.Add(Pair.Create(rule, methodBody)); } stmts[i] = null; // remove processed rules from the list } } else { if (stmt.Calls(_rule) || stmt.Calls(_token)) { context.Sink.Error(stmt, "A rule should have the form rule(Name(Args)::ReturnType, @{...})"); } } } if (rules.Count == 0) { context.Sink.Warning(node, "No grammar rules were found in LLLPG block"); } // Parse the rule definitions (now that we know the names of all the // rules, we can decide if an Id refers to a rule; if not, it's assumed // to refer to a terminal). new StageTwoParser(helper, context).Parse(rules); // Process the grammar & generate code var lllpg = new LLParserGenerator(helper, context); ApplyOptions(node, lllpg, context, rules.Select(p => p.Key)); // Read attributes such as [DefaultK(3)] foreach (var pair in rules) { lllpg.AddRule(pair.A); } // TODO: change lllpg so we can interleave generated code with other // user code, to preserve the order of declarations in the original code. var results = lllpg.Run(node.Source); return(F.Call(S.Splice, stmts.Where(p => p != null).Concat(results.Args))); }
int _ruleDepth = 0; // Used to avoid stack overflow, which crashes VS in SFG public ApplyPrematchVisitor(LLParserGenerator llpg) { LLPG = llpg; }
public PrematchAnalysisVisitor(LLParserGenerator llpg) { LLPG = llpg; Anything = LLPG.CodeGenHelper.EmptySet.Inverted(); _apply = new ApplyPrematchVisitor(llpg); }
public PredictionAnalysisVisitor(LLParserGenerator llpg) { LLPG = llpg; }