Search in sources :

Example 1 with StarBlockStartState

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

the class ParserATNFactory method star.

/**
	 * From {@code (blk)*} build {@code ( blk+ )?} with *two* decisions, one for
	 * entry and one for choosing alts of {@code blk}.
	 *
	 * <pre>
	 *   |-------------|
	 *   v             |
	 *   o--[o-blk-o]-&gt;o  o
	 *   |                ^
	 *   -----------------|
	 * </pre>
	 *
	 * Note that the optional bypass must jump outside the loop as
	 * {@code (A|B)*} is not the same thing as {@code (A|B|)+}.
	 */
@Override
public Handle star(GrammarAST starAST, Handle elem) {
    StarBlockStartState blkStart = (StarBlockStartState) elem.left;
    BlockEndState blkEnd = (BlockEndState) elem.right;
    preventEpsilonClosureBlocks.add(new Triple<Rule, ATNState, ATNState>(currentRule, blkStart, blkEnd));
    StarLoopEntryState entry = newState(StarLoopEntryState.class, starAST);
    entry.nonGreedy = !((QuantifierAST) starAST).isGreedy();
    atn.defineDecisionState(entry);
    LoopEndState end = newState(LoopEndState.class, starAST);
    StarLoopbackState loop = newState(StarLoopbackState.class, starAST);
    entry.loopBackState = loop;
    end.loopBackState = loop;
    BlockAST blkAST = (BlockAST) starAST.getChild(0);
    if (((QuantifierAST) starAST).isGreedy()) {
        if (expectNonGreedy(blkAST)) {
            g.tool.errMgr.grammarError(ErrorType.EXPECTED_NON_GREEDY_WILDCARD_BLOCK, g.fileName, starAST.getToken(), starAST.getToken().getText());
        }
        // loop enter edge (alt 1)
        epsilon(entry, blkStart);
        // bypass loop edge (alt 2)
        epsilon(entry, end);
    } else {
        // if not greedy, priority to exit branch; make it first
        // bypass loop edge (alt 1)
        epsilon(entry, end);
        // loop enter edge (alt 2)
        epsilon(entry, blkStart);
    }
    // block end hits loop back
    epsilon(blkEnd, loop);
    // loop back to entry/exit decision
    epsilon(loop, entry);
    // decision is to enter/exit; blk is its own decision
    starAST.atnState = entry;
    return new Handle(entry, end);
}
Also used : StarBlockStartState(org.antlr.v4.runtime.atn.StarBlockStartState) LoopEndState(org.antlr.v4.runtime.atn.LoopEndState) StarLoopbackState(org.antlr.v4.runtime.atn.StarLoopbackState) StarLoopEntryState(org.antlr.v4.runtime.atn.StarLoopEntryState) BlockAST(org.antlr.v4.tool.ast.BlockAST) QuantifierAST(org.antlr.v4.tool.ast.QuantifierAST) Rule(org.antlr.v4.tool.Rule) LeftRecursiveRule(org.antlr.v4.tool.LeftRecursiveRule) BlockEndState(org.antlr.v4.runtime.atn.BlockEndState) ATNState(org.antlr.v4.runtime.atn.ATNState)

Example 2 with StarBlockStartState

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

the class GrammarParserInterpreter method findOuterMostDecisionStates.

/** identify the ATN states where we need to set the outer alt number.
	 *  For regular rules, that's the block at the target to rule start state.
	 *  For left-recursive rules, we track the primary block, which looks just
	 *  like a regular rule's outer block, and the star loop block (always
	 *  there even if 1 alt).
	 */
public BitSet findOuterMostDecisionStates() {
    BitSet track = new BitSet(atn.states.size());
    int numberOfDecisions = atn.getNumberOfDecisions();
    for (int i = 0; i < numberOfDecisions; i++) {
        DecisionState decisionState = atn.getDecisionState(i);
        RuleStartState startState = atn.ruleToStartState[decisionState.ruleIndex];
        // Look for StarLoopEntryState that is in any left recursive rule
        if (decisionState instanceof StarLoopEntryState) {
            StarLoopEntryState loopEntry = (StarLoopEntryState) decisionState;
            if (loopEntry.isPrecedenceDecision) {
                // Recursive alts always result in a (...)* in the transformed
                // left recursive rule and that always has a BasicBlockStartState
                // even if just 1 recursive alt exists.
                ATNState blockStart = loopEntry.transition(0).target;
                // track the StarBlockStartState associated with the recursive alternatives
                track.set(blockStart.stateNumber);
            }
        } else if (startState.transition(0).target == decisionState) {
            // always track outermost block for any rule if it exists
            track.set(decisionState.stateNumber);
        }
    }
    return track;
}
Also used : StarLoopEntryState(org.antlr.v4.runtime.atn.StarLoopEntryState) RuleStartState(org.antlr.v4.runtime.atn.RuleStartState) BitSet(java.util.BitSet) DecisionState(org.antlr.v4.runtime.atn.DecisionState) ATNState(org.antlr.v4.runtime.atn.ATNState)

Aggregations

ATNState (org.antlr.v4.runtime.atn.ATNState)2 StarLoopEntryState (org.antlr.v4.runtime.atn.StarLoopEntryState)2 BitSet (java.util.BitSet)1 BlockEndState (org.antlr.v4.runtime.atn.BlockEndState)1 DecisionState (org.antlr.v4.runtime.atn.DecisionState)1 LoopEndState (org.antlr.v4.runtime.atn.LoopEndState)1 RuleStartState (org.antlr.v4.runtime.atn.RuleStartState)1 StarBlockStartState (org.antlr.v4.runtime.atn.StarBlockStartState)1 StarLoopbackState (org.antlr.v4.runtime.atn.StarLoopbackState)1 LeftRecursiveRule (org.antlr.v4.tool.LeftRecursiveRule)1 Rule (org.antlr.v4.tool.Rule)1 BlockAST (org.antlr.v4.tool.ast.BlockAST)1 QuantifierAST (org.antlr.v4.tool.ast.QuantifierAST)1