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