/** 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); }
/** 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); }