• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.antlr.test;
2 
3 import org.junit.Ignore;
4 import org.junit.Test;
5 
6 import static org.junit.Assert.*;
7 
8 /** */
9 @Ignore
10 public class TestLeftRecursion extends BaseTest {
11 	protected boolean debug = false;
12 
testSimple()13 	@Test public void testSimple() throws Exception {
14 		String grammar =
15 			"grammar T;\n" +
16 			"s : a {System.out.println($a.text);} ;\n" +
17 			"a : a ID\n" +
18 			"  | ID" +
19 			"  ;\n" +
20 			"ID : 'a'..'z'+ ;\n" +
21 			"WS : (' '|'\\n') {skip();} ;\n";
22 		String found = execParser("T.g", grammar, "TParser", "TLexer",
23 								  "s", "a b c", debug);
24 		String expecting = "abc\n";
25 		assertEquals(expecting, found);
26 	}
27 
testSemPred()28 	@Test public void testSemPred() throws Exception {
29 		String grammar =
30 			"grammar T;\n" +
31 			"s : a {System.out.println($a.text);} ;\n" +
32 			"a : a {true}? ID\n" +
33 			"  | ID" +
34 			"  ;\n" +
35 			"ID : 'a'..'z'+ ;\n" +
36 			"WS : (' '|'\\n') {skip();} ;\n";
37 		String found = execParser("T.g", grammar, "TParser", "TLexer",
38 								  "s", "a b c", debug);
39 		String expecting = "abc\n";
40 		assertEquals(expecting, found);
41 	}
42 
testTernaryExpr()43 	@Test public void testTernaryExpr() throws Exception {
44 		String grammar =
45 			"grammar T;\n" +
46 			"options {output=AST;}\n" +
47 			"e : e '*'^ e" +
48 			"  | e '+'^ e" +
49 			"  | e '?'<assoc=right>^ e ':'! e" +
50 			"  | e '='<assoc=right>^ e" +
51 			"  | ID" +
52 			"  ;\n" +
53 			"ID : 'a'..'z'+ ;\n" +
54 			"WS : (' '|'\\n') {skip();} ;\n";
55 		String[] tests = {
56 			"a",			"a",
57 			"a+b",			"(+ a b)",
58 			"a*b",			"(* a b)",
59 			"a?b:c",		"(? a b c)",
60 			"a=b=c",		"(= a (= b c))",
61 			"a?b+c:d",		"(? a (+ b c) d)",
62 			"a?b=c:d",		"(? a (= b c) d)",
63 			"a? b?c:d : e",	"(? a (? b c d) e)",
64 			"a?b: c?d:e",	"(? a b (? c d e))",
65 		};
66 		runTests(grammar, tests, "e");
67 	}
68 
testDeclarationsUsingASTOperators()69 	@Test public void testDeclarationsUsingASTOperators() throws Exception {
70 		String grammar =
71 			"grammar T;\n" +
72 			"options {output=AST;}\n" +
73 			"declarator\n" +
74 			"        : declarator '['^ e ']'!\n" +
75 			"        | declarator '['^ ']'!\n" +
76 			"        | declarator '('^ ')'!\n" +
77 			"        | '*'^ declarator\n" + // binds less tight than suffixes
78 			"        | '('! declarator ')'!\n" +
79 			"        | ID\n" +
80 			"        ;\n" +
81 			"e : INT ;\n" +
82 			"ID : 'a'..'z'+ ;\n" +
83 			"INT : '0'..'9'+ ;\n" +
84 			"WS : (' '|'\\n') {skip();} ;\n";
85 		String[] tests = {
86 			"a",		"a",
87 			"*a",		"(* a)",
88 			"**a",		"(* (* a))",
89 			"a[3]",		"([ a 3)",
90 			"b[]",		"([ b)",
91 			"(a)",		"a",
92 			"a[]()",	"(( ([ a))",
93 			"a[][]",	"([ ([ a))",
94 			"*a[]",		"(* ([ a))",
95 			"(*a)[]",	"([ (* a))",
96 		};
97 		runTests(grammar, tests, "declarator");
98 	}
99 
testDeclarationsUsingRewriteOperators()100 	@Test public void testDeclarationsUsingRewriteOperators() throws Exception {
101 		String grammar =
102 			"grammar T;\n" +
103 			"options {output=AST;}\n" +
104 			"declarator\n" +
105 			"        : declarator '[' e ']' -> ^('[' declarator e)\n" +
106 			"        | declarator '[' ']' -> ^('[' declarator)\n" +
107 			"        | declarator '(' ')' -> ^('(' declarator)\n" +
108 			"        | '*' declarator -> ^('*' declarator) \n" + // binds less tight than suffixes
109 			"        | '(' declarator ')' -> declarator\n" +
110 			"        | ID -> ID\n" +
111 			"        ;\n" +
112 			"e : INT ;\n" +
113 			"ID : 'a'..'z'+ ;\n" +
114 			"INT : '0'..'9'+ ;\n" +
115 			"WS : (' '|'\\n') {skip();} ;\n";
116 		String[] tests = {
117 			"a",		"a",
118 			"*a",		"(* a)",
119 			"**a",		"(* (* a))",
120 			"a[3]",		"([ a 3)",
121 			"b[]",		"([ b)",
122 			"(a)",		"a",
123 			"a[]()",	"(( ([ a))",
124 			"a[][]",	"([ ([ a))",
125 			"*a[]",		"(* ([ a))",
126 			"(*a)[]",	"([ (* a))",
127 		};
128 		runTests(grammar, tests, "declarator");
129 	}
130 
testExpressionsUsingASTOperators()131 	@Test public void testExpressionsUsingASTOperators() throws Exception {
132 		String grammar =
133 			"grammar T;\n" +
134 			"options {output=AST;}\n" +
135 			"e : e '.'^ ID\n" +
136 			"  | e '.'^ 'this'\n" +
137 			"  | '-'^ e\n" +
138 			"  | e '*'^ e\n" +
139 			"  | e ('+'^|'-'^) e\n" +
140 			"  | INT\n" +
141 			"  | ID\n" +
142 			"  ;\n" +
143 			"ID : 'a'..'z'+ ;\n" +
144 			"INT : '0'..'9'+ ;\n" +
145 			"WS : (' '|'\\n') {skip();} ;\n";
146 		String[] tests = {
147 			"a",		"a",
148 			"1",		"1",
149 			"a+1",		"(+ a 1)",
150 			"a*1",		"(* a 1)",
151 			"a.b",		"(. a b)",
152 			"a.this",	"(. a this)",
153 			"a-b+c",	"(+ (- a b) c)",
154 			"a+b*c",	"(+ a (* b c))",
155 			"a.b+1",	"(+ (. a b) 1)",
156 			"-a",		"(- a)",
157 			"-a+b",		"(+ (- a) b)",
158 			"-a.b",		"(- (. a b))",
159 		};
160 		runTests(grammar, tests, "e");
161 	}
162 
testExpressionsUsingRewriteOperators()163 	@Test public void testExpressionsUsingRewriteOperators() throws Exception {
164 		String grammar =
165 			"grammar T;\n" +
166 			"options {output=AST;}\n" +
167 			"e : e '.' ID 				-> ^('.' e ID)\n" +
168 			"  | e '.' 'this' 			-> ^('.' e 'this')\n" +
169 			"  | '-' e 					-> ^('-' e)\n" +
170 			"  | e '*' b=e 				-> ^('*' e $b)\n" +
171 			"  | e (op='+'|op='-') b=e	-> ^($op e $b)\n" +
172 			"  | INT 					-> INT\n" +
173 			"  | ID 					-> ID\n" +
174 			"  ;\n" +
175 			"ID : 'a'..'z'+ ;\n" +
176 			"INT : '0'..'9'+ ;\n" +
177 			"WS : (' '|'\\n') {skip();} ;\n";
178 		String[] tests = {
179 			"a",		"a",
180 			"1",		"1",
181 			"a+1",		"(+ a 1)",
182 			"a*1",		"(* a 1)",
183 			"a.b",		"(. a b)",
184 			"a.this",	"(. a this)",
185 			"a+b*c",	"(+ a (* b c))",
186 			"a.b+1",	"(+ (. a b) 1)",
187 			"-a",		"(- a)",
188 			"-a+b",		"(+ (- a) b)",
189 			"-a.b",		"(- (. a b))",
190 		};
191 		runTests(grammar, tests, "e");
192 	}
193 
testExpressionAssociativity()194 	@Test public void testExpressionAssociativity() throws Exception {
195 		String grammar =
196 			"grammar T;\n" +
197 			"options {output=AST;}\n" +
198 			"e\n" +
199 			"  : e '.'^ ID\n" +
200 			"  | '-'^ e\n" +
201 			"  | e '^'<assoc=right>^ e\n" +
202 			"  | e '*'^ e\n" +
203 			"  | e ('+'^|'-'^) e\n" +
204 			"  | e ('='<assoc=right>^ |'+='<assoc=right>^) e\n" +
205 			"  | INT\n" +
206 			"  | ID\n" +
207 			"  ;\n" +
208 			"ID : 'a'..'z'+ ;\n" +
209 			"INT : '0'..'9'+ ;\n" +
210 			"WS : (' '|'\\n') {skip();} ;\n";
211 		String[] tests = {
212 			"a",		"a",
213 			"1",		"1",
214 			"a+1",		"(+ a 1)",
215 			"a*1",		"(* a 1)",
216 			"a.b",		"(. a b)",
217 			"a-b+c",	"(+ (- a b) c)",
218 
219 			"a+b*c",	"(+ a (* b c))",
220 			"a.b+1",	"(+ (. a b) 1)",
221 			"-a",		"(- a)",
222 			"-a+b",		"(+ (- a) b)",
223 			"-a.b",		"(- (. a b))",
224 			"a^b^c",	"(^ a (^ b c))",
225 			"a=b=c",	"(= a (= b c))",
226 			"a=b=c+d.e","(= a (= b (+ c (. d e))))",
227 		};
228 		runTests(grammar, tests, "e");
229 	}
230 
testJavaExpressions()231 	@Test public void testJavaExpressions() throws Exception {
232 		// Generates about 7k in bytecodes for generated e_ rule;
233 		// Well within the 64k method limit. e_primary compiles
234 		// to about 2k in bytecodes.
235 		// this is simplified from real java
236 		String grammar =
237 			"grammar T;\n" +
238 			"options {output=AST;}\n" +
239 			"expressionList\n" +
240 			"    :   e (','! e)*\n" +
241 			"    ;\n" +
242 			"e   :   '('! e ')'!\n" +
243 			"    |   'this' \n" +
244 			"    |   'super'\n" +
245 			"    |   INT\n" +
246 			"    |   ID\n" +
247 			"    |   type '.'^ 'class'\n" +
248 			"    |   e '.'^ ID\n" +
249 			"    |   e '.'^ 'this'\n" +
250 			"    |   e '.'^ 'super' '('^ expressionList? ')'!\n" +
251 			"    |   e '.'^ 'new'^ ID '('! expressionList? ')'!\n" +
252 			"	 |	 'new'^ type ( '(' expressionList? ')'! | (options {k=1;}:'[' e ']'!)+)\n" + // ugly; simplified
253 			"    |   e '['^ e ']'!\n" +
254 			"    |   '('^ type ')'! e\n" +
255 			"    |   e ('++'^ | '--'^)\n" +
256 			"    |   e '('^ expressionList? ')'!\n" +
257 			"    |   ('+'^|'-'^|'++'^|'--'^) e\n" +
258 			"    |   ('~'^|'!'^) e\n" +
259 			"    |   e ('*'^|'/'^|'%'^) e\n" +
260 			"    |   e ('+'^|'-'^) e\n" +
261 			"    |   e ('<'^ '<' | '>'^ '>' '>' | '>'^ '>') e\n" +
262 			"    |   e ('<='^ | '>='^ | '>'^ | '<'^) e\n" +
263 			"    |   e 'instanceof'^ e\n" +
264 			"    |   e ('=='^ | '!='^) e\n" +
265 			"    |   e '&'^ e\n" +
266 			"    |   e '^'<assoc=right>^ e\n" +
267 			"    |   e '|'^ e\n" +
268 			"    |   e '&&'^ e\n" +
269 			"    |   e '||'^ e\n" +
270 			"    |   e '?' e ':' e\n" +
271 			"    |   e ('='<assoc=right>^\n" +
272 			"          |'+='<assoc=right>^\n" +
273 			"          |'-='<assoc=right>^\n" +
274 			"          |'*='<assoc=right>^\n" +
275 			"          |'/='<assoc=right>^\n" +
276 			"          |'&='<assoc=right>^\n" +
277 			"          |'|='<assoc=right>^\n" +
278 			"          |'^='<assoc=right>^\n" +
279 			"          |'>>='<assoc=right>^\n" +
280 			"          |'>>>='<assoc=right>^\n" +
281 			"          |'<<='<assoc=right>^\n" +
282 			"          |'%='<assoc=right>^) e\n" +
283 			"    ;\n" +
284 			"type: ID \n" +
285 			"    | ID '['^ ']'!\n" +
286 			"    | 'int'\n" +
287 			"	 | 'int' '['^ ']'! \n" +
288 			"    ;\n" +
289 			"ID : ('a'..'z'|'A'..'Z'|'_'|'$')+;\n" +
290 			"INT : '0'..'9'+ ;\n" +
291 			"WS : (' '|'\\n') {skip();} ;\n";
292 		String[] tests = {
293 			"a",		"a",
294 			"1",		"1",
295 			"a+1",		"(+ a 1)",
296 			"a*1",		"(* a 1)",
297 			"a.b",		"(. a b)",
298 			"a-b+c",	"(+ (- a b) c)",
299 
300 			"a+b*c",	"(+ a (* b c))",
301 			"a.b+1",	"(+ (. a b) 1)",
302 			"-a",		"(- a)",
303 			"-a+b",		"(+ (- a) b)",
304 			"-a.b",		"(- (. a b))",
305 			"a^b^c",	"(^ a (^ b c))",
306 			"a=b=c",	"(= a (= b c))",
307 			"a=b=c+d.e","(= a (= b (+ c (. d e))))",
308 			"a|b&c",	"(| a (& b c))",
309 			"(a|b)&c",	"(& (| a b) c)",
310 			"a > b",	"(> a b)",
311 			"a >> b",	"(> a b)",  // text is from one token
312 			"a < b",	"(< a b)",
313 
314 			"(T)x",							"(( T x)",
315 			"new A().b",					"(. (new A () b)",
316 			"(T)t.f()",						"(( (( T (. t f)))",
317 			"a.f(x)==T.c",					"(== (( (. a f) x) (. T c))",
318 			"a.f().g(x,1)",					"(( (. (( (. a f)) g) x 1)",
319 			"new T[((n-1) * x) + 1]",		"(new T [ (+ (* (- n 1) x) 1))",
320 		};
321 		runTests(grammar, tests, "e");
322 	}
323 
testReturnValueAndActions()324 	@Test public void testReturnValueAndActions() throws Exception {
325 		String grammar =
326 			"grammar T;\n" +
327 			"s : e {System.out.println($e.v);} ;\n" +
328 			"e returns [int v, List<String> ignored]\n" +
329 			"  : e '*' b=e {$v *= $b.v;}\n" +
330 			"  | e '+' b=e {$v += $b.v;}\n" +
331 			"  | INT {$v = $INT.int;}\n" +
332 			"  ;\n" +
333 			"INT : '0'..'9'+ ;\n" +
334 			"WS : (' '|'\\n') {skip();} ;\n";
335 		String[] tests = {
336 			"4",			"4",
337 			"1+2",			"3",
338 		};
339 		runTests(grammar, tests, "s");
340 	}
341 
testReturnValueAndActionsAndASTs()342 	@Test public void testReturnValueAndActionsAndASTs() throws Exception {
343 		String grammar =
344 			"grammar T;\n" +
345 			"options {output=AST;}\n" +
346 			"s : e {System.out.print(\"v=\"+$e.v+\", \");} ;\n" +
347 			"e returns [int v, List<String> ignored]\n" +
348 			"  : e '*'^ b=e {$v *= $b.v;}\n" +
349 			"  | e '+'^ b=e {$v += $b.v;}\n" +
350 			"  | INT {$v = $INT.int;}\n" +
351 			"  ;\n" +
352 			"INT : '0'..'9'+ ;\n" +
353 			"WS : (' '|'\\n') {skip();} ;\n";
354 		String[] tests = {
355 			"4",			"v=4, 4",
356 			"1+2",			"v=3, (+ 1 2)",
357 		};
358 		runTests(grammar, tests, "s");
359 	}
360 
runTests(String grammar, String[] tests, String startRule)361 	public void runTests(String grammar, String[] tests, String startRule) {
362 		rawGenerateAndBuildRecognizer("T.g", grammar, "TParser", "TLexer", debug);
363 		boolean parserBuildsTrees =
364 			grammar.indexOf("output=AST")>=0 ||
365 			grammar.indexOf("output = AST")>=0;
366 		writeRecognizerAndCompile("TParser",
367 										 null,
368 										 "TLexer",
369 										 startRule,
370 										 null,
371 										 parserBuildsTrees,
372 										 false,
373 										 false,
374 										 debug);
375 
376 		for (int i=0; i<tests.length; i+=2) {
377 			String test = tests[i];
378 			String expecting = tests[i+1]+"\n";
379 			writeFile(tmpdir, "input", test);
380 			String found = execRecognizer();
381 			System.out.print(test+" -> "+found);
382 			assertEquals(expecting, found);
383 		}
384 	}
385 
386 }
387