1 /*
2  * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
3  * Use of this file is governed by the BSD 3-clause license that
4  * can be found in the LICENSE.txt file in the project root.
5  */
6 
7 package org.antlr.v4.test.tool;
8 
9 import org.antlr.v4.tool.ErrorType;
10 import org.junit.Before;
11 import org.junit.Test;
12 
13 /** */
14 public class TestLeftRecursionToolIssues extends BaseJavaToolTest {
15 	protected boolean debug = false;
16 
17 	@Before
18 	@Override
testSetUp()19 	public void testSetUp() throws Exception {
20 		super.testSetUp();
21 	}
22 
testCheckForNonLeftRecursiveRule()23 	@Test public void testCheckForNonLeftRecursiveRule() throws Exception {
24 		String grammar =
25 			"grammar T;\n" +
26 			"s @after {System.out.println($ctx.toStringTree(this));} : a ;\n" +
27 			"a : a ID\n" +
28 			"  ;\n" +
29 			"ID : 'a'..'z'+ ;\n" +
30 			"WS : (' '|'\\n') -> skip ;\n";
31 		String expected =
32 			"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";
33 		testErrors(new String[] { grammar, expected }, false);
34 	}
35 
testCheckForLeftRecursiveEmptyFollow()36 	@Test public void testCheckForLeftRecursiveEmptyFollow() throws Exception {
37 		String grammar =
38 			"grammar T;\n" +
39 			"s @after {System.out.println($ctx.toStringTree(this));} : a ;\n" +
40 			"a : a ID?\n" +
41 			"  | ID\n" +
42 			"  ;\n" +
43 			"ID : 'a'..'z'+ ;\n" +
44 			"WS : (' '|'\\n') -> skip ;\n";
45 		String expected =
46 			"error(" + ErrorType.EPSILON_LR_FOLLOW.code + "): T.g4:3:0: left recursive rule a contains a left recursive alternative which can be followed by the empty string\n";
47 		testErrors(new String[] { grammar, expected }, false);
48 	}
49 
50 	/** Reproduces https://github.com/antlr/antlr4/issues/855 */
testLeftRecursiveRuleRefWithArg()51 	@Test public void testLeftRecursiveRuleRefWithArg() throws Exception {
52 		String grammar =
53 			"grammar T;\n" +
54 			"statement\n" +
55 			"locals[Scope scope]\n" +
56 			"    : expressionA[$scope] ';'\n" +
57 			"    ;\n" +
58 			"expressionA[Scope scope]\n" +
59 			"    : atom[$scope]\n" +
60 			"    | expressionA[$scope] '[' expressionA[$scope] ']'\n" +
61 			"    ;\n" +
62 			"atom[Scope scope]\n" +
63 			"    : 'dummy'\n" +
64 			"    ;\n";
65 		String expected =
66 			"error(" + ErrorType.NONCONFORMING_LR_RULE.code + "): T.g4:6:0: rule expressionA is left recursive but doesn't conform to a pattern ANTLR can handle\n";
67 		testErrors(new String[]{grammar, expected}, false);
68 	}
69 
70 	/** Reproduces https://github.com/antlr/antlr4/issues/855 */
testLeftRecursiveRuleRefWithArg2()71 	@Test public void testLeftRecursiveRuleRefWithArg2() throws Exception {
72 		String grammar =
73 			"grammar T;\n" +
74 			"a[int i] : 'x'\n" +
75 			"  | a[3] 'y'\n" +
76 			"  ;";
77 		String expected =
78 			"error(" + ErrorType.NONCONFORMING_LR_RULE.code + "): T.g4:2:0: rule a is left recursive but doesn't conform to a pattern ANTLR can handle\n";
79 		testErrors(new String[]{grammar, expected}, false);
80 	}
81 
82 	/** Reproduces https://github.com/antlr/antlr4/issues/855 */
testLeftRecursiveRuleRefWithArg3()83 	@Test public void testLeftRecursiveRuleRefWithArg3() throws Exception {
84 		String grammar =
85 			"grammar T;\n" +
86 			"a : 'x'\n" +
87 			"  | a[3] 'y'\n" +
88 			"  ;";
89 		String expected =
90 			"error(" + ErrorType.NONCONFORMING_LR_RULE.code + "): T.g4:2:0: rule a is left recursive but doesn't conform to a pattern ANTLR can handle\n";
91 		testErrors(new String[]{grammar, expected}, false);
92 	}
93 
94 	/** Reproduces https://github.com/antlr/antlr4/issues/822 */
testIsolatedLeftRecursiveRuleRef()95 	@Test public void testIsolatedLeftRecursiveRuleRef() throws Exception {
96 		String grammar =
97 			"grammar T;\n" +
98 			"a : a | b ;\n" +
99 			"b : 'B' ;\n";
100 		String expected =
101 			"error(" + ErrorType.NONCONFORMING_LR_RULE.code + "): T.g4:2:0: rule a is left recursive but doesn't conform to a pattern ANTLR can handle\n";
102 		testErrors(new String[]{grammar, expected}, false);
103 	}
104 
105 	/** Reproduces https://github.com/antlr/antlr4/issues/773 */
testArgOnPrimaryRuleInLeftRecursiveRule()106 	@Test public void testArgOnPrimaryRuleInLeftRecursiveRule() throws Exception {
107 		String grammar =
108 			"grammar T;\n" +
109 			"val: dval[1]\n" +
110 			"   | val '*' val\n" +
111 			"   ;\n" +
112 			"dval[int  x]: '.';\n";
113 		String expected = ""; // dval[1] should not be error
114 		testErrors(new String[]{grammar, expected}, false);
115 	}
116 }
117