use of org.antlr.v4.tool.ast.GrammarAST in project antlr4 by antlr.
the class ParserATNFactory method newState.
public ATNState newState(GrammarAST node) {
ATNState n = new BasicState();
n.setRuleIndex(currentRule.index);
atn.addState(n);
return n;
}
use of org.antlr.v4.tool.ast.GrammarAST 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]->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);
}
use of org.antlr.v4.tool.ast.GrammarAST 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;
}
use of org.antlr.v4.tool.ast.GrammarAST in project antlr4 by antlr.
the class ParserATNFactory method _createATN.
protected void _createATN(Collection<Rule> rules) {
createRuleStartAndStopATNStates();
GrammarASTAdaptor adaptor = new GrammarASTAdaptor();
for (Rule r : rules) {
// find rule's block
GrammarAST blk = (GrammarAST) r.ast.getFirstChildWithType(ANTLRParser.BLOCK);
CommonTreeNodeStream nodes = new CommonTreeNodeStream(adaptor, blk);
ATNBuilder b = new ATNBuilder(nodes, this);
try {
setCurrentRuleName(r.name);
Handle h = b.ruleBlock(null);
rule(r.ast, r.name, h);
} catch (RecognitionException re) {
ErrorManager.fatalInternalError("bad grammar AST structure", re);
}
}
}
use of org.antlr.v4.tool.ast.GrammarAST in project antlr4 by antlr.
the class ParserATNFactory method set.
/** From set build single edge graph {@code o->o-set->o}. To conform to
* what an alt block looks like, must have extra state on left.
* This also handles {@code ~A}, converted to {@code ~{A}} set.
*/
@Override
public Handle set(GrammarAST associatedAST, List<GrammarAST> terminals, boolean invert) {
ATNState left = newState(associatedAST);
ATNState right = newState(associatedAST);
IntervalSet set = new IntervalSet();
for (GrammarAST t : terminals) {
int ttype = g.getTokenType(t.getText());
set.add(ttype);
}
if (invert) {
left.addTransition(new NotSetTransition(right, set));
} else {
left.addTransition(new SetTransition(right, set));
}
associatedAST.atnState = left;
return new Handle(left, right);
}
Aggregations