• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * [The "BSD license"]
3  *  Copyright (c) 2010 Terence Parr
4  *  All rights reserved.
5  *
6  *  Redistribution and use in source and binary forms, with or without
7  *  modification, are permitted provided that the following conditions
8  *  are met:
9  *  1. Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *      notice, this list of conditions and the following disclaimer in the
13  *      documentation and/or other materials provided with the distribution.
14  *  3. The name of the author may not be used to endorse or promote products
15  *      derived from this software without specific prior written permission.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 package org.antlr.test;
29 
30 import org.junit.Ignore;
31 import org.junit.Test;
32 
33 import static org.junit.Assert.*;
34 
35 public class TestAutoAST extends BaseTest {
36 	protected boolean debug = false;
37 
testTokenList()38 	@Test public void testTokenList() throws Exception {
39 		String grammar =
40 			"grammar foo;\n" +
41 			"options {output=AST;}\n" +
42 			"a : ID INT ;\n" +
43 			"ID : 'a'..'z'+ ;\n" +
44 			"INT : '0'..'9'+;\n" +
45 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
46 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
47 								  "a", "abc 34", debug);
48 		assertEquals("abc 34\n", found);
49 	}
50 
testTokenListInSingleAltBlock()51 	@Test public void testTokenListInSingleAltBlock() throws Exception {
52 		String grammar =
53 			"grammar foo;\n" +
54 			"options {output=AST;}\n" +
55 			"a : (ID INT) ;\n" +
56 			"ID : 'a'..'z'+ ;\n" +
57 			"INT : '0'..'9'+;\n" +
58 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
59 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
60 								  "a", "abc 34", debug);
61 		assertEquals("abc 34\n", found);
62 	}
63 
testSimpleRootAtOuterLevel()64 	@Test public void testSimpleRootAtOuterLevel() throws Exception {
65 		String grammar =
66 			"grammar foo;\n" +
67 			"options {output=AST;}\n" +
68 			"a : ID^ INT ;\n" +
69 			"ID : 'a'..'z'+ ;\n" +
70 			"INT : '0'..'9'+;\n" +
71 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
72 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
73 								  "a", "abc 34", debug);
74 		assertEquals("(abc 34)\n", found);
75 	}
76 
testSimpleRootAtOuterLevelReverse()77 	@Test public void testSimpleRootAtOuterLevelReverse() throws Exception {
78 		String grammar =
79 			"grammar T;\n" +
80 			"options {output=AST;}\n" +
81 			"a : INT ID^ ;\n" +
82 			"ID : 'a'..'z'+ ;\n" +
83 			"INT : '0'..'9'+;\n" +
84 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
85 		String found = execParser("T.g", grammar, "TParser", "TLexer",
86 								  "a", "34 abc", debug);
87 		assertEquals("(abc 34)\n", found);
88 	}
89 
testBang()90 	@Test public void testBang() throws Exception {
91 		String grammar =
92 			"grammar T;\n" +
93 			"options {output=AST;}\n" +
94 			"a : ID INT! ID! INT ;\n" +
95 			"ID : 'a'..'z'+ ;\n" +
96 			"INT : '0'..'9'+;\n" +
97 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
98 		String found = execParser("T.g", grammar, "TParser", "TLexer",
99 								  "a", "abc 34 dag 4532", debug);
100 		assertEquals("abc 4532\n", found);
101 	}
102 
testOptionalThenRoot()103 	@Test public void testOptionalThenRoot() throws Exception {
104 		String grammar =
105 			"grammar T;\n" +
106 			"options {output=AST;}\n" +
107 			"a : ( ID INT )? ID^ ;\n" +
108 			"ID : 'a'..'z'+ ;\n" +
109 			"INT : '0'..'9'+;\n" +
110 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
111 		String found = execParser("T.g", grammar, "TParser", "TLexer",
112 								  "a", "a 1 b", debug);
113 		assertEquals("(b a 1)\n", found);
114 	}
115 
testLabeledStringRoot()116 	@Test public void testLabeledStringRoot() throws Exception {
117 		String grammar =
118 			"grammar T;\n" +
119 			"options {output=AST;}\n" +
120 			"a : v='void'^ ID ';' ;\n" +
121 			"ID : 'a'..'z'+ ;\n" +
122 			"INT : '0'..'9'+;\n" +
123 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
124 		String found = execParser("T.g", grammar, "TParser", "TLexer",
125 								  "a", "void foo;", debug);
126 		assertEquals("(void foo ;)\n", found);
127 	}
128 
testWildcard()129 	@Test public void testWildcard() throws Exception {
130 		String grammar =
131 			"grammar T;\n" +
132 			"options {output=AST;}\n" +
133 			"a : v='void'^ . ';' ;\n" +
134 			"ID : 'a'..'z'+ ;\n" +
135 			"INT : '0'..'9'+;\n" +
136 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
137 		String found = execParser("T.g", grammar, "TParser", "TLexer",
138 								  "a", "void foo;", debug);
139 		assertEquals("(void foo ;)\n", found);
140 	}
141 
testWildcardRoot()142 	@Test public void testWildcardRoot() throws Exception {
143 		String grammar =
144 			"grammar T;\n" +
145 			"options {output=AST;}\n" +
146 			"a : v='void' .^ ';' ;\n" +
147 			"ID : 'a'..'z'+ ;\n" +
148 			"INT : '0'..'9'+;\n" +
149 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
150 		String found = execParser("T.g", grammar, "TParser", "TLexer",
151 								  "a", "void foo;", debug);
152 		assertEquals("(foo void ;)\n", found);
153 	}
154 
testWildcardRootWithLabel()155 	@Test public void testWildcardRootWithLabel() throws Exception {
156 		String grammar =
157 			"grammar T;\n" +
158 			"options {output=AST;}\n" +
159 			"a : v='void' x=.^ ';' ;\n" +
160 			"ID : 'a'..'z'+ ;\n" +
161 			"INT : '0'..'9'+;\n" +
162 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
163 		String found = execParser("T.g", grammar, "TParser", "TLexer",
164 								  "a", "void foo;", debug);
165 		assertEquals("(foo void ;)\n", found);
166 	}
167 
testWildcardRootWithListLabel()168     @Test public void testWildcardRootWithListLabel() throws Exception {
169         String grammar =
170             "grammar T;\n" +
171             "options {output=AST;}\n" +
172             "a : v='void' x=.^ ';' ;\n" +
173             "ID : 'a'..'z'+ ;\n" +
174             "INT : '0'..'9'+;\n" +
175             "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
176         String found = execParser("T.g", grammar, "TParser", "TLexer",
177                                   "a", "void foo;", debug);
178         assertEquals("(foo void ;)\n", found);
179     }
180 
testWildcardBangWithListLabel()181     @Test public void testWildcardBangWithListLabel() throws Exception {
182         String grammar =
183             "grammar T;\n" +
184             "options {output=AST;}\n" +
185             "a : v='void' x=.! ';' ;\n" +
186             "ID : 'a'..'z'+ ;\n" +
187             "INT : '0'..'9'+;\n" +
188             "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
189         String found = execParser("T.g", grammar, "TParser", "TLexer",
190                                   "a", "void foo;", debug);
191         assertEquals("void ;\n", found);
192     }
193 
testRootRoot()194 	@Test public void testRootRoot() throws Exception {
195 		String grammar =
196 			"grammar T;\n" +
197 			"options {output=AST;}\n" +
198 			"a : ID^ INT^ ID ;\n" +
199 			"ID : 'a'..'z'+ ;\n" +
200 			"INT : '0'..'9'+;\n" +
201 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
202 		String found = execParser("T.g", grammar, "TParser", "TLexer",
203 								  "a", "a 34 c", debug);
204 		assertEquals("(34 a c)\n", found);
205 	}
206 
testRootRoot2()207 	@Test public void testRootRoot2() throws Exception {
208 		String grammar =
209 			"grammar T;\n" +
210 			"options {output=AST;}\n" +
211 			"a : ID INT^ ID^ ;\n" +
212 			"ID : 'a'..'z'+ ;\n" +
213 			"INT : '0'..'9'+;\n" +
214 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
215 		String found = execParser("T.g", grammar, "TParser", "TLexer",
216 								  "a", "a 34 c", debug);
217 		assertEquals("(c (34 a))\n", found);
218 	}
219 
testRootThenRootInLoop()220 	@Test public void testRootThenRootInLoop() throws Exception {
221 		String grammar =
222 			"grammar T;\n" +
223 			"options {output=AST;}\n" +
224 			"a : ID^ (INT '*'^ ID)+ ;\n" +
225 			"ID  : 'a'..'z'+ ;\n" +
226 			"INT : '0'..'9'+;\n" +
227 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
228 		String found = execParser("T.g", grammar, "TParser", "TLexer",
229 								  "a", "a 34 * b 9 * c", debug);
230 		assertEquals("(* (* (a 34) b 9) c)\n", found);
231 	}
232 
testNestedSubrule()233 	@Test public void testNestedSubrule() throws Exception {
234 		String grammar =
235 			"grammar T;\n" +
236 			"options {output=AST;}\n" +
237 			"a : 'void' (({;}ID|INT) ID | 'null' ) ';' ;\n" +
238 			"ID : 'a'..'z'+ ;\n" +
239 			"INT : '0'..'9'+;\n" +
240 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
241 		String found = execParser("T.g", grammar, "TParser", "TLexer",
242 								  "a", "void a b;", debug);
243 		assertEquals("void a b ;\n", found);
244 	}
245 
testInvokeRule()246 	@Test public void testInvokeRule() throws Exception {
247 		String grammar =
248 			"grammar T;\n" +
249 			"options {output=AST;}\n" +
250 			"a  : type ID ;\n" +
251 			"type : {;}'int' | 'float' ;\n" +
252 			"ID : 'a'..'z'+ ;\n" +
253 			"INT : '0'..'9'+;\n" +
254 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
255 		String found = execParser("T.g", grammar, "TParser", "TLexer",
256 								  "a", "int a", debug);
257 		assertEquals("int a\n", found);
258 	}
259 
testInvokeRuleAsRoot()260 	@Test public void testInvokeRuleAsRoot() throws Exception {
261 		String grammar =
262 			"grammar T;\n" +
263 			"options {output=AST;}\n" +
264 			"a  : type^ ID ;\n" +
265 			"type : {;}'int' | 'float' ;\n" +
266 			"ID : 'a'..'z'+ ;\n" +
267 			"INT : '0'..'9'+;\n" +
268 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
269 		String found = execParser("T.g", grammar, "TParser", "TLexer",
270 								  "a", "int a", debug);
271 		assertEquals("(int a)\n", found);
272 	}
273 
testInvokeRuleAsRootWithLabel()274 	@Test public void testInvokeRuleAsRootWithLabel() throws Exception {
275 		String grammar =
276 			"grammar T;\n" +
277 			"options {output=AST;}\n" +
278 			"a  : x=type^ ID ;\n" +
279 			"type : {;}'int' | 'float' ;\n" +
280 			"ID : 'a'..'z'+ ;\n" +
281 			"INT : '0'..'9'+;\n" +
282 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
283 		String found = execParser("T.g", grammar, "TParser", "TLexer",
284 								  "a", "int a", debug);
285 		assertEquals("(int a)\n", found);
286 	}
287 
testInvokeRuleAsRootWithListLabel()288 	@Test public void testInvokeRuleAsRootWithListLabel() throws Exception {
289 		String grammar =
290 			"grammar T;\n" +
291 			"options {output=AST;}\n" +
292 			"a  : x+=type^ ID ;\n" +
293 			"type : {;}'int' | 'float' ;\n" +
294 			"ID : 'a'..'z'+ ;\n" +
295 			"INT : '0'..'9'+;\n" +
296 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
297 		String found = execParser("T.g", grammar, "TParser", "TLexer",
298 								  "a", "int a", debug);
299 		assertEquals("(int a)\n", found);
300 	}
301 
testRuleRootInLoop()302 	@Test public void testRuleRootInLoop() throws Exception {
303 		String grammar =
304 			"grammar T;\n" +
305 			"options {output=AST;}\n" +
306 			"a : ID ('+'^ ID)* ;\n" +
307 			"ID : 'a'..'z'+ ;\n" +
308 			"INT : '0'..'9'+;\n" +
309 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
310 		String found = execParser("T.g", grammar, "TParser", "TLexer",
311 								  "a", "a+b+c+d", debug);
312 		assertEquals("(+ (+ (+ a b) c) d)\n", found);
313 	}
314 
testRuleInvocationRuleRootInLoop()315 	@Test public void testRuleInvocationRuleRootInLoop() throws Exception {
316 		String grammar =
317 			"grammar T;\n" +
318 			"options {output=AST;}\n" +
319 			"a : ID (op^ ID)* ;\n" +
320 			"op : {;}'+' | '-' ;\n" +
321 			"ID : 'a'..'z'+ ;\n" +
322 			"INT : '0'..'9'+;\n" +
323 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
324 		String found = execParser("T.g", grammar, "TParser", "TLexer",
325 								  "a", "a+b+c-d", debug);
326 		assertEquals("(- (+ (+ a b) c) d)\n", found);
327 	}
328 
testTailRecursion()329 	@Test public void testTailRecursion() throws Exception {
330 		String grammar =
331 			"grammar T;\n" +
332 			"options {output=AST;}\n" +
333 			"s : a ;\n" +
334 			"a : atom ('exp'^ a)? ;\n" +
335 			"atom : INT ;\n" +
336 			"ID : 'a'..'z'+ ;\n" +
337 			"INT : '0'..'9'+;\n" +
338 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
339 		String found = execParser("T.g", grammar, "TParser", "TLexer",
340 								  "s", "3 exp 4 exp 5", debug);
341 		assertEquals("(exp 3 (exp 4 5))\n", found);
342 	}
343 
testSet()344 	@Test public void testSet() throws Exception {
345 		String grammar =
346 			"grammar T;\n" +
347 			"options {output=AST;}\n" +
348 			"a : ID|INT ;\n" +
349 			"ID : 'a'..'z'+ ;\n" +
350 			"INT : '0'..'9'+;\n" +
351 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
352 		String found = execParser("T.g", grammar, "TParser", "TLexer",
353 								  "a", "abc", debug);
354 		assertEquals("abc\n", found);
355 	}
356 
testSetRoot()357 	@Test public void testSetRoot() throws Exception {
358 		String grammar =
359 			"grammar T;\n" +
360 			"options {output=AST;}\n" +
361 			"a : ('+' | '-')^ ID ;\n" +
362 			"ID : 'a'..'z'+ ;\n" +
363 			"INT : '0'..'9'+;\n" +
364 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
365 		String found = execParser("T.g", grammar, "TParser", "TLexer",
366 								  "a", "+abc", debug);
367 		assertEquals("(+ abc)\n", found);
368 	}
369 
370 	@Test
testSetRootWithLabel()371     public void testSetRootWithLabel() throws Exception {
372 
373 		String grammar =
374 			"grammar T;\n" +
375 			"options {output=AST;}\n" +
376 			"a : x=('+' | '-')^ ID ;\n" +
377 			"ID : 'a'..'z'+ ;\n" +
378 			"INT : '0'..'9'+;\n" +
379 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
380 		String found = execParser("T.g", grammar, "TParser", "TLexer",
381 								  "a", "+abc", debug);
382 		assertEquals("(+ abc)\n", found);
383 	}
384 
testSetAsRuleRootInLoop()385 	@Test public void testSetAsRuleRootInLoop() throws Exception {
386 		String grammar =
387 			"grammar T;\n" +
388 			"options {output=AST;}\n" +
389 			"a : ID (('+'|'-')^ ID)* ;\n" +
390 			"ID : 'a'..'z'+ ;\n" +
391 			"INT : '0'..'9'+;\n" +
392 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
393 		String found = execParser("T.g", grammar, "TParser", "TLexer",
394 								  "a", "a+b-c", debug);
395 		assertEquals("(- (+ a b) c)\n", found);
396 	}
397 
testNotSet()398 	@Test public void testNotSet() throws Exception {
399 		String grammar =
400 			"grammar T;\n" +
401 			"options {output=AST;}\n" +
402 			"a : ~ID '+' INT ;\n" +
403 			"ID : 'a'..'z'+ ;\n" +
404 			"INT : '0'..'9'+;\n" +
405 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
406 		String found = execParser("T.g", grammar, "TParser", "TLexer",
407 								  "a", "34+2", debug);
408 		assertEquals("34 + 2\n", found);
409 	}
410 
testNotSetWithLabel()411 	@Test public void testNotSetWithLabel() throws Exception {
412 		String grammar =
413 			"grammar T;\n" +
414 			"options {output=AST;}\n" +
415 			"a : x=~ID '+' INT ;\n" +
416 			"ID : 'a'..'z'+ ;\n" +
417 			"INT : '0'..'9'+;\n" +
418 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
419 		String found = execParser("T.g", grammar, "TParser", "TLexer",
420 								  "a", "34+2", debug);
421 		assertEquals("34 + 2\n", found);
422 	}
423 
testNotSetWithListLabel()424 	@Test public void testNotSetWithListLabel() throws Exception {
425 		String grammar =
426 			"grammar T;\n" +
427 			"options {output=AST;}\n" +
428 			"a : x=~ID '+' INT ;\n" +
429 			"ID : 'a'..'z'+ ;\n" +
430 			"INT : '0'..'9'+;\n" +
431 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
432 		String found = execParser("T.g", grammar, "TParser", "TLexer",
433 								  "a", "34+2", debug);
434 		assertEquals("34 + 2\n", found);
435 	}
436 
testNotSetRoot()437 	@Test public void testNotSetRoot() throws Exception {
438 		String grammar =
439 			"grammar T;\n" +
440 			"options {output=AST;}\n" +
441 			"a : ~'+'^ INT ;\n" +
442 			"ID : 'a'..'z'+ ;\n" +
443 			"INT : '0'..'9'+;\n" +
444 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
445 		String found = execParser("T.g", grammar, "TParser", "TLexer",
446 								  "a", "34 55", debug);
447 		assertEquals("(34 55)\n", found);
448 	}
449 
testNotSetRootWithLabel()450 	@Test public void testNotSetRootWithLabel() throws Exception {
451 		String grammar =
452 			"grammar T;\n" +
453 			"options {output=AST;}\n" +
454 			"a : ~'+'^ INT ;\n" +
455 			"ID : 'a'..'z'+ ;\n" +
456 			"INT : '0'..'9'+;\n" +
457 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
458 		String found = execParser("T.g", grammar, "TParser", "TLexer",
459 								  "a", "34 55", debug);
460 		assertEquals("(34 55)\n", found);
461 	}
462 
testNotSetRootWithListLabel()463 	@Test public void testNotSetRootWithListLabel() throws Exception {
464 		String grammar =
465 			"grammar T;\n" +
466 			"options {output=AST;}\n" +
467 			"a : ~'+'^ INT ;\n" +
468 			"ID : 'a'..'z'+ ;\n" +
469 			"INT : '0'..'9'+;\n" +
470 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
471 		String found = execParser("T.g", grammar, "TParser", "TLexer",
472 								  "a", "34 55", debug);
473 		assertEquals("(34 55)\n", found);
474 	}
475 
testNotSetRuleRootInLoop()476 	@Test public void testNotSetRuleRootInLoop() throws Exception {
477 		String grammar =
478 			"grammar T;\n" +
479 			"options {output=AST;}\n" +
480 			"a : INT (~INT^ INT)* ;\n" +
481 			"blort : '+' ;\n" +
482 			"ID : 'a'..'z'+ ;\n" +
483 			"INT : '0'..'9'+;\n" +
484 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
485 		String found = execParser("T.g", grammar, "TParser", "TLexer",
486 								  "a", "3+4+5", debug);
487 		assertEquals("(+ (+ 3 4) 5)\n", found);
488 	}
489 
testTokenLabelReuse()490 	@Test public void testTokenLabelReuse() throws Exception {
491 		// check for compilation problem due to multiple defines
492 		String grammar =
493 			"grammar T;\n" +
494 			"options {output=AST;}\n" +
495 			"a : id=ID id=ID {System.out.print(\"2nd id=\"+$id.text+';');} ;\n" +
496 			"ID : 'a'..'z'+ ;\n" +
497 			"INT : '0'..'9'+;\n" +
498 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
499 		String found = execParser("T.g", grammar, "TParser", "TLexer",
500 								  "a", "a b", debug);
501 		assertEquals("2nd id=b;a b\n", found);
502 	}
503 
testTokenLabelReuse2()504 	@Test public void testTokenLabelReuse2() throws Exception {
505 		// check for compilation problem due to multiple defines
506 		String grammar =
507 			"grammar T;\n" +
508 			"options {output=AST;}\n" +
509 			"a : id=ID id=ID^ {System.out.print(\"2nd id=\"+$id.text+';');} ;\n" +
510 			"ID : 'a'..'z'+ ;\n" +
511 			"INT : '0'..'9'+;\n" +
512 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
513 		String found = execParser("T.g", grammar, "TParser", "TLexer",
514 								  "a", "a b", debug);
515 		assertEquals("2nd id=b;(b a)\n", found);
516 	}
517 
testTokenListLabelReuse()518 	@Test public void testTokenListLabelReuse() throws Exception {
519 		// check for compilation problem due to multiple defines
520 		// make sure ids has both ID tokens
521 		String grammar =
522 			"grammar T;\n" +
523 			"options {output=AST;}\n" +
524 			"a : ids+=ID ids+=ID {System.out.print(\"id list=\"+$ids+';');} ;\n" +
525 			"ID : 'a'..'z'+ ;\n" +
526 			"INT : '0'..'9'+;\n" +
527 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
528 		String found = execParser("T.g", grammar, "TParser", "TLexer",
529 								  "a", "a b", debug);
530 		String expecting = "id list=[[@0,0:0='a',<4>,1:0], [@2,2:2='b',<4>,1:2]];a b\n";
531 		assertEquals(expecting, found);
532 	}
533 
testTokenListLabelReuse2()534 	@Test public void testTokenListLabelReuse2() throws Exception {
535 		// check for compilation problem due to multiple defines
536 		// make sure ids has both ID tokens
537 		String grammar =
538 			"grammar T;\n" +
539 			"options {output=AST;}\n" +
540 			"a : ids+=ID^ ids+=ID {System.out.print(\"id list=\"+$ids+';');} ;\n" +
541 			"ID : 'a'..'z'+ ;\n" +
542 			"INT : '0'..'9'+;\n" +
543 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
544 		String found = execParser("T.g", grammar, "TParser", "TLexer",
545 								  "a", "a b", debug);
546 		String expecting = "id list=[[@0,0:0='a',<4>,1:0], [@2,2:2='b',<4>,1:2]];(a b)\n";
547 		assertEquals(expecting, found);
548 	}
549 
testTokenListLabelRuleRoot()550 	@Test public void testTokenListLabelRuleRoot() throws Exception {
551 		String grammar =
552 			"grammar T;\n" +
553 			"options {output=AST;}\n" +
554 			"a : id+=ID^ ;\n" +
555 			"ID : 'a'..'z'+ ;\n" +
556 			"INT : '0'..'9'+;\n" +
557 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
558 		String found = execParser("T.g", grammar, "TParser", "TLexer",
559 								  "a", "a", debug);
560 		assertEquals("a\n", found);
561 	}
562 
testTokenListLabelBang()563 	@Test public void testTokenListLabelBang() throws Exception {
564 		String grammar =
565 			"grammar T;\n" +
566 			"options {output=AST;}\n" +
567 			"a : id+=ID! ;\n" +
568 			"ID : 'a'..'z'+ ;\n" +
569 			"INT : '0'..'9'+;\n" +
570 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
571 		String found = execParser("T.g", grammar, "TParser", "TLexer",
572 								  "a", "a", debug);
573 		assertEquals("", found);
574 	}
575 
testRuleListLabel()576 	@Test public void testRuleListLabel() throws Exception {
577 		String grammar =
578 			"grammar T;\n" +
579 			"options {output=AST;}\n" +
580 			"a : x+=b x+=b {" +
581 			"Tree t=(Tree)$x.get(1);" +
582 			"System.out.print(\"2nd x=\"+t.toStringTree()+';');} ;\n" +
583 			"b : ID;\n" +
584 			"ID : 'a'..'z'+ ;\n" +
585 			"INT : '0'..'9'+;\n" +
586 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
587 		String found = execParser("T.g", grammar, "TParser", "TLexer",
588 								  "a", "a b", debug);
589 		assertEquals("2nd x=b;a b\n", found);
590 	}
591 
testRuleListLabelRuleRoot()592 	@Test public void testRuleListLabelRuleRoot() throws Exception {
593 		String grammar =
594 			"grammar T;\n" +
595 			"options {output=AST;}\n" +
596 			"a : ( x+=b^ )+ {" +
597 			"System.out.print(\"x=\"+((CommonTree)$x.get(1)).toStringTree()+';');} ;\n" +
598 			"b : ID;\n" +
599 			"ID : 'a'..'z'+ ;\n" +
600 			"INT : '0'..'9'+;\n" +
601 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
602 		String found = execParser("T.g", grammar, "TParser", "TLexer",
603 								  "a", "a b", debug);
604 		assertEquals("x=(b a);(b a)\n", found);
605 	}
606 
testRuleListLabelBang()607 	@Test public void testRuleListLabelBang() throws Exception {
608 		String grammar =
609 			"grammar T;\n" +
610 			"options {output=AST;}\n" +
611 			"a : x+=b! x+=b {" +
612 			"System.out.print(\"1st x=\"+((CommonTree)$x.get(0)).toStringTree()+';');} ;\n" +
613 			"b : ID;\n" +
614 			"ID : 'a'..'z'+ ;\n" +
615 			"INT : '0'..'9'+;\n" +
616 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
617 		String found = execParser("T.g", grammar, "TParser", "TLexer",
618 								  "a", "a b", debug);
619 		assertEquals("1st x=a;b\n", found);
620 	}
621 
testComplicatedMelange()622 	@Test public void testComplicatedMelange() throws Exception {
623 		// check for compilation problem
624 		String grammar =
625 			"grammar T;\n" +
626 			"options {output=AST;}\n" +
627 			"a : A b=B b=B c+=C c+=C D {String s = $D.text;} ;\n" +
628 			"A : 'a' ;\n" +
629 			"B : 'b' ;\n" +
630 			"C : 'c' ;\n" +
631 			"D : 'd' ;\n" +
632 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
633 		String found = execParser("T.g", grammar, "TParser", "TLexer",
634 								  "a", "a b b c c d", debug);
635 		assertEquals("a b b c c d\n", found);
636 	}
637 
testReturnValueWithAST()638 	@Test public void testReturnValueWithAST() throws Exception {
639 		String grammar =
640 			"grammar foo;\n" +
641 			"options {output=AST;}\n" +
642 			"a : ID b {System.out.println($b.i);} ;\n" +
643 			"b returns [int i] : INT {$i=Integer.parseInt($INT.text);} ;\n" +
644 			"ID : 'a'..'z'+ ;\n" +
645 			"INT : '0'..'9'+;\n" +
646 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
647 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
648 								  "a", "abc 34", debug);
649 		assertEquals("34\nabc 34\n", found);
650 	}
651 
testSetLoop()652 	@Test public void testSetLoop() throws Exception {
653 		String grammar =
654 			"grammar T;\n" +
655 			"options { output=AST; }\n" +
656 			"r : (INT|ID)+ ; \n" +
657 			"ID : 'a'..'z' + ;\n" +
658 			"INT : '0'..'9' +;\n" +
659 			"WS: (' ' | '\\n' | '\\t')+ {$channel = HIDDEN;};\n";
660 		String found = execParser("T.g", grammar, "TParser", "TLexer",
661 								  "r", "abc 34 d", debug);
662 		assertEquals("abc 34 d\n", found);
663 	}
664 
testExtraTokenInSimpleDecl()665 	@Test public void testExtraTokenInSimpleDecl() throws Exception {
666 		String grammar =
667 			"grammar foo;\n" +
668 			"options {output=AST;}\n" +
669 			"decl : type^ ID '='! INT ';'! ;\n" +
670 			"type : 'int' | 'float' ;\n" +
671 			"ID : 'a'..'z'+ ;\n" +
672 			"INT : '0'..'9'+;\n" +
673 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
674 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
675 								  "decl", "int 34 x=1;", debug);
676 		assertEquals("line 1:4 extraneous input '34' expecting ID\n", this.stderrDuringParse);
677 		assertEquals("(int x 1)\n", found); // tree gets correct x and 1 tokens
678 	}
679 
testMissingIDInSimpleDecl()680 	@Test public void testMissingIDInSimpleDecl() throws Exception {
681 		String grammar =
682 			"grammar foo;\n" +
683 			"options {output=AST;}\n" +
684 			"tokens {EXPR;}\n" +
685 			"decl : type^ ID '='! INT ';'! ;\n" +
686 			"type : 'int' | 'float' ;\n" +
687 			"ID : 'a'..'z'+ ;\n" +
688 			"INT : '0'..'9'+;\n" +
689 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
690 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
691 								  "decl", "int =1;", debug);
692 		assertEquals("line 1:4 missing ID at '='\n", this.stderrDuringParse);
693 		assertEquals("(int <missing ID> 1)\n", found); // tree gets invented ID token
694 	}
695 
testMissingSetInSimpleDecl()696 	@Test public void testMissingSetInSimpleDecl() throws Exception {
697 		String grammar =
698 			"grammar foo;\n" +
699 			"options {output=AST;}\n" +
700 			"tokens {EXPR;}\n" +
701 			"decl : type^ ID '='! INT ';'! ;\n" +
702 			"type : 'int' | 'float' ;\n" +
703 			"ID : 'a'..'z'+ ;\n" +
704 			"INT : '0'..'9'+;\n" +
705 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
706 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
707 								  "decl", "x=1;", debug);
708 		assertEquals("line 1:0 mismatched input 'x' expecting set null\n", this.stderrDuringParse);
709 		assertEquals("(<error: x> x 1)\n", found); // tree gets invented ID token
710 	}
711 
testMissingTokenGivesErrorNode()712 	@Test public void testMissingTokenGivesErrorNode() throws Exception {
713 		String grammar =
714 			"grammar foo;\n" +
715 			"options {output=AST;}\n" +
716 			"a : ID INT ;\n" + // follow is EOF
717 			"ID : 'a'..'z'+ ;\n" +
718 			"INT : '0'..'9'+;\n" +
719 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
720 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
721 								  "a", "abc", debug);
722 		assertEquals("line 1:3 missing INT at '<EOF>'\n", this.stderrDuringParse);
723 		assertEquals("abc <missing INT>\n", found);
724 	}
725 
testMissingTokenGivesErrorNodeInInvokedRule()726 	@Test public void testMissingTokenGivesErrorNodeInInvokedRule() throws Exception {
727 		String grammar =
728 			"grammar foo;\n" +
729 			"options {output=AST;}\n" +
730 			"a : b ;\n" +
731 			"b : ID INT ;\n" + // follow should see EOF
732 			"ID : 'a'..'z'+ ;\n" +
733 			"INT : '0'..'9'+;\n" +
734 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
735 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
736 								  "a", "abc", debug);
737 		assertEquals("line 1:3 mismatched input '<EOF>' expecting INT\n", this.stderrDuringParse);
738 		assertEquals("<mismatched token: [@1,3:3='<EOF>',<-1>,1:3], resync=abc>\n", found);
739 	}
740 
testExtraTokenGivesErrorNode()741 	@Test public void testExtraTokenGivesErrorNode() throws Exception {
742 		String grammar =
743 			"grammar foo;\n" +
744 			"options {output=AST;}\n" +
745 			"a : b c ;\n" +
746 			"b : ID ;\n" +
747 			"c : INT ;\n" +
748 			"ID : 'a'..'z'+ ;\n" +
749 			"INT : '0'..'9'+;\n" +
750 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
751 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
752 								  "a", "abc ick 34", debug);
753 		assertEquals("line 1:4 extraneous input 'ick' expecting INT\n", this.stderrDuringParse);
754 		assertEquals("abc 34\n", found);
755 	}
756 
testMissingFirstTokenGivesErrorNode()757 	@Test public void testMissingFirstTokenGivesErrorNode() throws Exception {
758 		String grammar =
759 			"grammar foo;\n" +
760 			"options {output=AST;}\n" +
761 			"a : ID INT ;\n" +
762 			"ID : 'a'..'z'+ ;\n" +
763 			"INT : '0'..'9'+;\n" +
764 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
765 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
766 								  "a", "34", debug);
767 		assertEquals("line 1:0 missing ID at '34'\n", this.stderrDuringParse);
768 		assertEquals("<missing ID> 34\n", found);
769 	}
770 
testMissingFirstTokenGivesErrorNode2()771 	@Test public void testMissingFirstTokenGivesErrorNode2() throws Exception {
772 		String grammar =
773 			"grammar foo;\n" +
774 			"options {output=AST;}\n" +
775 			"a : b c ;\n" +
776 			"b : ID ;\n" +
777 			"c : INT ;\n" +
778 			"ID : 'a'..'z'+ ;\n" +
779 			"INT : '0'..'9'+;\n" +
780 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
781 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
782 								  "a", "34", debug);
783 		// finds an error at the first token, 34, and re-syncs.
784 		// re-synchronizing does not consume a token because 34 follows
785 		// ref to rule b (start of c). It then matches 34 in c.
786 		assertEquals("line 1:0 missing ID at '34'\n", this.stderrDuringParse);
787 		assertEquals("<missing ID> 34\n", found);
788 	}
789 
testNoViableAltGivesErrorNode()790 	@Test public void testNoViableAltGivesErrorNode() throws Exception {
791 		String grammar =
792 			"grammar foo;\n" +
793 			"options {output=AST;}\n" +
794 			"a : b | c ;\n" +
795 			"b : ID ;\n" +
796 			"c : INT ;\n" +
797 			"ID : 'a'..'z'+ ;\n" +
798 			"S : '*' ;\n" +
799 			"INT : '0'..'9'+;\n" +
800 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
801 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
802 								  "a", "*", debug);
803 		assertEquals("line 1:0 no viable alternative at input '*'\n", this.stderrDuringParse);
804 		assertEquals("<unexpected: [@0,0:0='*',<6>,1:0], resync=*>\n", found);
805 	}
806 
807 
808 	// S U P P O R T
809 
_test()810 	private void _test() throws Exception {
811 		String grammar =
812 			"grammar T;\n" +
813 			"options {output=AST;}\n" +
814 			"a :  ;\n" +
815 			"ID : 'a'..'z'+ ;\n" +
816 			"INT : '0'..'9'+;\n" +
817 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
818 		String found = execParser("T.g", grammar, "TParser", "TLexer", "a", "abc 34", debug);
819 		assertEquals("\n", found);
820 	}
821 
822 }
823