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