Home | History | Annotate | Download | only in test
      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 public class TestAutoAST extends BaseTest {
     34 	protected boolean debug = false;
     35 
     36 	@Test public void testTokenList() throws Exception {
     37 		String grammar =
     38 			"grammar foo;\n" +
     39 			"options {output=AST;}\n" +
     40 			"a : ID INT ;\n" +
     41 			"ID : 'a'..'z'+ ;\n" +
     42 			"INT : '0'..'9'+;\n" +
     43 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
     44 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
     45 								  "a", "abc 34", debug);
     46 		assertEquals("abc 34\n", found);
     47 	}
     48 
     49 	@Test public void testTokenListInSingleAltBlock() throws Exception {
     50 		String grammar =
     51 			"grammar foo;\n" +
     52 			"options {output=AST;}\n" +
     53 			"a : (ID INT) ;\n" +
     54 			"ID : 'a'..'z'+ ;\n" +
     55 			"INT : '0'..'9'+;\n" +
     56 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
     57 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
     58 								  "a", "abc 34", debug);
     59 		assertEquals("abc 34\n", found);
     60 	}
     61 
     62 	@Test public void testSimpleRootAtOuterLevel() throws Exception {
     63 		String grammar =
     64 			"grammar foo;\n" +
     65 			"options {output=AST;}\n" +
     66 			"a : ID^ INT ;\n" +
     67 			"ID : 'a'..'z'+ ;\n" +
     68 			"INT : '0'..'9'+;\n" +
     69 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
     70 		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
     71 								  "a", "abc 34", debug);
     72 		assertEquals("(abc 34)\n", found);
     73 	}
     74 
     75 	@Test public void testSimpleRootAtOuterLevelReverse() throws Exception {
     76 		String grammar =
     77 			"grammar T;\n" +
     78 			"options {output=AST;}\n" +
     79 			"a : INT ID^ ;\n" +
     80 			"ID : 'a'..'z'+ ;\n" +
     81 			"INT : '0'..'9'+;\n" +
     82 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
     83 		String found = execParser("T.g", grammar, "TParser", "TLexer",
     84 								  "a", "34 abc", debug);
     85 		assertEquals("(abc 34)\n", found);
     86 	}
     87 
     88 	@Test public void testBang() throws Exception {
     89 		String grammar =
     90 			"grammar T;\n" +
     91 			"options {output=AST;}\n" +
     92 			"a : ID INT! ID! INT ;\n" +
     93 			"ID : 'a'..'z'+ ;\n" +
     94 			"INT : '0'..'9'+;\n" +
     95 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
     96 		String found = execParser("T.g", grammar, "TParser", "TLexer",
     97 								  "a", "abc 34 dag 4532", debug);
     98 		assertEquals("abc 4532\n", found);
     99 	}
    100 
    101 	@Test public void testOptionalThenRoot() throws Exception {
    102 		String grammar =
    103 			"grammar T;\n" +
    104 			"options {output=AST;}\n" +
    105 			"a : ( ID INT )? ID^ ;\n" +
    106 			"ID : 'a'..'z'+ ;\n" +
    107 			"INT : '0'..'9'+;\n" +
    108 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    109 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    110 								  "a", "a 1 b", debug);
    111 		assertEquals("(b a 1)\n", found);
    112 	}
    113 
    114 	@Test public void testLabeledStringRoot() throws Exception {
    115 		String grammar =
    116 			"grammar T;\n" +
    117 			"options {output=AST;}\n" +
    118 			"a : v='void'^ ID ';' ;\n" +
    119 			"ID : 'a'..'z'+ ;\n" +
    120 			"INT : '0'..'9'+;\n" +
    121 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    122 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    123 								  "a", "void foo;", debug);
    124 		assertEquals("(void foo ;)\n", found);
    125 	}
    126 
    127 	@Test public void testWildcard() throws Exception {
    128 		String grammar =
    129 			"grammar T;\n" +
    130 			"options {output=AST;}\n" +
    131 			"a : v='void'^ . ';' ;\n" +
    132 			"ID : 'a'..'z'+ ;\n" +
    133 			"INT : '0'..'9'+;\n" +
    134 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    135 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    136 								  "a", "void foo;", debug);
    137 		assertEquals("(void foo ;)\n", found);
    138 	}
    139 
    140 	@Test public void testWildcardRoot() throws Exception {
    141 		String grammar =
    142 			"grammar T;\n" +
    143 			"options {output=AST;}\n" +
    144 			"a : v='void' .^ ';' ;\n" +
    145 			"ID : 'a'..'z'+ ;\n" +
    146 			"INT : '0'..'9'+;\n" +
    147 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    148 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    149 								  "a", "void foo;", debug);
    150 		assertEquals("(foo void ;)\n", found);
    151 	}
    152 
    153 	@Test public void testWildcardRootWithLabel() throws Exception {
    154 		String grammar =
    155 			"grammar T;\n" +
    156 			"options {output=AST;}\n" +
    157 			"a : v='void' x=.^ ';' ;\n" +
    158 			"ID : 'a'..'z'+ ;\n" +
    159 			"INT : '0'..'9'+;\n" +
    160 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    161 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    162 								  "a", "void foo;", debug);
    163 		assertEquals("(foo void ;)\n", found);
    164 	}
    165 
    166     @Test public void testWildcardRootWithListLabel() throws Exception {
    167         String grammar =
    168             "grammar T;\n" +
    169             "options {output=AST;}\n" +
    170             "a : v='void' x=.^ ';' ;\n" +
    171             "ID : 'a'..'z'+ ;\n" +
    172             "INT : '0'..'9'+;\n" +
    173             "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    174         String found = execParser("T.g", grammar, "TParser", "TLexer",
    175                                   "a", "void foo;", debug);
    176         assertEquals("(foo void ;)\n", found);
    177     }
    178 
    179     @Test public void testWildcardBangWithListLabel() throws Exception {
    180         String grammar =
    181             "grammar T;\n" +
    182             "options {output=AST;}\n" +
    183             "a : v='void' x=.! ';' ;\n" +
    184             "ID : 'a'..'z'+ ;\n" +
    185             "INT : '0'..'9'+;\n" +
    186             "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    187         String found = execParser("T.g", grammar, "TParser", "TLexer",
    188                                   "a", "void foo;", debug);
    189         assertEquals("void ;\n", found);
    190     }
    191 
    192 	@Test public void testRootRoot() throws Exception {
    193 		String grammar =
    194 			"grammar T;\n" +
    195 			"options {output=AST;}\n" +
    196 			"a : ID^ INT^ ID ;\n" +
    197 			"ID : 'a'..'z'+ ;\n" +
    198 			"INT : '0'..'9'+;\n" +
    199 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    200 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    201 								  "a", "a 34 c", debug);
    202 		assertEquals("(34 a c)\n", found);
    203 	}
    204 
    205 	@Test public void testRootRoot2() throws Exception {
    206 		String grammar =
    207 			"grammar T;\n" +
    208 			"options {output=AST;}\n" +
    209 			"a : ID INT^ ID^ ;\n" +
    210 			"ID : 'a'..'z'+ ;\n" +
    211 			"INT : '0'..'9'+;\n" +
    212 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    213 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    214 								  "a", "a 34 c", debug);
    215 		assertEquals("(c (34 a))\n", found);
    216 	}
    217 
    218 	@Test public void testRootThenRootInLoop() throws Exception {
    219 		String grammar =
    220 			"grammar T;\n" +
    221 			"options {output=AST;}\n" +
    222 			"a : ID^ (INT '*'^ ID)+ ;\n" +
    223 			"ID  : 'a'..'z'+ ;\n" +
    224 			"INT : '0'..'9'+;\n" +
    225 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    226 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    227 								  "a", "a 34 * b 9 * c", debug);
    228 		assertEquals("(* (* (a 34) b 9) c)\n", found);
    229 	}
    230 
    231 	@Test public void testNestedSubrule() throws Exception {
    232 		String grammar =
    233 			"grammar T;\n" +
    234 			"options {output=AST;}\n" +
    235 			"a : 'void' (({;}ID|INT) ID | 'null' ) ';' ;\n" +
    236 			"ID : 'a'..'z'+ ;\n" +
    237 			"INT : '0'..'9'+;\n" +
    238 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    239 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    240 								  "a", "void a b;", debug);
    241 		assertEquals("void a b ;\n", found);
    242 	}
    243 
    244 	@Test public void testInvokeRule() throws Exception {
    245 		String grammar =
    246 			"grammar T;\n" +
    247 			"options {output=AST;}\n" +
    248 			"a  : type ID ;\n" +
    249 			"type : {;}'int' | 'float' ;\n" +
    250 			"ID : 'a'..'z'+ ;\n" +
    251 			"INT : '0'..'9'+;\n" +
    252 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    253 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    254 								  "a", "int a", debug);
    255 		assertEquals("int a\n", found);
    256 	}
    257 
    258 	@Test public void testInvokeRuleAsRoot() throws Exception {
    259 		String grammar =
    260 			"grammar T;\n" +
    261 			"options {output=AST;}\n" +
    262 			"a  : type^ ID ;\n" +
    263 			"type : {;}'int' | 'float' ;\n" +
    264 			"ID : 'a'..'z'+ ;\n" +
    265 			"INT : '0'..'9'+;\n" +
    266 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    267 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    268 								  "a", "int a", debug);
    269 		assertEquals("(int a)\n", found);
    270 	}
    271 
    272 	@Test public void testInvokeRuleAsRootWithLabel() throws Exception {
    273 		String grammar =
    274 			"grammar T;\n" +
    275 			"options {output=AST;}\n" +
    276 			"a  : x=type^ ID ;\n" +
    277 			"type : {;}'int' | 'float' ;\n" +
    278 			"ID : 'a'..'z'+ ;\n" +
    279 			"INT : '0'..'9'+;\n" +
    280 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    281 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    282 								  "a", "int a", debug);
    283 		assertEquals("(int a)\n", found);
    284 	}
    285 
    286 	@Test public void testInvokeRuleAsRootWithListLabel() throws Exception {
    287 		String grammar =
    288 			"grammar T;\n" +
    289 			"options {output=AST;}\n" +
    290 			"a  : x+=type^ ID ;\n" +
    291 			"type : {;}'int' | 'float' ;\n" +
    292 			"ID : 'a'..'z'+ ;\n" +
    293 			"INT : '0'..'9'+;\n" +
    294 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    295 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    296 								  "a", "int a", debug);
    297 		assertEquals("(int a)\n", found);
    298 	}
    299 
    300 	@Test public void testRuleRootInLoop() throws Exception {
    301 		String grammar =
    302 			"grammar T;\n" +
    303 			"options {output=AST;}\n" +
    304 			"a : ID ('+'^ ID)* ;\n" +
    305 			"ID : 'a'..'z'+ ;\n" +
    306 			"INT : '0'..'9'+;\n" +
    307 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    308 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    309 								  "a", "a+b+c+d", debug);
    310 		assertEquals("(+ (+ (+ a b) c) d)\n", found);
    311 	}
    312 
    313 	@Test public void testRuleInvocationRuleRootInLoop() throws Exception {
    314 		String grammar =
    315 			"grammar T;\n" +
    316 			"options {output=AST;}\n" +
    317 			"a : ID (op^ ID)* ;\n" +
    318 			"op : {;}'+' | '-' ;\n" +
    319 			"ID : 'a'..'z'+ ;\n" +
    320 			"INT : '0'..'9'+;\n" +
    321 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    322 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    323 								  "a", "a+b+c-d", debug);
    324 		assertEquals("(- (+ (+ a b) c) d)\n", found);
    325 	}
    326 
    327 	@Test public void testTailRecursion() throws Exception {
    328 		String grammar =
    329 			"grammar T;\n" +
    330 			"options {output=AST;}\n" +
    331 			"s : a ;\n" +
    332 			"a : atom ('exp'^ a)? ;\n" +
    333 			"atom : INT ;\n" +
    334 			"ID : 'a'..'z'+ ;\n" +
    335 			"INT : '0'..'9'+;\n" +
    336 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    337 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    338 								  "s", "3 exp 4 exp 5", debug);
    339 		assertEquals("(exp 3 (exp 4 5))\n", found);
    340 	}
    341 
    342 	@Test public void testSet() throws Exception {
    343 		String grammar =
    344 			"grammar T;\n" +
    345 			"options {output=AST;}\n" +
    346 			"a : ID|INT ;\n" +
    347 			"ID : 'a'..'z'+ ;\n" +
    348 			"INT : '0'..'9'+;\n" +
    349 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    350 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    351 								  "a", "abc", debug);
    352 		assertEquals("abc\n", found);
    353 	}
    354 
    355 	@Test public void testSetRoot() throws Exception {
    356 		String grammar =
    357 			"grammar T;\n" +
    358 			"options {output=AST;}\n" +
    359 			"a : ('+' | '-')^ ID ;\n" +
    360 			"ID : 'a'..'z'+ ;\n" +
    361 			"INT : '0'..'9'+;\n" +
    362 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    363 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    364 								  "a", "+abc", debug);
    365 		assertEquals("(+ abc)\n", found);
    366 	}
    367 
    368 	@Ignore
    369     // TODO: FAILS until I rebuild the antlr.g in v3
    370     //
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    810 	public 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