forked from jasder/antlr
fix LL1 analyzer
This commit is contained in:
parent
3a6ffafec3
commit
0eb27279de
|
@ -150,7 +150,8 @@ public class LL1Analyzer {
|
|||
if (ctx == null) {
|
||||
look.add(Token.EPSILON);
|
||||
return;
|
||||
} else if (ctx.isEmpty() && addEOF) {
|
||||
}
|
||||
else if (ctx.isEmpty() && addEOF) {
|
||||
look.add(Token.EOF);
|
||||
return;
|
||||
}
|
||||
|
@ -160,26 +161,26 @@ public class LL1Analyzer {
|
|||
if ( ctx==null ) {
|
||||
look.add(Token.EPSILON);
|
||||
return;
|
||||
} else if (ctx.isEmpty() && addEOF) {
|
||||
}
|
||||
else if (ctx.isEmpty() && addEOF) {
|
||||
look.add(Token.EOF);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ctx != PredictionContext.EMPTY ) {
|
||||
// run thru all possible stack tops in ctx
|
||||
for (int i = 0; i < ctx.size(); i++) {
|
||||
ATNState returnState = atn.states.get(ctx.getReturnState(i));
|
||||
// System.out.println("popping back to "+retState);
|
||||
|
||||
boolean removed = calledRuleStack.get(returnState.ruleIndex);
|
||||
try {
|
||||
calledRuleStack.clear(returnState.ruleIndex);
|
||||
boolean removed = calledRuleStack.get(s.ruleIndex);
|
||||
try {
|
||||
calledRuleStack.clear(s.ruleIndex);
|
||||
for (int i = 0; i < ctx.size(); i++) {
|
||||
ATNState returnState = atn.states.get(ctx.getReturnState(i));
|
||||
// System.out.println("popping back to "+retState);
|
||||
_LOOK(returnState, stopState, ctx.getParent(i), look, lookBusy, calledRuleStack, seeThruPreds, addEOF);
|
||||
}
|
||||
finally {
|
||||
if (removed) {
|
||||
calledRuleStack.set(returnState.ruleIndex);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (removed) {
|
||||
calledRuleStack.set(s.ruleIndex);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -317,6 +317,40 @@ public class TestToolSyntaxErrors extends BaseJavaToolTest {
|
|||
super.testErrors(pair, true);
|
||||
}
|
||||
|
||||
// Test for https://github.com/antlr/antlr4/issues/1203
|
||||
@Test public void testEpsilonNestedClosureAnalysis() {
|
||||
String grammar =
|
||||
"grammar T;\n"+
|
||||
"s : (a a)* ;\n"+
|
||||
"a : 'foo'* ;\n";
|
||||
String expected =
|
||||
"error(" + ErrorType.EPSILON_CLOSURE.code + "): T.g4:2:0: rule s contains a closure with at least one alternative that can match an empty string\n";
|
||||
|
||||
String[] pair = new String[] {
|
||||
grammar,
|
||||
expected
|
||||
};
|
||||
|
||||
super.testErrors(pair, true);
|
||||
}
|
||||
|
||||
// Test for https://github.com/antlr/antlr4/issues/1203
|
||||
@Test public void testEpsilonOptionalAndClosureAnalysis() {
|
||||
String grammar =
|
||||
"grammar T;\n"+
|
||||
"s : (a a)? ;\n"+
|
||||
"a : 'foo'* ;\n";
|
||||
String expected =
|
||||
"warning(" + ErrorType.EPSILON_OPTIONAL.code + "): T.g4:2:0: rule s contains an optional block with at least one alternative that can match an empty string\n";
|
||||
|
||||
String[] pair = new String[] {
|
||||
grammar,
|
||||
expected
|
||||
};
|
||||
|
||||
super.testErrors(pair, true);
|
||||
}
|
||||
|
||||
@Test public void testEpsilonOptionalAnalysis() {
|
||||
String grammar =
|
||||
"grammar A;\n"
|
||||
|
|
|
@ -34,7 +34,8 @@ public class AnalysisPipeline {
|
|||
|
||||
if (g.isLexer()) {
|
||||
processLexer();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// BUILD DFA FOR EACH DECISION
|
||||
processParser();
|
||||
}
|
||||
|
|
|
@ -113,7 +113,10 @@ public class ParserATNFactory implements ATNFactory {
|
|||
|
||||
for (Triple<Rule, ATNState, ATNState> pair : preventEpsilonClosureBlocks) {
|
||||
LL1Analyzer analyzer = new LL1Analyzer(atn);
|
||||
if (analyzer.LOOK(pair.b, pair.c, null).contains(org.antlr.v4.runtime.Token.EPSILON)) {
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue