use of org.antlr.v4.runtime.misc.IntervalSet in project antlr4 by antlr.
the class TestExpectedTokens method testFollowIncluded.
@Test
public void testFollowIncluded() throws Exception {
String gtext = "parser grammar T;\n" + "a : b A ;\n" + "b : B | ;";
Grammar g = new Grammar(gtext);
String atnText = "RuleStart_a_0->s4\n" + "s4-b->RuleStart_b_2\n" + "s5-A->s6\n" + "s6->RuleStop_a_1\n" + "RuleStop_a_1-EOF->s11\n";
checkRuleATN(g, "a", atnText);
atnText = "RuleStart_b_2->BlockStart_9\n" + "BlockStart_9->s7\n" + "BlockStart_9->s8\n" + "s7-B->BlockEnd_10\n" + "s8->BlockEnd_10\n" + "BlockEnd_10->RuleStop_b_3\n" + "RuleStop_b_3->s5\n";
checkRuleATN(g, "b", atnText);
ATN atn = g.getATN();
// From the start of 'b' with empty stack, can only see B and EOF
int blkStartStateNumber = 9;
IntervalSet tokens = atn.getExpectedTokens(blkStartStateNumber, RuleContext.EMPTY);
assertEquals("{<EOF>, B}", tokens.toString(g.getTokenNames()));
// Now call from 'a'
tokens = atn.getExpectedTokens(blkStartStateNumber, new ParserRuleContext(ParserRuleContext.EMPTY, 4));
assertEquals("{A, B}", tokens.toString(g.getTokenNames()));
}
use of org.antlr.v4.runtime.misc.IntervalSet 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.runtime.misc.IntervalSet 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);
}
use of org.antlr.v4.runtime.misc.IntervalSet in project antlr4 by antlr.
the class LexerATNFactory method getSetFromCharSetLiteral.
public IntervalSet getSetFromCharSetLiteral(GrammarAST charSetAST) {
String chars = charSetAST.getText();
chars = chars.substring(1, chars.length() - 1);
IntervalSet set = new IntervalSet();
if (chars.length() == 0) {
g.tool.errMgr.grammarError(ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED, g.fileName, charSetAST.getToken(), "[]");
return set;
}
CharSetParseState state = CharSetParseState.NONE;
int n = chars.length();
for (int i = 0; i < n; ) {
if (state.mode == CharSetParseState.Mode.ERROR) {
return new IntervalSet();
}
int c = chars.codePointAt(i);
int offset = Character.charCount(c);
if (c == '\\') {
EscapeSequenceParsing.Result escapeParseResult = EscapeSequenceParsing.parseEscape(chars, i);
switch(escapeParseResult.type) {
case INVALID:
g.tool.errMgr.grammarError(ErrorType.INVALID_ESCAPE_SEQUENCE, g.fileName, charSetAST.getToken(), charSetAST.getText());
state = CharSetParseState.ERROR;
break;
case CODE_POINT:
state = applyPrevStateAndMoveToCodePoint(charSetAST, set, state, escapeParseResult.codePoint);
break;
case PROPERTY:
state = applyPrevStateAndMoveToProperty(charSetAST, set, state, escapeParseResult.propertyIntervalSet);
break;
}
offset = escapeParseResult.parseLength;
} else if (c == '-' && !state.inRange && i != 0 && i != n - 1) {
if (state.mode == CharSetParseState.Mode.PREV_PROPERTY) {
g.tool.errMgr.grammarError(ErrorType.UNICODE_PROPERTY_NOT_ALLOWED_IN_RANGE, g.fileName, charSetAST.getToken(), charSetAST.getText());
state = CharSetParseState.ERROR;
} else {
state = new CharSetParseState(state.mode, true, state.prevCodePoint, state.prevProperty);
}
} else {
state = applyPrevStateAndMoveToCodePoint(charSetAST, set, state, c);
}
i += offset;
}
if (state.mode == CharSetParseState.Mode.ERROR) {
return new IntervalSet();
}
// Whether or not we were in a range, we'll add the last code point found to the set.
applyPrevState(charSetAST, set, state);
return set;
}
use of org.antlr.v4.runtime.misc.IntervalSet in project antlr4 by antlr.
the class LexerATNFactory method charSetLiteral.
/** [Aa\t ሴa-z\]\p{Letter}\-] char sets */
@Override
public Handle charSetLiteral(GrammarAST charSetAST) {
ATNState left = newState(charSetAST);
ATNState right = newState(charSetAST);
IntervalSet set = getSetFromCharSetLiteral(charSetAST);
left.addTransition(new SetTransition(right, set));
charSetAST.atnState = left;
return new Handle(left, right);
}
Aggregations