Search in sources :

Example 26 with ATNState

use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.

the class LeftRecursionDetector method check.

public void check() {
    for (RuleStartState start : atn.ruleToStartState) {
        // System.out.print("check "+start.rule.name);
        rulesVisitedPerRuleCheck.clear();
        rulesVisitedPerRuleCheck.add(start);
        // FASerializer ser = new FASerializer(atn.g, start);
        // System.out.print(":\n"+ser+"\n");
        check(g.getRule(start.ruleIndex), start, new HashSet<ATNState>());
    }
    // System.out.println("cycles="+listOfRecursiveCycles);
    if (!listOfRecursiveCycles.isEmpty()) {
        g.tool.errMgr.leftRecursionCycles(g.fileName, listOfRecursiveCycles);
    }
}
Also used : RuleStartState(org.antlr.v4.runtime.atn.RuleStartState) ATNState(org.antlr.v4.runtime.atn.ATNState)

Example 27 with ATNState

use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.

the class ParserATNSimulator method computeStartState.

@NotNull
protected SimulatorState computeStartState(DFA dfa, ParserRuleContext globalContext, boolean useContext) {
    DFAState s0 = dfa.isPrecedenceDfa() ? dfa.getPrecedenceStartState(parser.getPrecedence(), useContext) : useContext ? dfa.s0full.get() : dfa.s0.get();
    if (s0 != null) {
        if (!useContext) {
            return new SimulatorState(globalContext, s0, useContext, globalContext);
        }
        s0.setContextSensitive(atn);
    }
    final int decision = dfa.decision;
    @NotNull final ATNState p = dfa.atnStartState;
    int previousContext = 0;
    ParserRuleContext remainingGlobalContext = globalContext;
    // always at least the implicit call to start rule
    PredictionContext initialContext = useContext ? PredictionContext.EMPTY_FULL : PredictionContext.EMPTY_LOCAL;
    PredictionContextCache contextCache = new PredictionContextCache();
    if (useContext) {
        if (!enable_global_context_dfa) {
            while (remainingGlobalContext != null) {
                if (remainingGlobalContext.isEmpty()) {
                    previousContext = PredictionContext.EMPTY_FULL_STATE_KEY;
                    remainingGlobalContext = null;
                } else {
                    previousContext = getReturnState(remainingGlobalContext);
                    initialContext = initialContext.appendContext(previousContext, contextCache);
                    remainingGlobalContext = remainingGlobalContext.getParent();
                }
            }
        }
        while (s0 != null && s0.isContextSensitive() && remainingGlobalContext != null) {
            DFAState next;
            remainingGlobalContext = skipTailCalls(remainingGlobalContext);
            if (remainingGlobalContext.isEmpty()) {
                next = s0.getContextTarget(PredictionContext.EMPTY_FULL_STATE_KEY);
                previousContext = PredictionContext.EMPTY_FULL_STATE_KEY;
                remainingGlobalContext = null;
            } else {
                previousContext = getReturnState(remainingGlobalContext);
                next = s0.getContextTarget(previousContext);
                initialContext = initialContext.appendContext(previousContext, contextCache);
                remainingGlobalContext = remainingGlobalContext.getParent();
            }
            if (next == null) {
                break;
            }
            s0 = next;
        }
    }
    if (s0 != null && !s0.isContextSensitive()) {
        return new SimulatorState(globalContext, s0, useContext, remainingGlobalContext);
    }
    ATNConfigSet configs = new ATNConfigSet();
    while (true) {
        ATNConfigSet reachIntermediate = new ATNConfigSet();
        int n = p.getNumberOfTransitions();
        for (int ti = 0; ti < n; ti++) {
            // for each transition
            ATNState target = p.transition(ti).target;
            reachIntermediate.add(ATNConfig.create(target, ti + 1, initialContext));
        }
        boolean hasMoreContext = remainingGlobalContext != null;
        if (!hasMoreContext) {
            configs.setOutermostConfigSet(true);
        }
        final boolean collectPredicates = true;
        closure(reachIntermediate, configs, collectPredicates, hasMoreContext, contextCache, false);
        boolean stepIntoGlobal = configs.getDipsIntoOuterContext();
        DFAState next;
        if (useContext && !enable_global_context_dfa) {
            s0 = addDFAState(dfa, configs, contextCache);
            break;
        } else if (s0 == null) {
            if (!dfa.isPrecedenceDfa()) {
                AtomicReference<DFAState> reference = useContext ? dfa.s0full : dfa.s0;
                next = addDFAState(dfa, configs, contextCache);
                if (!reference.compareAndSet(null, next)) {
                    next = reference.get();
                }
            } else {
                /* If this is a precedence DFA, we use applyPrecedenceFilter
					 * to convert the computed start state to a precedence start
					 * state. We then use DFA.setPrecedenceStartState to set the
					 * appropriate start state for the precedence level rather
					 * than simply setting DFA.s0.
					 */
                configs = applyPrecedenceFilter(configs, globalContext, contextCache);
                next = addDFAState(dfa, configs, contextCache);
                dfa.setPrecedenceStartState(parser.getPrecedence(), useContext, next);
            }
        } else {
            if (dfa.isPrecedenceDfa()) {
                configs = applyPrecedenceFilter(configs, globalContext, contextCache);
            }
            next = addDFAState(dfa, configs, contextCache);
            s0.setContextTarget(previousContext, next);
        }
        s0 = next;
        if (!useContext || !stepIntoGlobal) {
            break;
        }
        // TODO: make sure it distinguishes empty stack states
        next.setContextSensitive(atn);
        configs.clear();
        remainingGlobalContext = skipTailCalls(remainingGlobalContext);
        int nextContextElement = getReturnState(remainingGlobalContext);
        if (remainingGlobalContext.isEmpty()) {
            remainingGlobalContext = null;
        } else {
            remainingGlobalContext = remainingGlobalContext.getParent();
        }
        if (nextContextElement != PredictionContext.EMPTY_FULL_STATE_KEY) {
            initialContext = initialContext.appendContext(nextContextElement, contextCache);
        }
        previousContext = nextContextElement;
    }
    return new SimulatorState(globalContext, s0, useContext, remainingGlobalContext);
}
Also used : ParserRuleContext(org.antlr.v4.runtime.ParserRuleContext) DFAState(org.antlr.v4.runtime.dfa.DFAState) AtomicReference(java.util.concurrent.atomic.AtomicReference) NotNull(org.antlr.v4.runtime.misc.NotNull) NotNull(org.antlr.v4.runtime.misc.NotNull)

Example 28 with ATNState

use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.

the class Parser method getExpectedTokensWithinCurrentRule.

@NotNull
public IntervalSet getExpectedTokensWithinCurrentRule() {
    ATN atn = getInterpreter().atn;
    ATNState s = atn.states.get(getState());
    return atn.nextTokens(s);
}
Also used : ATN(org.antlr.v4.runtime.atn.ATN) ATNState(org.antlr.v4.runtime.atn.ATNState) NotNull(org.antlr.v4.runtime.misc.NotNull)

Example 29 with ATNState

use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.

the class ParserInterpreter method visitState.

protected void visitState(ATNState p) {
    int predictedAlt = 1;
    if (p.getNumberOfTransitions() > 1) {
        predictedAlt = visitDecisionState((DecisionState) p);
    }
    Transition transition = p.transition(predictedAlt - 1);
    switch(transition.getSerializationType()) {
        case Transition.EPSILON:
            if (pushRecursionContextStates.get(p.stateNumber) && !(transition.target instanceof LoopEndState)) {
                // We are at the start of a left recursive rule's (...)* loop
                // and we're not taking the exit branch of loop.
                InterpreterRuleContext localctx = createInterpreterRuleContext(_parentContextStack.peek().getItem1(), _parentContextStack.peek().getItem2(), _ctx.getRuleIndex());
                pushNewRecursionContext(localctx, atn.ruleToStartState[p.ruleIndex].stateNumber, _ctx.getRuleIndex());
            }
            break;
        case Transition.ATOM:
            match(((AtomTransition) transition).label);
            break;
        case Transition.RANGE:
        case Transition.SET:
        case Transition.NOT_SET:
            if (!transition.matches(_input.LA(1), Token.MIN_USER_TOKEN_TYPE, 65535)) {
                recoverInline();
            }
            matchWildcard();
            break;
        case Transition.WILDCARD:
            matchWildcard();
            break;
        case Transition.RULE:
            RuleStartState ruleStartState = (RuleStartState) transition.target;
            int ruleIndex = ruleStartState.ruleIndex;
            InterpreterRuleContext newctx = createInterpreterRuleContext(_ctx, p.stateNumber, ruleIndex);
            if (ruleStartState.isPrecedenceRule) {
                enterRecursionRule(newctx, ruleStartState.stateNumber, ruleIndex, ((RuleTransition) transition).precedence);
            } else {
                enterRule(newctx, transition.target.stateNumber, ruleIndex);
            }
            break;
        case Transition.PREDICATE:
            PredicateTransition predicateTransition = (PredicateTransition) transition;
            if (!sempred(_ctx, predicateTransition.ruleIndex, predicateTransition.predIndex)) {
                throw new FailedPredicateException(this);
            }
            break;
        case Transition.ACTION:
            ActionTransition actionTransition = (ActionTransition) transition;
            action(_ctx, actionTransition.ruleIndex, actionTransition.actionIndex);
            break;
        case Transition.PRECEDENCE:
            if (!precpred(_ctx, ((PrecedencePredicateTransition) transition).precedence)) {
                throw new FailedPredicateException(this, String.format("precpred(_ctx, %d)", ((PrecedencePredicateTransition) transition).precedence));
            }
            break;
        default:
            throw new UnsupportedOperationException("Unrecognized ATN transition type.");
    }
    setState(transition.target.stateNumber);
}
Also used : LoopEndState(org.antlr.v4.runtime.atn.LoopEndState) ActionTransition(org.antlr.v4.runtime.atn.ActionTransition) RuleStartState(org.antlr.v4.runtime.atn.RuleStartState) AtomTransition(org.antlr.v4.runtime.atn.AtomTransition) RuleTransition(org.antlr.v4.runtime.atn.RuleTransition) ActionTransition(org.antlr.v4.runtime.atn.ActionTransition) PredicateTransition(org.antlr.v4.runtime.atn.PredicateTransition) PrecedencePredicateTransition(org.antlr.v4.runtime.atn.PrecedencePredicateTransition) Transition(org.antlr.v4.runtime.atn.Transition) PredicateTransition(org.antlr.v4.runtime.atn.PredicateTransition) PrecedencePredicateTransition(org.antlr.v4.runtime.atn.PrecedencePredicateTransition) PrecedencePredicateTransition(org.antlr.v4.runtime.atn.PrecedencePredicateTransition) DecisionState(org.antlr.v4.runtime.atn.DecisionState)

Example 30 with ATNState

use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.

the class DefaultErrorStrategy method getErrorRecoverySet.

/*  Compute the error recovery set for the current rule.  During
	 *  rule invocation, the parser pushes the set of tokens that can
	 *  follow that rule reference on the stack; this amounts to
	 *  computing FIRST of what follows the rule reference in the
	 *  enclosing rule. See LinearApproximator.FIRST().
	 *  This local follow set only includes tokens
	 *  from within the rule; i.e., the FIRST computation done by
	 *  ANTLR stops at the end of a rule.
	 *
	 *  EXAMPLE
	 *
	 *  When you find a "no viable alt exception", the input is not
	 *  consistent with any of the alternatives for rule r.  The best
	 *  thing to do is to consume tokens until you see something that
	 *  can legally follow a call to r *or* any rule that called r.
	 *  You don't want the exact set of viable next tokens because the
	 *  input might just be missing a token--you might consume the
	 *  rest of the input looking for one of the missing tokens.
	 *
	 *  Consider grammar:
	 *
	 *  a : '[' b ']'
	 *    | '(' b ')'
	 *    ;
	 *  b : c '^' INT ;
	 *  c : ID
	 *    | INT
	 *    ;
	 *
	 *  At each rule invocation, the set of tokens that could follow
	 *  that rule is pushed on a stack.  Here are the various
	 *  context-sensitive follow sets:
	 *
	 *  FOLLOW(b1_in_a) = FIRST(']') = ']'
	 *  FOLLOW(b2_in_a) = FIRST(')') = ')'
	 *  FOLLOW(c_in_b) = FIRST('^') = '^'
	 *
	 *  Upon erroneous input "[]", the call chain is
	 *
	 *  a -> b -> c
	 *
	 *  and, hence, the follow context stack is:
	 *
	 *  depth     follow set       start of rule execution
	 *    0         <EOF>                    a (from main())
	 *    1          ']'                     b
	 *    2          '^'                     c
	 *
	 *  Notice that ')' is not included, because b would have to have
	 *  been called from a different context in rule a for ')' to be
	 *  included.
	 *
	 *  For error recovery, we cannot consider FOLLOW(c)
	 *  (context-sensitive or otherwise).  We need the combined set of
	 *  all context-sensitive FOLLOW sets--the set of all tokens that
	 *  could follow any reference in the call chain.  We need to
	 *  resync to one of those tokens.  Note that FOLLOW(c)='^' and if
	 *  we resync'd to that token, we'd consume until EOF.  We need to
	 *  sync to context-sensitive FOLLOWs for a, b, and c: {']','^'}.
	 *  In this case, for input "[]", LA(1) is ']' and in the set, so we would
	 *  not consume anything. After printing an error, rule c would
	 *  return normally.  Rule b would not find the required '^' though.
	 *  At this point, it gets a mismatched token error and throws an
	 *  exception (since LA(1) is not in the viable following token
	 *  set).  The rule exception handler tries to recover, but finds
	 *  the same recovery set and doesn't consume anything.  Rule b
	 *  exits normally returning to rule a.  Now it finds the ']' (and
	 *  with the successful match exits errorRecovery mode).
	 *
	 *  So, you can see that the parser walks up the call chain looking
	 *  for the token that was a member of the recovery set.
	 *
	 *  Errors are not generated in errorRecovery mode.
	 *
	 *  ANTLR's error recovery mechanism is based upon original ideas:
	 *
	 *  "Algorithms + Data Structures = Programs" by Niklaus Wirth
	 *
	 *  and
	 *
	 *  "A note on error recovery in recursive descent parsers":
	 *  http://portal.acm.org/citation.cfm?id=947902.947905
	 *
	 *  Later, Josef Grosch had some good ideas:
	 *
	 *  "Efficient and Comfortable Error Recovery in Recursive Descent
	 *  Parsers":
	 *  ftp://www.cocolab.com/products/cocktail/doca4.ps/ell.ps.zip
	 *
	 *  Like Grosch I implement context-sensitive FOLLOW sets that are combined
	 *  at run-time upon error to avoid overhead during parsing.
	 */
@NotNull
protected IntervalSet getErrorRecoverySet(@NotNull Parser recognizer) {
    ATN atn = recognizer.getInterpreter().atn;
    RuleContext ctx = recognizer._ctx;
    IntervalSet recoverSet = new IntervalSet();
    while (ctx != null && ctx.invokingState >= 0) {
        // compute what follows who invoked us
        ATNState invokingState = atn.states.get(ctx.invokingState);
        RuleTransition rt = (RuleTransition) invokingState.transition(0);
        IntervalSet follow = atn.nextTokens(rt.followState);
        recoverSet.addAll(follow);
        ctx = ctx.parent;
    }
    recoverSet.remove(Token.EPSILON);
    // System.out.println("recover set "+recoverSet.toString(recognizer.getTokenNames()));
    return recoverSet;
}
Also used : IntervalSet(org.antlr.v4.runtime.misc.IntervalSet) RuleTransition(org.antlr.v4.runtime.atn.RuleTransition) ATN(org.antlr.v4.runtime.atn.ATN) ATNState(org.antlr.v4.runtime.atn.ATNState) NotNull(org.antlr.v4.runtime.misc.NotNull)

Aggregations

ATNState (org.antlr.v4.runtime.atn.ATNState)94 IntervalSet (org.antlr.v4.runtime.misc.IntervalSet)34 ATN (org.antlr.v4.runtime.atn.ATN)25 RuleTransition (org.antlr.v4.runtime.atn.RuleTransition)23 Rule (org.antlr.v4.tool.Rule)22 Transition (org.antlr.v4.runtime.atn.Transition)21 NotNull (org.antlr.v4.runtime.misc.NotNull)19 AtomTransition (org.antlr.v4.runtime.atn.AtomTransition)18 RuleStartState (org.antlr.v4.runtime.atn.RuleStartState)17 ActionTransition (org.antlr.v4.runtime.atn.ActionTransition)16 SetTransition (org.antlr.v4.runtime.atn.SetTransition)16 NotSetTransition (org.antlr.v4.runtime.atn.NotSetTransition)15 DecisionState (org.antlr.v4.runtime.atn.DecisionState)11 DOTGenerator (org.antlr.v4.tool.DOTGenerator)10 GrammarAST (org.antlr.v4.tool.ast.GrammarAST)10 ParserATNFactory (org.antlr.v4.automata.ParserATNFactory)9 LeftRecursiveRule (org.antlr.v4.tool.LeftRecursiveRule)9 ArrayList (java.util.ArrayList)8 EpsilonTransition (org.antlr.v4.runtime.atn.EpsilonTransition)8 PrecedencePredicateTransition (org.antlr.v4.runtime.atn.PrecedencePredicateTransition)8