use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class ParserATNFactory method epsilon.
/**
* From an empty alternative build {@code o-e->o}.
*/
@NotNull
@Override
public Handle epsilon(@NotNull GrammarAST node) {
ATNState left = newState(node);
ATNState right = newState(node);
epsilon(left, right);
node.atnState = left;
return new Handle(left, right);
}
use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class ParserATNFactory method epsilon.
protected void epsilon(ATNState a, @NotNull ATNState b, boolean prepend) {
for (Transition t : a.getTransitions()) {
if (t.getSerializationType() != Transition.EPSILON) {
continue;
}
if (t.target == b && ((EpsilonTransition) t).outermostPrecedenceReturn() == -1) {
// This transition was already added
return;
}
}
if (a != null) {
int index = prepend ? 0 : a.getNumberOfTransitions();
a.addTransition(index, new EpsilonTransition(b));
}
}
use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class ParserATNFactory method addEOFTransitionToStartRules.
/**
* Add an EOF transition to any rule end ATNState that points to nothing
* (i.e., for all those rules not invoked by another rule). These
* are start symbols then.
*
* Return the number of grammar entry points; i.e., how many rules are
* not invoked by another rule (they can only be invoked from outside).
* These are the start rules.
*/
public int addEOFTransitionToStartRules() {
int n = 0;
// one unique EOF target for all rules
ATNState eofTarget = newState(null);
for (Rule r : g.rules.values()) {
ATNState stop = atn.ruleToStopState[r.index];
if (stop.getNumberOfTransitions() > 0)
continue;
n++;
Transition t = new AtomTransition(eofTarget, Token.EOF);
stop.addTransition(t);
}
return n;
}
use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class ParserATNFactory method createATN.
@NotNull
@Override
public ATN createATN() {
_createATN(g.rules.values());
assert atn.maxTokenType == g.getMaxTokenType();
addRuleFollowLinks();
addEOFTransitionToStartRules();
ATNOptimizer.optimize(g, atn);
for (Tuple3<? extends Rule, ? extends ATNState, ? extends ATNState> pair : preventEpsilonClosureBlocks) {
LL1Analyzer analyzer = new LL1Analyzer(atn);
ATNState blkStart = pair.getItem2();
ATNState blkStop = pair.getItem3();
IntervalSet lookahead = analyzer.LOOK(blkStart, blkStop, PredictionContext.EMPTY_LOCAL);
if (lookahead.contains(org.antlr.v4.runtime.Token.EPSILON)) {
ErrorType errorType = pair.getItem1() instanceof LeftRecursiveRule ? ErrorType.EPSILON_LR_FOLLOW : ErrorType.EPSILON_CLOSURE;
g.tool.errMgr.grammarError(errorType, g.fileName, ((GrammarAST) pair.getItem1().ast.getChild(0)).getToken(), pair.getItem1().name);
}
}
optionalCheck: for (Tuple3<? extends Rule, ? extends ATNState, ? extends ATNState> pair : preventEpsilonOptionalBlocks) {
int bypassCount = 0;
for (int i = 0; i < pair.getItem2().getNumberOfTransitions(); i++) {
ATNState startState = pair.getItem2().transition(i).target;
if (startState == pair.getItem3()) {
bypassCount++;
continue;
}
LL1Analyzer analyzer = new LL1Analyzer(atn);
if (analyzer.LOOK(startState, pair.getItem3(), PredictionContext.EMPTY_LOCAL).contains(org.antlr.v4.runtime.Token.EPSILON)) {
g.tool.errMgr.grammarError(ErrorType.EPSILON_OPTIONAL, g.fileName, ((GrammarAST) pair.getItem1().ast.getChild(0)).getToken(), pair.getItem1().name);
continue optionalCheck;
}
}
if (bypassCount != 1) {
throw new UnsupportedOperationException("Expected optional block with exactly 1 bypass alternative.");
}
}
return atn;
}
use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class ParserATNFactory method block.
/**
* From {@code A|B|..|Z} alternative block build
*
* <pre>
* o->o-A->o->o (last ATNState is BlockEndState pointed to by all alts)
* | ^
* |->o-B->o--|
* | |
* ... |
* | |
* |->o-Z->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->o graph.
* <p>
* TODO: Set alt number (1..n) in the states?
*/
@NotNull
@Override
public Handle block(@NotNull BlockAST blkAST, @NotNull GrammarAST ebnfRoot, @NotNull 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;
}
Aggregations