Add error 147: left recursive rule 'a' must contain an alternative which is not left recursive; fixes antlr/antlr4#140
This commit is contained in:
parent
8e32d7b695
commit
9ccdca49bb
|
@ -145,6 +145,10 @@ public class LeftRecursiveRuleTransformer {
|
||||||
r.recPrimaryAlts = new ArrayList<LeftRecursiveRuleAltInfo>();
|
r.recPrimaryAlts = new ArrayList<LeftRecursiveRuleAltInfo>();
|
||||||
r.recPrimaryAlts.addAll(leftRecursiveRuleWalker.prefixAlts);
|
r.recPrimaryAlts.addAll(leftRecursiveRuleWalker.prefixAlts);
|
||||||
r.recPrimaryAlts.addAll(leftRecursiveRuleWalker.otherAlts);
|
r.recPrimaryAlts.addAll(leftRecursiveRuleWalker.otherAlts);
|
||||||
|
if (r.recPrimaryAlts.isEmpty()) {
|
||||||
|
tool.errMgr.grammarError(ErrorType.NO_NON_LR_ALTS, g.fileName, ((GrammarAST)prevRuleAST.getChild(0)).getToken(), r.name);
|
||||||
|
}
|
||||||
|
|
||||||
r.recOpAlts = new OrderedHashMap<Integer, LeftRecursiveRuleAltInfo>();
|
r.recOpAlts = new OrderedHashMap<Integer, LeftRecursiveRuleAltInfo>();
|
||||||
r.recOpAlts.putAll(leftRecursiveRuleWalker.binaryAlts);
|
r.recOpAlts.putAll(leftRecursiveRuleWalker.binaryAlts);
|
||||||
r.recOpAlts.putAll(leftRecursiveRuleWalker.ternaryAlts);
|
r.recOpAlts.putAll(leftRecursiveRuleWalker.ternaryAlts);
|
||||||
|
|
|
@ -129,6 +129,7 @@ public enum ErrorType {
|
||||||
INVALID_LITERAL_IN_LEXER_SET(144, "multi-character literals are not allowed in lexer sets: <arg>", ErrorSeverity.ERROR),
|
INVALID_LITERAL_IN_LEXER_SET(144, "multi-character literals are not allowed in lexer sets: <arg>", ErrorSeverity.ERROR),
|
||||||
MODE_WITHOUT_RULES(145, "lexer mode '<arg>' must contain at least one non-fragment rule", ErrorSeverity.ERROR),
|
MODE_WITHOUT_RULES(145, "lexer mode '<arg>' must contain at least one non-fragment rule", ErrorSeverity.ERROR),
|
||||||
EPSILON_TOKEN(146, "non-fragment lexer rule '<arg>' can match the empty string", ErrorSeverity.ERROR),
|
EPSILON_TOKEN(146, "non-fragment lexer rule '<arg>' can match the empty string", ErrorSeverity.ERROR),
|
||||||
|
NO_NON_LR_ALTS(147, "left recursive rule '<arg>' must contain an alternative which is not left recursive", ErrorSeverity.ERROR),
|
||||||
|
|
||||||
// Backward incompatibility errors
|
// Backward incompatibility errors
|
||||||
V3_TREE_GRAMMAR(200, "tree grammars are not supported in ANTLR 4", ErrorSeverity.ERROR),
|
V3_TREE_GRAMMAR(200, "tree grammars are not supported in ANTLR 4", ErrorSeverity.ERROR),
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
package org.antlr.v4.test;
|
package org.antlr.v4.test;
|
||||||
|
|
||||||
|
import org.antlr.v4.tool.ErrorType;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
@ -373,6 +374,19 @@ public class TestLeftRecursion extends BaseTest {
|
||||||
stderrDuringParse);
|
stderrDuringParse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void testCheckForNonLeftRecursiveRule() throws Exception {
|
||||||
|
String grammar =
|
||||||
|
"grammar T;\n" +
|
||||||
|
"s @after {System.out.println($ctx.toStringTree(this));} : a ;\n" +
|
||||||
|
"a : a ID\n" +
|
||||||
|
" ;\n" +
|
||||||
|
"ID : 'a'..'z'+ ;\n" +
|
||||||
|
"WS : (' '|'\\n') -> skip ;\n";
|
||||||
|
String expected =
|
||||||
|
"error(" + ErrorType.NO_NON_LR_ALTS.code + "): T.g4:3:0: left recursive rule 'a' must contain an alternative which is not left recursive\n";
|
||||||
|
testErrors(new String[] { grammar, expected }, false);
|
||||||
|
}
|
||||||
|
|
||||||
public void runTests(String grammar, String[] tests, String startRule) {
|
public void runTests(String grammar, String[] tests, String startRule) {
|
||||||
rawGenerateAndBuildRecognizer("T.g4", grammar, "TParser", "TLexer");
|
rawGenerateAndBuildRecognizer("T.g4", grammar, "TParser", "TLexer");
|
||||||
writeRecognizerAndCompile("TParser",
|
writeRecognizerAndCompile("TParser",
|
||||||
|
|
Loading…
Reference in New Issue