Пример #1
0
        private Pred TranslateLoopExpr(LNode expr, Context ctx)
        {
            Symbol type   = expr.Name;
            bool?  greedy = null;
            bool   g;

            expr = expr.Args[0];
            if ((g = expr.Calls(_Greedy, 1)) || expr.Calls(_Nongreedy, 1))
            {
                greedy = g;
                expr   = expr.Args[0];
            }
            BranchMode branchMode;
            Pred       subpred = BranchToPred(expr, out branchMode, ctx);

            if (branchMode != BranchMode.None)
            {
                _sink.Write(Severity.Warning, expr, "'default' and 'error' only apply when there are multiple arms (a|b, a/b)");
            }

            if (type == _Star)
            {
                return(new Alts(expr, LoopMode.Star, subpred, greedy));
            }
            else if (type == _Plus)
            {
                return(new Seq(subpred, new Alts(expr, LoopMode.Star, subpred.Clone(), greedy), expr));
            }
            else               // type == _Opt
            {
                return(new Alts(expr, LoopMode.Opt, subpred, greedy));
            }
        }
Пример #2
0
        public override Pred Clone()
        {
            Gate clone = (Gate)base.Clone();

            clone.Predictor = Predictor.Clone();
            clone.Match     = Match.Clone();
            return(clone);
        }
Пример #3
0
        public override Pred Clone()
        {
            Gate clone = (Gate)base.Clone();

            clone._predictor = _predictor.Clone();
            clone._match     = _match.Clone();
            return(clone);
        }
Пример #4
0
        private Pred TranslateLoopExpr(LNode expr, Context ctx)
        {
            Symbol type   = expr.Name;
            bool?  greedy = null;
            bool   g;

            expr = expr.Args[0];
            if ((g = expr.Calls(_Greedy, 1)) || expr.Calls(_Nongreedy, 1))
            {
                greedy = g;
                expr   = expr.Args[0];
            }
            BranchMode branchMode;
            Pred       subpred = BranchToPred(expr, out branchMode, ctx);

            if (branchMode == BranchMode.ErrorContinue || branchMode == BranchMode.ErrorExit)
            {
                _sink.Error(expr, "'error' only applies when there are multiple arms (a|b, a/b)");
            }

            Pred clone = type == _Plus?subpred.Clone() : null;

            Alts alts = new Alts(expr, type == _Opt ? LoopMode.Opt : LoopMode.Star, clone ?? subpred, greedy);

            if (branchMode == BranchMode.Default)
            {
                alts.DefaultArm = 0;
            }
            if (clone != null)
            {
                return(new Seq(subpred, alts, expr));
            }
            else
            {
                return(alts);
            }
        }
Пример #5
0
        Pred NodeToPredCore(LNode expr, Context ctx = Context.Rule)
        {
            if (expr.IsCall)
            {
                bool slash = false, not;
                if (expr.Calls(S.Tuple))
                {
                    // sequence: (a, b, c)
                    if (expr.Calls(S.Tuple, 1))
                    {
                        return(NodeToPred(expr.Args[0], ctx));
                    }
                    return(ArgsToSeq(expr, ctx));
                }
                else if (expr.Calls(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?)
                    Symbol type   = expr.Name;
                    bool?  greedy = null;
                    bool   g;
                    expr = expr.Args[0];
                    if ((g = expr.Calls(_Greedy, 1)) || expr.Calls(_Nongreedy, 1))
                    {
                        greedy = g;
                        expr   = expr.Args[0];
                    }
                    BranchMode branchMode;
                    Pred       subpred = BranchToPred(expr, out branchMode, ctx);

                    if (branchMode != BranchMode.None)
                    {
                        _sink.Write(Severity.Warning, expr, "'default' and 'error' only apply when there are multiple arms (a|b, a/b)");
                    }

                    if (type == _Star)
                    {
                        return(new Alts(expr, LoopMode.Star, subpred, greedy));
                    }
                    else if (type == _Plus)
                    {
                        return(new Seq(subpred, new Alts(expr, LoopMode.Star, subpred.Clone(), greedy), expr));
                    }
                    else                       // type == _Opt
                    {
                        return(new Alts(expr, LoopMode.Opt, subpred, greedy));
                    }
                }
                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.Write(Severity.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;
                    bool  local   = false;
                    if (subexpr != null && (subpred = subexpr.WithoutAttrNamed(_Local)) != subexpr)
                    {
                        local = true;
                    }
                    return(new AndPred(expr, subpred, not, local));
                }
                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.Write(Severity.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.Name.Name.EndsWith("=") && expr.ArgCount == 2)
                {
                    var lhs  = expr.Args[0];
                    var pred = NodeToPred(expr.Args[1], ctx);
                    if (expr.Calls(S.AddSet))
                    {
                        pred.ResultSaver = result => F.Call(F.Dot(lhs, _Add), result);
                    }
                    else if (expr.Calls(S.QuickBindSet))
                    {
                        pred.ResultSaver = result => F.Call(S.Var, F._Missing, F.Call(S.Assign, lhs, result));
                    }
                    else
                    {
                        pred.ResultSaver = result => F.Call(expr.Target, lhs, result);
                    }
                    return(pred);
                }
            }

            // expr is an Id, literal, or non-special call
            Rule rule;

            if (!expr.IsLiteral && _rules.TryGetValue(expr.Name, out rule))
            {
                //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.CodeToPred(expr, ref errorMsg);

            if (terminal == null)
            {
                errorMsg = errorMsg ?? "LLLPG: unrecognized expression";
                terminal = new TerminalPred(expr, _helper.EmptySet);
                _sink.Write(Severity.Error, expr, errorMsg);
            }
            else if (errorMsg != null)
            {
                _sink.Write(Severity.Warning, expr, errorMsg);
            }
            return(terminal);
        }