Search in sources :

Example 11 with Alternative

use of org.antlr.v4.tool.Alternative in project antlr4 by antlr.

the class ParserATNFactory method createATN.

@Override
public ATN createATN() {
    _createATN(g.rules.values());
    assert atn.maxTokenType == g.getMaxTokenType();
    addRuleFollowLinks();
    addEOFTransitionToStartRules();
    ATNOptimizer.optimize(g, atn);
    for (Triple<Rule, ATNState, ATNState> pair : preventEpsilonClosureBlocks) {
        LL1Analyzer analyzer = new LL1Analyzer(atn);
        ATNState blkStart = pair.b;
        ATNState blkStop = pair.c;
        IntervalSet lookahead = analyzer.LOOK(blkStart, blkStop, null);
        if (lookahead.contains(org.antlr.v4.runtime.Token.EPSILON)) {
            ErrorType errorType = pair.a instanceof LeftRecursiveRule ? ErrorType.EPSILON_LR_FOLLOW : ErrorType.EPSILON_CLOSURE;
            g.tool.errMgr.grammarError(errorType, g.fileName, ((GrammarAST) pair.a.ast.getChild(0)).getToken(), pair.a.name);
        }
    }
    optionalCheck: for (Triple<Rule, ATNState, ATNState> pair : preventEpsilonOptionalBlocks) {
        int bypassCount = 0;
        for (int i = 0; i < pair.b.getNumberOfTransitions(); i++) {
            ATNState startState = pair.b.transition(i).target;
            if (startState == pair.c) {
                bypassCount++;
                continue;
            }
            LL1Analyzer analyzer = new LL1Analyzer(atn);
            if (analyzer.LOOK(startState, pair.c, null).contains(org.antlr.v4.runtime.Token.EPSILON)) {
                g.tool.errMgr.grammarError(ErrorType.EPSILON_OPTIONAL, g.fileName, ((GrammarAST) pair.a.ast.getChild(0)).getToken(), pair.a.name);
                continue optionalCheck;
            }
        }
        if (bypassCount != 1) {
            throw new UnsupportedOperationException("Expected optional block with exactly 1 bypass alternative.");
        }
    }
    return atn;
}
Also used : LeftRecursiveRule(org.antlr.v4.tool.LeftRecursiveRule) Triple(org.antlr.v4.runtime.misc.Triple) LL1Analyzer(org.antlr.v4.runtime.atn.LL1Analyzer) ErrorType(org.antlr.v4.tool.ErrorType) IntervalSet(org.antlr.v4.runtime.misc.IntervalSet) GrammarAST(org.antlr.v4.tool.ast.GrammarAST) Rule(org.antlr.v4.tool.Rule) LeftRecursiveRule(org.antlr.v4.tool.LeftRecursiveRule) ATNState(org.antlr.v4.runtime.atn.ATNState)

Example 12 with Alternative

use of org.antlr.v4.tool.Alternative in project antlr4 by antlr.

the class ParserATNSimulator method execATNWithFullContext.

// comes back with reach.uniqueAlt set to a valid alt
protected int execATNWithFullContext(DFA dfa, // how far we got in SLL DFA before failing over
DFAState D, ATNConfigSet s0, TokenStream input, int startIndex, ParserRuleContext outerContext) {
    if (debug || debug_list_atn_decisions) {
        System.out.println("execATNWithFullContext " + s0);
    }
    boolean fullCtx = true;
    boolean foundExactAmbig = false;
    ATNConfigSet reach = null;
    ATNConfigSet previous = s0;
    input.seek(startIndex);
    int t = input.LA(1);
    int predictedAlt;
    while (true) {
        // while more work
        //			System.out.println("LL REACH "+getLookaheadName(input)+
        //							   " from configs.size="+previous.size()+
        //							   " line "+input.LT(1).getLine()+":"+input.LT(1).getCharPositionInLine());
        reach = computeReachSet(previous, t, fullCtx);
        if (reach == null) {
            // if any configs in previous dipped into outer context, that
            // means that input up to t actually finished entry rule
            // at least for LL decision. Full LL doesn't dip into outer
            // so don't need special case.
            // We will get an error no matter what so delay until after
            // decision; better error message. Also, no reachable target
            // ATN states in SLL implies LL will also get nowhere.
            // If conflict in states that dip out, choose min since we
            // will get error no matter what.
            NoViableAltException e = noViableAlt(input, outerContext, previous, startIndex);
            input.seek(startIndex);
            int alt = getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previous, outerContext);
            if (alt != ATN.INVALID_ALT_NUMBER) {
                return alt;
            }
            throw e;
        }
        Collection<BitSet> altSubSets = PredictionMode.getConflictingAltSubsets(reach);
        if (debug) {
            System.out.println("LL altSubSets=" + altSubSets + ", predict=" + PredictionMode.getUniqueAlt(altSubSets) + ", resolvesToJustOneViableAlt=" + PredictionMode.resolvesToJustOneViableAlt(altSubSets));
        }
        //			System.out.println("altSubSets: "+altSubSets);
        //			System.err.println("reach="+reach+", "+reach.conflictingAlts);
        reach.uniqueAlt = getUniqueAlt(reach);
        // unique prediction?
        if (reach.uniqueAlt != ATN.INVALID_ALT_NUMBER) {
            predictedAlt = reach.uniqueAlt;
            break;
        }
        if (mode != PredictionMode.LL_EXACT_AMBIG_DETECTION) {
            predictedAlt = PredictionMode.resolvesToJustOneViableAlt(altSubSets);
            if (predictedAlt != ATN.INVALID_ALT_NUMBER) {
                break;
            }
        } else {
            // Just keeps scarfing until we know what the conflict is
            if (PredictionMode.allSubsetsConflict(altSubSets) && PredictionMode.allSubsetsEqual(altSubSets)) {
                foundExactAmbig = true;
                predictedAlt = PredictionMode.getSingleViableAlt(altSubSets);
                break;
            }
        // else there are multiple non-conflicting subsets or
        // we're not sure what the ambiguity is yet.
        // So, keep going.
        }
        previous = reach;
        if (t != IntStream.EOF) {
            input.consume();
            t = input.LA(1);
        }
    }
    // not SLL.
    if (reach.uniqueAlt != ATN.INVALID_ALT_NUMBER) {
        reportContextSensitivity(dfa, predictedAlt, reach, startIndex, input.index());
        return predictedAlt;
    }
    // We do not check predicates here because we have checked them
    // on-the-fly when doing full context prediction.
    /*
		In non-exact ambiguity detection mode, we might	actually be able to
		detect an exact ambiguity, but I'm not going to spend the cycles
		needed to check. We only emit ambiguity warnings in exact ambiguity
		mode.

		For example, we might know that we have conflicting configurations.
		But, that does not mean that there is no way forward without a
		conflict. It's possible to have nonconflicting alt subsets as in:

		   LL altSubSets=[{1, 2}, {1, 2}, {1}, {1, 2}]

		from

		   [(17,1,[5 $]), (13,1,[5 10 $]), (21,1,[5 10 $]), (11,1,[$]),
			(13,2,[5 10 $]), (21,2,[5 10 $]), (11,2,[$])]

		In this case, (17,1,[5 $]) indicates there is some next sequence that
		would resolve this without conflict to alternative 1. Any other viable
		next sequence, however, is associated with a conflict.  We stop
		looking for input because no amount of further lookahead will alter
		the fact that we should predict alternative 1.  We just can't say for
		sure that there is an ambiguity without looking further.
		*/
    reportAmbiguity(dfa, D, startIndex, input.index(), foundExactAmbig, reach.getAlts(), reach);
    return predictedAlt;
}
Also used : NoViableAltException(org.antlr.v4.runtime.NoViableAltException) BitSet(java.util.BitSet)

Example 13 with Alternative

use of org.antlr.v4.tool.Alternative in project antlr4 by antlr.

the class ParserATNSimulator method computeTargetState.

/**
	 * Compute a target state for an edge in the DFA, and attempt to add the
	 * computed state and corresponding edge to the DFA.
	 *
	 * @param dfa The DFA
	 * @param previousD The current DFA state
	 * @param t The next input symbol
	 *
	 * @return The computed target DFA state for the given input symbol
	 * {@code t}. If {@code t} does not lead to a valid DFA state, this method
	 * returns {@link #ERROR}.
	 */
protected DFAState computeTargetState(DFA dfa, DFAState previousD, int t) {
    ATNConfigSet reach = computeReachSet(previousD.configs, t, false);
    if (reach == null) {
        addDFAEdge(dfa, previousD, t, ERROR);
        return ERROR;
    }
    // create new target state; we'll add to DFA after it's complete
    DFAState D = new DFAState(reach);
    int predictedAlt = getUniqueAlt(reach);
    if (debug) {
        Collection<BitSet> altSubSets = PredictionMode.getConflictingAltSubsets(reach);
        System.out.println("SLL altSubSets=" + altSubSets + ", configs=" + reach + ", predict=" + predictedAlt + ", allSubsetsConflict=" + PredictionMode.allSubsetsConflict(altSubSets) + ", conflictingAlts=" + getConflictingAlts(reach));
    }
    if (predictedAlt != ATN.INVALID_ALT_NUMBER) {
        // NO CONFLICT, UNIQUELY PREDICTED ALT
        D.isAcceptState = true;
        D.configs.uniqueAlt = predictedAlt;
        D.prediction = predictedAlt;
    } else if (PredictionMode.hasSLLConflictTerminatingPrediction(mode, reach)) {
        // MORE THAN ONE VIABLE ALTERNATIVE
        D.configs.conflictingAlts = getConflictingAlts(reach);
        D.requiresFullContext = true;
        // in SLL-only mode, we will stop at this state and return the minimum alt
        D.isAcceptState = true;
        D.prediction = D.configs.conflictingAlts.nextSetBit(0);
    }
    if (D.isAcceptState && D.configs.hasSemanticContext) {
        predicateDFAState(D, atn.getDecisionState(dfa.decision));
        if (D.predicates != null) {
            D.prediction = ATN.INVALID_ALT_NUMBER;
        }
    }
    // all adds to dfa are done after we've created full D state
    D = addDFAEdge(dfa, previousD, t, D);
    return D;
}
Also used : DFAState(org.antlr.v4.runtime.dfa.DFAState) BitSet(java.util.BitSet)

Example 14 with Alternative

use of org.antlr.v4.tool.Alternative in project antlr4 by antlr.

the class LeftRecursiveRuleAnalyzer method text.

public String text(GrammarAST t) {
    if (t == null)
        return "";
    int tokenStartIndex = t.getTokenStartIndex();
    int tokenStopIndex = t.getTokenStopIndex();
    // ignore tokens from existing option subtrees like:
    //    (ELEMENT_OPTIONS (= assoc right))
    //
    // element options are added back according to the values in the map
    // returned by getOptions().
    IntervalSet ignore = new IntervalSet();
    List<GrammarAST> optionsSubTrees = t.getNodesWithType(ELEMENT_OPTIONS);
    for (GrammarAST sub : optionsSubTrees) {
        ignore.add(sub.getTokenStartIndex(), sub.getTokenStopIndex());
    }
    // Individual labels appear as RULE_REF or TOKEN_REF tokens in the tree,
    // but do not support the ELEMENT_OPTIONS syntax. Make sure to not try
    // and add the tokenIndex option when writing these tokens.
    IntervalSet noOptions = new IntervalSet();
    List<GrammarAST> labeledSubTrees = t.getNodesWithType(new IntervalSet(ASSIGN, PLUS_ASSIGN));
    for (GrammarAST sub : labeledSubTrees) {
        noOptions.add(sub.getChild(0).getTokenStartIndex());
    }
    StringBuilder buf = new StringBuilder();
    int i = tokenStartIndex;
    while (i <= tokenStopIndex) {
        if (ignore.contains(i)) {
            i++;
            continue;
        }
        Token tok = tokenStream.get(i);
        // Compute/hold any element options
        StringBuilder elementOptions = new StringBuilder();
        if (!noOptions.contains(i)) {
            GrammarAST node = t.getNodeWithTokenIndex(tok.getTokenIndex());
            if (node != null && (tok.getType() == TOKEN_REF || tok.getType() == STRING_LITERAL || tok.getType() == RULE_REF)) {
                elementOptions.append("tokenIndex=").append(tok.getTokenIndex());
            }
            if (node instanceof GrammarASTWithOptions) {
                GrammarASTWithOptions o = (GrammarASTWithOptions) node;
                for (Map.Entry<String, GrammarAST> entry : o.getOptions().entrySet()) {
                    if (elementOptions.length() > 0) {
                        elementOptions.append(',');
                    }
                    elementOptions.append(entry.getKey());
                    elementOptions.append('=');
                    elementOptions.append(entry.getValue().getText());
                }
            }
        }
        // add actual text of the current token to the rewritten alternative
        buf.append(tok.getText());
        // move to the next token
        i++;
        // Are there args on a rule?
        if (tok.getType() == RULE_REF && i <= tokenStopIndex && tokenStream.get(i).getType() == ARG_ACTION) {
            buf.append('[' + tokenStream.get(i).getText() + ']');
            i++;
        }
        // now that we have the actual element, we can add the options.
        if (elementOptions.length() > 0) {
            buf.append('<').append(elementOptions).append('>');
        }
    }
    return buf.toString();
}
Also used : IntervalSet(org.antlr.v4.runtime.misc.IntervalSet) GrammarAST(org.antlr.v4.tool.ast.GrammarAST) Token(org.antlr.runtime.Token) CommonToken(org.antlr.runtime.CommonToken) GrammarASTWithOptions(org.antlr.v4.tool.ast.GrammarASTWithOptions) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 15 with Alternative

use of org.antlr.v4.tool.Alternative in project antlr4 by antlr.

the class ParserATNFactory method block.

/**
	 * From {@code A|B|..|Z} alternative block build
	 *
	 * <pre>
	 *  o-&gt;o-A-&gt;o-&gt;o (last ATNState is BlockEndState pointed to by all alts)
	 *  |          ^
	 *  |-&gt;o-B-&gt;o--|
	 *  |          |
	 *  ...        |
	 *  |          |
	 *  |-&gt;o-Z-&gt;o--|
	 * </pre>
	 *
	 * So start node points at every alternative with epsilon transition and
	 * every alt right side points at a block end ATNState.
	 * <p>
	 * Special case: only one alternative: don't make a block with alt
	 * begin/end.
	 * <p>
	 * Special case: if just a list of tokens/chars/sets, then collapse to a
	 * single edged o-set-&gt;o graph.
	 * <p>
	 * TODO: Set alt number (1..n) in the states?
	 */
@Override
public Handle block(BlockAST blkAST, GrammarAST ebnfRoot, List<Handle> alts) {
    if (ebnfRoot == null) {
        if (alts.size() == 1) {
            Handle h = alts.get(0);
            blkAST.atnState = h.left;
            return h;
        }
        BlockStartState start = newState(BasicBlockStartState.class, blkAST);
        if (alts.size() > 1)
            atn.defineDecisionState(start);
        return makeBlock(start, blkAST, alts);
    }
    switch(ebnfRoot.getType()) {
        case ANTLRParser.OPTIONAL:
            BlockStartState start = newState(BasicBlockStartState.class, blkAST);
            atn.defineDecisionState(start);
            Handle h = makeBlock(start, blkAST, alts);
            return optional(ebnfRoot, h);
        case ANTLRParser.CLOSURE:
            BlockStartState star = newState(StarBlockStartState.class, ebnfRoot);
            if (alts.size() > 1)
                atn.defineDecisionState(star);
            h = makeBlock(star, blkAST, alts);
            return star(ebnfRoot, h);
        case ANTLRParser.POSITIVE_CLOSURE:
            PlusBlockStartState plus = newState(PlusBlockStartState.class, ebnfRoot);
            if (alts.size() > 1)
                atn.defineDecisionState(plus);
            h = makeBlock(plus, blkAST, alts);
            return plus(ebnfRoot, h);
    }
    return null;
}
Also used : PlusBlockStartState(org.antlr.v4.runtime.atn.PlusBlockStartState) PlusBlockStartState(org.antlr.v4.runtime.atn.PlusBlockStartState) StarBlockStartState(org.antlr.v4.runtime.atn.StarBlockStartState) BasicBlockStartState(org.antlr.v4.runtime.atn.BasicBlockStartState) BlockStartState(org.antlr.v4.runtime.atn.BlockStartState)

Aggregations

ArrayList (java.util.ArrayList)4 Alternative (org.antlr.v4.tool.Alternative)4 Rule (org.antlr.v4.tool.Rule)4 GrammarAST (org.antlr.v4.tool.ast.GrammarAST)4 BitSet (java.util.BitSet)3 ParserInterpreter (org.antlr.v4.runtime.ParserInterpreter)3 ATNState (org.antlr.v4.runtime.atn.ATNState)3 IntervalSet (org.antlr.v4.runtime.misc.IntervalSet)3 HashMap (java.util.HashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 List (java.util.List)2 NoViableAltException (org.antlr.v4.runtime.NoViableAltException)2 ParserRuleContext (org.antlr.v4.runtime.ParserRuleContext)2 DFAState (org.antlr.v4.runtime.dfa.DFAState)2 LeftRecursiveRule (org.antlr.v4.tool.LeftRecursiveRule)2 ActionAST (org.antlr.v4.tool.ast.ActionAST)2 Map (java.util.Map)1 CommonToken (org.antlr.runtime.CommonToken)1 Token (org.antlr.runtime.Token)1 BailErrorStrategy (org.antlr.v4.runtime.BailErrorStrategy)1