public override void Visit(TerminalPred term) { if (_recognizerMode) _target.Add(CGH.GenerateMatch(term.Set, false, _recognizerMode)); else if (term.Set.ContainsEverything || (term.Prematched ?? false)) _target.Add(term.AutoSaveResult(CGH.GenerateSkip(term.ResultSaver != null))); else _target.Add(term.AutoSaveResult(CGH.GenerateMatch(term.Set, term.ResultSaver != null, false))); }
Pred NodeToPredCore(LNode expr, Context ctx = Context.Rule) { if (expr.IsCall) { bool slash = false, not; var name = expr.Name; if (name == S.Tuple) { // sequence: (a, b, c) if (expr.Calls(S.Tuple, 1)) return NodeToPred(expr.Args[0], ctx); return ArgsToSeq(expr, ctx); } else if (name == S.Braces) { // Just code: use an empty sequence var seq = new Seq(expr); seq.PostAction = RemoveBraces(expr); return seq; } else if (expr.Calls(S.OrBits, 2) || (slash = expr.Calls(S.Div, 2))) { // alternatives: a | b, a || b, a / b LNode lhs = expr.Args[0], rhs = expr.Args[1]; BranchMode lhsMode, rhsMode; Pred left = BranchToPred(lhs, out lhsMode, ctx); Pred right = BranchToPred(rhs, out rhsMode, ctx); return Pred.Or(left, right, slash, expr, lhsMode, rhsMode, _sink); } else if (expr.Calls(_Star, 1) || expr.Calls(_Plus, 1) || expr.Calls(_Opt, 1)) { // loop (a+, a*) or optional (a?) return TranslateLoopExpr(expr, ctx); } else if (expr.Calls(_Gate, 1) || expr.Calls(_EqGate, 1)) { // => foo (LES-based parser artifact) return new Gate(expr, new Seq(F.Missing), NodeToPred(expr.Args[0], Context.GateRight)) { IsEquivalency = expr.Calls(_EqGate) }; } else if (expr.Calls(_Gate, 2) || expr.Calls(_EqGate, 2)) { if (ctx == Context.GateLeft) _sink.Error(expr, "Cannot use a gate in the left-hand side of another gate"); return new Gate(expr, NodeToPred(expr.Args[0], Context.GateLeft), NodeToPred(expr.Args[1], Context.GateRight)) { IsEquivalency = expr.Calls(_EqGate) }; } else if ((not = expr.Calls(_AndNot, 1)) || expr.Calls(_And, 1)) { expr = expr.Args[0]; var subpred = AutoNodeToPred(expr, Context.And); LNode subexpr = subpred as LNode, subexpr0 = subexpr; bool local = false; if (subexpr != null) { local = true; if ((subexpr = subexpr.WithoutAttrNamed(_Hoist)) != subexpr0) local = false; // also recognize [Local], which was not the default until v1.9.1 subexpr = subexpr.WithoutAttrNamed(_Local); } // Extract error message for Check(), if provided. string errorString = null; if (subexpr != null) subexpr = subexpr.WithAttrs(n => { if (n.Value is string) { errorString = (string)n.Value; return NoValue.Value; // drop attribute from output } else if (n.IsIdNamed("NoCheck")) { errorString = ""; return NoValue.Value; } return n; }); return new AndPred(expr, subexpr ?? subpred, not, local) { CheckErrorMessage = errorString }; } else if (expr.Calls(S.NotBits, 1)) { var subpred = NodeToPred(expr.Args[0], ctx); if (subpred is TerminalPred) { var term = (TerminalPred)subpred; term.Set = term.Set.Inverted().WithoutEOF(); return term; } else { _sink.Error(expr, "The set-inversion operator ~ can only be applied to a single terminal, not a '{0}'", subpred.GetType().Name); return subpred; } } else if (expr.Calls(_Any, 2) && expr.Args[0].IsId) { return Translate_any_in_Expr(expr, ctx); } else if ((name.Name.EndsWith(":") || name.Name.EndsWith("=")) && expr.ArgCount == 2) { return TranslateLabeledExpr(expr, ctx); } } // expr is an Id, literal, or non-special call Rule rule = TryGetRule(expr); if (rule != null) { //int ruleArgc = rule.Basis.Args[2].ArgCount; //if (expr.ArgCount > ruleArgc) // don't complain about too few args, in case there are default args (I'm too lazy to check) // _sink.Write(MessageSink.Error, expr, "Rule '{0}' takes {1} arguments ({2} given)", rule.Name, ruleArgc, expr.ArgCount); return new RuleRef(expr, rule) { Params = expr.Args }; } string errorMsg = null; Pred terminal = _helper.CodeToTerminalPred(expr, ref errorMsg); if (terminal == null) { errorMsg = errorMsg ?? "LLLPG: unrecognized expression"; terminal = new TerminalPred(expr, _helper.EmptySet); _sink.Error(expr, errorMsg); } else if (errorMsg != null) _sink.Warning(expr, errorMsg); return terminal; }
public override void Visit(TerminalPred term) { if (_index < _path.Count) { if (term.Prematched != false) { IPGTerminalSet predicted = _path[_index].Terminals; bool pm = predicted.IsSubsetOf(term.Set); if (pm || !_reachedInnerAlts) term.Prematched = pm; } _index++; } else if (!_reachedInnerAlts) { term.Prematched = false; } }
public virtual void Visit(TerminalPred term) { VisitOther(term); }