Пример #1
0
        /** Return a list of parse trees, one for each alternative in a decision
         *  given the same input.
         *
         *  Very similar to {@link #getAllPossibleParseTrees} except
         *  that it re-parses the input for every alternative in a decision,
         *  not just the ambiguous ones (there is no alts parameter here).
         *  This method also tries to reduce the size of the parse trees
         *  by stripping away children of the tree that are completely out of range
         *  of startIndex..stopIndex. Also, because errors are expected, we
         *  use a specialized error handler that more or less bails out
         *  but that also consumes the first erroneous token at least. This
         *  ensures that an error node will be in the parse tree for display.
         *
         *  NOTES:
         * // we must parse the entire input now with decision overrides
         * // we cannot parse a subset because it could be that a decision
         * // above our decision of interest needs to read way past
         * // lookaheadInfo.stopIndex. It seems like there is no escaping
         * // the use of a full and complete token stream if we are
         * // resetting to token index 0 and re-parsing from the start symbol.
         * // It's not easy to restart parsing somewhere in the middle like a
         * // continuation because our call stack does not match the
         * // tree stack because of left recursive rule rewriting. grrrr!
         *
         * @since 4.5.1
         */
        public static IList <ParserRuleContext> GetLookaheadParseTrees(Grammar g,
                                                                       ParserInterpreter originalParser,
                                                                       ITokenStream tokens,
                                                                       int startRuleIndex,
                                                                       int decision,
                                                                       int startIndex,
                                                                       int stopIndex)
        {
            IList <ParserRuleContext> trees = new List <ParserRuleContext>();
            // Create a new parser interpreter to parse the ambiguous subphrase
            ParserInterpreter parser = DeriveTempParserInterpreter(g, originalParser, tokens);

            DecisionState decisionState = originalParser.Atn.decisionToState[decision];

            for (int alt = 1; alt <= decisionState.Transitions.Length; alt++)
            {
                // 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.)
                BailButConsumeErrorStrategy errorHandler = new BailButConsumeErrorStrategy();
                parser.ErrorHandler = errorHandler;
                parser.Reset();
                parser.AddDecisionOverride(decision, startIndex, alt);
                ParserRuleContext tt = parser.Parse(startRuleIndex);
                int stopTreeAt       = stopIndex;
                if (errorHandler.firstErrorTokenIndex >= 0)
                {
                    stopTreeAt = errorHandler.firstErrorTokenIndex; // cut off rest at first error
                }

                Interval overallRange = tt.SourceInterval;
                if (stopTreeAt > overallRange.b)
                {
                    // If we try to look beyond range of tree, stopTreeAt must be EOF
                    // for which there is no EOF ref in grammar. That means tree
                    // will not have node for stopTreeAt; limit to overallRange.b
                    stopTreeAt = overallRange.b;
                }

                ParserRuleContext subtree =
                    Trees.GetRootOfSubtreeEnclosingRegion(tt,
                                                          startIndex,
                                                          stopTreeAt);
                // Use higher of overridden decision tree or tree enclosing all tokens
                if (Trees.IsAncestorOf(parser.OverrideDecisionRoot, subtree))
                {
                    subtree = parser.OverrideDecisionRoot;
                }
                Trees.StripChildrenOutOfRange(subtree, parser.OverrideDecisionRoot, startIndex, stopTreeAt);
                trees.Add(subtree);
            }

            return(trees);
        }
Пример #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);
        }