Inheritance: Antlr4.Runtime.InterpreterRuleContext
Example #1
0
        /** Override this method so that we can record which alternative
         *  was taken at each decision point. For non-left recursive rules,
         *  it's simple. Set decisionStatesThatSetOuterAltNumInContext
         *  indicates which decision states should set the outer alternative number.
         *
         *  <p>Left recursive rules are much more complicated to deal with:
         *  there is typically a decision for the primary alternatives and a
         *  decision to choose between the recursive operator alternatives.
         *  For example, the following left recursive rule has two primary and 2
         *  recursive alternatives.</p>
         *
         *   e : e '*' e
         | '-' INT
         | e '+' e
         | ID
         |     ;
         |
         *  <p>ANTLR rewrites that rule to be</p>
         *
         *   e[int precedence]
         *       : ('-' INT | ID)
         *       ( {...}? '*' e[5]
         | {...}? '+' e[3]
         |       )*
         |      ;
         |
         *
         *  <p>So, there are two decisions associated with picking the outermost alt.
         *  This complicates our tracking significantly. The outermost alternative number
         *  is a function of the decision (ATN state) within a left recursive rule and the
         *  predicted alternative coming back from adaptivePredict().</p>
         *
         *  We use stateToAltsMap as a cache to avoid expensive calls to
         *  getRecursiveOpAlts().
         */
        protected override int VisitDecisionState(DecisionState p)
        {
            int predictedAlt = base.VisitDecisionState(p);

            if (p.NumberOfTransitions > 1)
            {
                //			System.out.println("decision "+p.decision+": "+predictedAlt);
                if (p.decision == this.overrideDecision &&
                    this._input.Index == this.overrideDecisionInputIndex)
                {
                    overrideDecisionRoot = (GrammarInterpreterRuleContext)Context;
                }
            }

            GrammarInterpreterRuleContext ctx = (GrammarInterpreterRuleContext)_ctx;

            if (decisionStatesThatSetOuterAltNumInContext.Get(p.stateNumber))
            {
                ctx.OuterAlternative = predictedAlt;
                Rule r = g.GetRule(p.ruleIndex);
                if (atn.ruleToStartState[r.index].isPrecedenceRule)
                {
                    int[]             alts = stateToAltsMap[p.stateNumber];
                    LeftRecursiveRule lr   = (LeftRecursiveRule)g.GetRule(p.ruleIndex);
                    if (p.StateType == StateType.BlockStart)
                    {
                        if (alts == null)
                        {
                            alts = lr.GetPrimaryAlts();
                            stateToAltsMap[p.stateNumber] = alts; // cache it
                        }
                    }
                    else if (p.StateType == StateType.StarBlockStart)
                    {
                        if (alts == null)
                        {
                            alts = lr.GetRecursiveOpAlts();
                            stateToAltsMap[p.stateNumber] = alts; // cache it
                        }
                    }
                    ctx.OuterAlternative = alts[predictedAlt];
                }
            }

            return(predictedAlt);
        }
Example #2
0
        /** Given an ambiguous parse information, return the list of ambiguous parse trees.
         *  An ambiguity occurs when a specific token sequence can be recognized
         *  in more than one way by the grammar. These ambiguities are detected only
         *  at decision points.
         *
         *  The list of trees includes the actual interpretation (that for
         *  the minimum alternative number) and all ambiguous alternatives.
         *  The actual interpretation is always first.
         *
         *  This method reuses the same physical input token stream used to
         *  detect the ambiguity by the original parser in the first place.
         *  This method resets/seeks within but does not alter originalParser.
         *
         *  The trees are rooted at the node whose start..stop token indices
         *  include the start and stop indices of this ambiguity event. That is,
         *  the trees returned will always include the complete ambiguous subphrase
         *  identified by the ambiguity event.  The subtrees returned will
         *  also always contain the node associated with the overridden decision.
         *
         *  Be aware that this method does NOT notify error or parse listeners as
         *  it would trigger duplicate or otherwise unwanted events.
         *
         *  This uses a temporary ParserATNSimulator and a ParserInterpreter
         *  so we don't mess up any statistics, event lists, etc...
         *  The parse tree constructed while identifying/making ambiguityInfo is
         *  not affected by this method as it creates a new parser interp to
         *  get the ambiguous interpretations.
         *
         *  Nodes in the returned ambig trees are independent of the original parse
         *  tree (constructed while identifying/creating ambiguityInfo).
         *
         *  @since 4.5.1
         *
         *  @param g              From which grammar should we drive alternative
         *                        numbers and alternative labels.
         *
         *  @param originalParser The parser used to create ambiguityInfo; it
         *                        is not modified by this routine and can be either
         *                        a generated or interpreted parser. It's token
         *                        stream *is* reset/seek()'d.
         *  @param tokens		  A stream of tokens to use with the temporary parser.
         *                        This will often be just the token stream within the
         *                        original parser but here it is for flexibility.
         *
         *  @param decision       Which decision to try different alternatives for.
         *
         *  @param alts           The set of alternatives to try while re-parsing.
         *
         *  @param startIndex	  The index of the first token of the ambiguous
         *                        input or other input of interest.
         *
         *  @param stopIndex      The index of the last token of the ambiguous input.
         *                        The start and stop indexes are used primarily to
         *                        identify how much of the resulting parse tree
         *                        to return.
         *
         *  @param startRuleIndex The start rule for the entire grammar, not
         *                        the ambiguous decision. We re-parse the entire input
         *                        and so we need the original start rule.
         *
         *  @return               The list of all possible interpretations of
         *                        the input for the decision in ambiguityInfo.
         *                        The actual interpretation chosen by the parser
         *                        is always given first because this method
         *                        retests the input in alternative order and
         *                        ANTLR always resolves ambiguities by choosing
         *                        the first alternative that matches the input.
         *                        The subtree returned
         *
         *  @throws RecognitionException Throws upon syntax error while matching
         *                               ambig input.
         */
        public static IList <ParserRuleContext> GetAllPossibleParseTrees(Grammar g,
                                                                         Parser originalParser,
                                                                         ITokenStream tokens,
                                                                         int decision,
                                                                         BitSet alts,
                                                                         int startIndex,
                                                                         int stopIndex,
                                                                         int startRuleIndex)
        {
            IList <ParserRuleContext> trees = new List <ParserRuleContext>();
            // Create a new parser interpreter to parse the ambiguous subphrase
            ParserInterpreter parser = DeriveTempParserInterpreter(g, originalParser, tokens);

            if (stopIndex >= (tokens.Size - 1))
            {
                // if we are pointing at EOF token
                // EOF is not in tree, so must be 1 less than last non-EOF token
                stopIndex = tokens.Size - 2;
            }

            // get ambig trees
            int alt = alts.NextSetBit(0);

            while (alt >= 0)
            {
                // re-parse entire input for all ambiguous alternatives
                // (don't have to do first as it's been parsed, but do again for simplicity
                //  using this temp parser.)
                parser.Reset();
                parser.AddDecisionOverride(decision, startIndex, alt);
                ParserRuleContext             t            = parser.Parse(startRuleIndex);
                GrammarInterpreterRuleContext ambigSubTree =
                    (GrammarInterpreterRuleContext)Trees.GetRootOfSubtreeEnclosingRegion(t, startIndex, stopIndex);
                // Use higher of overridden decision tree or tree enclosing all tokens
                if (Trees.IsAncestorOf(parser.OverrideDecisionRoot, ambigSubTree))
                {
                    ambigSubTree = (GrammarInterpreterRuleContext)parser.OverrideDecisionRoot;
                }
                trees.Add(ambigSubTree);
                alt = alts.NextSetBit(alt + 1);
            }

            return(trees);
        }