1 /* 2 * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. 3 * Use of this file is governed by the BSD 3-clause license that 4 * can be found in the LICENSE.txt file in the project root. 5 */ 6 package org.antlr.v4.test.tool; 7 8 import org.antlr.v4.Tool; 9 import org.antlr.v4.automata.ATNPrinter; 10 import org.antlr.v4.automata.LexerATNFactory; 11 import org.antlr.v4.automata.ParserATNFactory; 12 import org.antlr.v4.parse.ANTLRParser; 13 import org.antlr.v4.runtime.atn.ATN; 14 import org.antlr.v4.runtime.atn.ATNState; 15 import org.antlr.v4.test.runtime.ErrorQueue; 16 import org.antlr.v4.tool.ErrorType; 17 import org.antlr.v4.tool.Grammar; 18 import org.antlr.v4.tool.LexerGrammar; 19 import org.antlr.v4.tool.ast.GrammarAST; 20 import org.antlr.v4.tool.ast.GrammarRootAST; 21 import org.antlr.v4.tool.ast.RuleAST; 22 import org.junit.Before; 23 import org.junit.Test; 24 25 import java.util.Arrays; 26 import java.util.LinkedHashMap; 27 import java.util.List; 28 import java.util.Map; 29 30 import static org.junit.Assert.assertEquals; 31 import static org.junit.Assert.assertTrue; 32 33 public class TestATNConstruction extends BaseJavaToolTest { 34 @Before 35 @Override testSetUp()36 public void testSetUp() throws Exception { 37 super.testSetUp(); 38 } 39 40 @Test testA()41 public void testA() throws Exception { 42 Grammar g = new Grammar( 43 "parser grammar P;\n"+ 44 "a : A;"); 45 String expecting = 46 "RuleStart_a_0->s2\n" + 47 "s2-A->s3\n" + 48 "s3->RuleStop_a_1\n" + 49 "RuleStop_a_1-EOF->s4\n"; 50 checkRuleATN(g, "a", expecting); 51 } testAB()52 @Test public void testAB() throws Exception { 53 Grammar g = new Grammar( 54 "parser grammar P;\n"+ 55 "a : A B ;"); 56 String expecting = 57 "RuleStart_a_0->s2\n" + 58 "s2-A->s3\n" + 59 "s3-B->s4\n" + 60 "s4->RuleStop_a_1\n" + 61 "RuleStop_a_1-EOF->s5\n"; 62 checkRuleATN(g, "a", expecting); 63 } testAorB()64 @Test public void testAorB() throws Exception { 65 Grammar g = new Grammar( 66 "parser grammar P;\n"+ 67 "a : A | B {;} ;"); 68 String expecting = 69 "RuleStart_a_0->BlockStart_5\n" + 70 "BlockStart_5->s2\n" + 71 "BlockStart_5->s3\n" + 72 "s2-A->BlockEnd_6\n" + 73 "s3-B->s4\n" + 74 "BlockEnd_6->RuleStop_a_1\n" + 75 "s4-action_0:-1->BlockEnd_6\n" + 76 "RuleStop_a_1-EOF->s7\n"; 77 checkRuleATN(g, "a", expecting); 78 } testSetAorB()79 @Test public void testSetAorB() throws Exception { 80 Grammar g = new Grammar( 81 "parser grammar P;\n"+ 82 "a : A | B ;"); 83 String expecting = 84 "RuleStart_a_0->s2\n" + 85 "s2-{A, B}->s3\n" + 86 "s3->RuleStop_a_1\n" + 87 "RuleStop_a_1-EOF->s4\n"; 88 checkRuleATN(g, "a", expecting); 89 } testLexerIsntSetMultiCharString()90 @Test public void testLexerIsntSetMultiCharString() throws Exception { 91 LexerGrammar g = new LexerGrammar( 92 "lexer grammar P;\n"+ 93 "A : ('0x' | '0X') ;"); 94 String expecting = 95 "s0->RuleStart_A_1\n" + 96 "RuleStart_A_1->BlockStart_7\n" + 97 "BlockStart_7->s3\n" + 98 "BlockStart_7->s5\n" + 99 "s3-'0'->s4\n" + 100 "s5-'0'->s6\n" + 101 "s4-'x'->BlockEnd_8\n" + 102 "s6-'X'->BlockEnd_8\n" + 103 "BlockEnd_8->RuleStop_A_2\n"; 104 checkTokensRule(g, null, expecting); 105 } testRange()106 @Test public void testRange() throws Exception { 107 LexerGrammar g = new LexerGrammar( 108 "lexer grammar P;\n"+ 109 "A : 'a'..'c' ;" 110 ); 111 String expecting = 112 "s0->RuleStart_A_1\n" + 113 "RuleStart_A_1->s3\n" + 114 "s3-'a'..'c'->s4\n" + 115 "s4->RuleStop_A_2\n"; 116 checkTokensRule(g, null, expecting); 117 } testCharSet()118 @Test public void testCharSet() throws Exception { 119 LexerGrammar g = new LexerGrammar( 120 "lexer grammar P;\n"+ 121 "A : [abc] ;" 122 ); 123 String expecting = 124 "s0->RuleStart_A_1\n" + 125 "RuleStart_A_1->s3\n" + 126 "s3-{97..99}->s4\n" + 127 "s4->RuleStop_A_2\n"; 128 checkTokensRule(g, null, expecting); 129 } testCharSetRange()130 @Test public void testCharSetRange() throws Exception { 131 LexerGrammar g = new LexerGrammar( 132 "lexer grammar P;\n"+ 133 "A : [a-c] ;" 134 ); 135 String expecting = 136 "s0->RuleStart_A_1\n" + 137 "RuleStart_A_1->s3\n" + 138 "s3-{97..99}->s4\n" + 139 "s4->RuleStop_A_2\n"; 140 checkTokensRule(g, null, expecting); 141 } testCharSetUnicodeBMPEscape()142 @Test public void testCharSetUnicodeBMPEscape() throws Exception { 143 LexerGrammar g = new LexerGrammar( 144 "lexer grammar P;\n"+ 145 "A : [\\uABCD] ;" 146 ); 147 String expecting = 148 "s0->RuleStart_A_1\n" + 149 "RuleStart_A_1->s3\n" + 150 "s3-43981->s4\n" + 151 "s4->RuleStop_A_2\n"; 152 checkTokensRule(g, null, expecting); 153 } testCharSetUnicodeBMPEscapeRange()154 @Test public void testCharSetUnicodeBMPEscapeRange() throws Exception { 155 LexerGrammar g = new LexerGrammar( 156 "lexer grammar P;\n"+ 157 "A : [a-c\\uABCD-\\uABFF] ;" 158 ); 159 String expecting = 160 "s0->RuleStart_A_1\n" + 161 "RuleStart_A_1->s3\n" + 162 "s3-{97..99, 43981..44031}->s4\n" + 163 "s4->RuleStop_A_2\n"; 164 checkTokensRule(g, null, expecting); 165 } testCharSetUnicodeSMPEscape()166 @Test public void testCharSetUnicodeSMPEscape() throws Exception { 167 LexerGrammar g = new LexerGrammar( 168 "lexer grammar P;\n"+ 169 "A : [\\u{10ABCD}] ;" 170 ); 171 String expecting = 172 "s0->RuleStart_A_1\n" + 173 "RuleStart_A_1->s3\n" + 174 "s3-1092557->s4\n" + 175 "s4->RuleStop_A_2\n"; 176 checkTokensRule(g, null, expecting); 177 } testCharSetUnicodeSMPEscapeRange()178 @Test public void testCharSetUnicodeSMPEscapeRange() throws Exception { 179 LexerGrammar g = new LexerGrammar( 180 "lexer grammar P;\n"+ 181 "A : [a-c\\u{10ABCD}-\\u{10ABFF}] ;" 182 ); 183 String expecting = 184 "s0->RuleStart_A_1\n" + 185 "RuleStart_A_1->s3\n" + 186 "s3-{97..99, 1092557..1092607}->s4\n" + 187 "s4->RuleStop_A_2\n"; 188 checkTokensRule(g, null, expecting); 189 } testCharSetUnicodePropertyEscape()190 @Test public void testCharSetUnicodePropertyEscape() throws Exception { 191 // The Gothic script is long dead and unlikely to change (which would 192 // cause this test to fail) 193 LexerGrammar g = new LexerGrammar( 194 "lexer grammar P;\n"+ 195 "A : [\\p{Gothic}] ;" 196 ); 197 String expecting = 198 "s0->RuleStart_A_1\n" + 199 "RuleStart_A_1->s3\n" + 200 "s3-{66352..66378}->s4\n" + 201 "s4->RuleStop_A_2\n"; 202 checkTokensRule(g, null, expecting); 203 } testCharSetUnicodePropertyInvertEscape()204 @Test public void testCharSetUnicodePropertyInvertEscape() throws Exception { 205 LexerGrammar g = new LexerGrammar( 206 "lexer grammar P;\n"+ 207 "A : [\\P{Gothic}] ;" 208 ); 209 String expecting = 210 "s0->RuleStart_A_1\n" + 211 "RuleStart_A_1->s3\n" + 212 "s3-{0..66351, 66379..1114111}->s4\n" + 213 "s4->RuleStop_A_2\n"; 214 checkTokensRule(g, null, expecting); 215 } testCharSetUnicodeMultiplePropertyEscape()216 @Test public void testCharSetUnicodeMultiplePropertyEscape() throws Exception { 217 // Ditto the Mahajani script. Not going to change soon. I hope. 218 LexerGrammar g = new LexerGrammar( 219 "lexer grammar P;\n"+ 220 "A : [\\p{Gothic}\\p{Mahajani}] ;" 221 ); 222 String expecting = 223 "s0->RuleStart_A_1\n" + 224 "RuleStart_A_1->s3\n" + 225 "s3-{66352..66378, 69968..70006}->s4\n" + 226 "s4->RuleStop_A_2\n"; 227 checkTokensRule(g, null, expecting); 228 } testCharSetUnicodePropertyOverlap()229 @Test public void testCharSetUnicodePropertyOverlap() throws Exception { 230 LexerGrammar g = new LexerGrammar( 231 "lexer grammar P;\n"+ 232 "A : [\\p{ASCII_Hex_Digit}\\p{Hex_Digit}] ;" 233 ); 234 String expecting = 235 "s0->RuleStart_A_1\n" + 236 "RuleStart_A_1->s3\n" + 237 "s3-{48..57, 65..70, 97..102, 65296..65305, 65313..65318, 65345..65350}->s4\n" + 238 "s4->RuleStop_A_2\n"; 239 checkTokensRule(g, null, expecting); 240 } testRangeOrRange()241 @Test public void testRangeOrRange() throws Exception { 242 LexerGrammar g = new LexerGrammar( 243 "lexer grammar P;\n"+ 244 "A : ('a'..'c' 'h' | 'q' 'j'..'l') ;" 245 ); 246 String expecting = 247 "s0->RuleStart_A_1\n" + 248 "RuleStart_A_1->BlockStart_7\n" + 249 "BlockStart_7->s3\n" + 250 "BlockStart_7->s5\n" + 251 "s3-'a'..'c'->s4\n" + 252 "s5-'q'->s6\n" + 253 "s4-'h'->BlockEnd_8\n" + 254 "s6-'j'..'l'->BlockEnd_8\n" + 255 "BlockEnd_8->RuleStop_A_2\n"; 256 checkTokensRule(g, null, expecting); 257 } testStringLiteralInParser()258 @Test public void testStringLiteralInParser() throws Exception { 259 Grammar g = new Grammar( 260 "grammar P;\n"+ 261 "a : A|'b' ;" 262 ); 263 String expecting = 264 "RuleStart_a_0->s2\n" + 265 "s2-{'b', A}->s3\n" + 266 "s3->RuleStop_a_1\n" + 267 "RuleStop_a_1-EOF->s4\n"; 268 checkRuleATN(g, "a", expecting); 269 } testABorCD()270 @Test public void testABorCD() throws Exception { 271 Grammar g = new Grammar( 272 "parser grammar P;\n"+ 273 "a : A B | C D;"); 274 String expecting = 275 "RuleStart_a_0->BlockStart_6\n" + 276 "BlockStart_6->s2\n" + 277 "BlockStart_6->s4\n" + 278 "s2-A->s3\n" + 279 "s4-C->s5\n" + 280 "s3-B->BlockEnd_7\n" + 281 "s5-D->BlockEnd_7\n" + 282 "BlockEnd_7->RuleStop_a_1\n" + 283 "RuleStop_a_1-EOF->s8\n"; 284 checkRuleATN(g, "a", expecting); 285 } testbA()286 @Test public void testbA() throws Exception { 287 Grammar g = new Grammar( 288 "parser grammar P;\n"+ 289 "a : b A ;\n"+ 290 "b : B ;"); 291 String expecting = 292 "RuleStart_a_0->s4\n" + 293 "s4-b->RuleStart_b_2\n" + 294 "s5-A->s6\n" + 295 "s6->RuleStop_a_1\n" + 296 "RuleStop_a_1-EOF->s9\n"; 297 checkRuleATN(g, "a", expecting); 298 expecting = 299 "RuleStart_b_2->s7\n" + 300 "s7-B->s8\n" + 301 "s8->RuleStop_b_3\n" + 302 "RuleStop_b_3->s5\n"; 303 checkRuleATN(g, "b", expecting); 304 } testFollow()305 @Test public void testFollow() throws Exception { 306 Grammar g = new Grammar( 307 "parser grammar P;\n"+ 308 "a : b A ;\n"+ 309 "b : B ;\n"+ 310 "c : b C;"); 311 String expecting = 312 "RuleStart_b_2->s9\n" + 313 "s9-B->s10\n" + 314 "s10->RuleStop_b_3\n" + 315 "RuleStop_b_3->s7\n" + 316 "RuleStop_b_3->s12\n"; 317 checkRuleATN(g, "b", expecting); 318 } testAorEpsilon()319 @Test public void testAorEpsilon() throws Exception { 320 Grammar g = new Grammar( 321 "parser grammar P;\n"+ 322 "a : A | ;"); 323 String expecting = 324 "RuleStart_a_0->BlockStart_4\n" + 325 "BlockStart_4->s2\n" + 326 "BlockStart_4->s3\n" + 327 "s2-A->BlockEnd_5\n" + 328 "s3->BlockEnd_5\n" + 329 "BlockEnd_5->RuleStop_a_1\n" + 330 "RuleStop_a_1-EOF->s6\n"; 331 checkRuleATN(g, "a", expecting); 332 } testAOptional()333 @Test public void testAOptional() throws Exception { 334 Grammar g = new Grammar( 335 "parser grammar P;\n"+ 336 "a : A?;"); 337 String expecting = 338 "RuleStart_a_0->BlockStart_3\n" + 339 "BlockStart_3->s2\n" + 340 "BlockStart_3->BlockEnd_4\n" + 341 "s2-A->BlockEnd_4\n" + 342 "BlockEnd_4->RuleStop_a_1\n" + 343 "RuleStop_a_1-EOF->s5\n"; 344 checkRuleATN(g, "a", expecting); 345 } testAorBoptional()346 @Test public void testAorBoptional() throws Exception { 347 Grammar g = new Grammar( 348 "parser grammar P;\n"+ 349 "a : (A{;}|B)?;"); 350 String expecting = 351 "RuleStart_a_0->BlockStart_5\n" + 352 "BlockStart_5->s2\n" + 353 "BlockStart_5->s4\n" + 354 "BlockStart_5->BlockEnd_6\n" + 355 "s2-A->s3\n" + 356 "s4-B->BlockEnd_6\n" + 357 "BlockEnd_6->RuleStop_a_1\n" + 358 "s3-action_0:-1->BlockEnd_6\n" + 359 "RuleStop_a_1-EOF->s7\n"; 360 checkRuleATN(g, "a", expecting); 361 } testSetAorBoptional()362 @Test public void testSetAorBoptional() throws Exception { 363 Grammar g = new Grammar( 364 "parser grammar P;\n"+ 365 "a : (A|B)?;"); 366 String expecting = 367 "RuleStart_a_0->BlockStart_3\n" + 368 "BlockStart_3->s2\n" + 369 "BlockStart_3->BlockEnd_4\n" + 370 "s2-{A, B}->BlockEnd_4\n" + 371 "BlockEnd_4->RuleStop_a_1\n" + 372 "RuleStop_a_1-EOF->s5\n"; 373 checkRuleATN(g, "a", expecting); 374 } testAorBthenC()375 @Test public void testAorBthenC() throws Exception { 376 Grammar g = new Grammar( 377 "parser grammar P;\n"+ 378 "a : (A | B) C;"); 379 String expecting = 380 "RuleStart_a_0->s2\n" + 381 "s2-{A, B}->s3\n" + 382 "s3-C->s4\n" + 383 "s4->RuleStop_a_1\n" + 384 "RuleStop_a_1-EOF->s5\n"; 385 checkRuleATN(g, "a", expecting); 386 } testAplus()387 @Test public void testAplus() throws Exception { 388 Grammar g = new Grammar( 389 "parser grammar P;\n"+ 390 "a : A+;"); 391 String expecting = 392 "RuleStart_a_0->PlusBlockStart_3\n" + 393 "PlusBlockStart_3->s2\n" + 394 "s2-A->BlockEnd_4\n" + 395 "BlockEnd_4->PlusLoopBack_5\n" + 396 "PlusLoopBack_5->PlusBlockStart_3\n" + 397 "PlusLoopBack_5->s6\n" + 398 "s6->RuleStop_a_1\n" + 399 "RuleStop_a_1-EOF->s7\n"; 400 checkRuleATN(g, "a", expecting); 401 } testAplusSingleAltHasPlusASTPointingAtLoopBackState()402 @Test public void testAplusSingleAltHasPlusASTPointingAtLoopBackState() throws Exception { 403 Grammar g = new Grammar( 404 "parser grammar P;\n"+ 405 "s : a B ;\n" + // (RULE a (BLOCK (ALT (+ (BLOCK (ALT A)))))) 406 "a : A+;"); 407 String expecting = 408 "RuleStart_a_2->PlusBlockStart_8\n" + 409 "PlusBlockStart_8->s7\n" + 410 "s7-A->BlockEnd_9\n" + 411 "BlockEnd_9->PlusLoopBack_10\n" + 412 "PlusLoopBack_10->PlusBlockStart_8\n" + 413 "PlusLoopBack_10->s11\n" + 414 "s11->RuleStop_a_3\n" + 415 "RuleStop_a_3->s5\n"; 416 checkRuleATN(g, "a", expecting); 417 // Get all AST -> ATNState relationships. Make sure loopback is covered when no loop entry decision 418 List<GrammarAST> ruleNodes = g.ast.getNodesWithType(ANTLRParser.RULE); 419 RuleAST a = (RuleAST)ruleNodes.get(1); 420 List<GrammarAST> nodesInRule = a.getNodesWithType(null); 421 Map<GrammarAST, ATNState> covered = new LinkedHashMap<GrammarAST, ATNState>(); 422 for (GrammarAST node : nodesInRule) { 423 if ( node.atnState != null ) { 424 covered.put(node, node.atnState); 425 } 426 } 427 assertEquals("{RULE=2, BLOCK=8, +=10, BLOCK=8, A=7}", covered.toString()); 428 } testAorBplus()429 @Test public void testAorBplus() throws Exception { 430 Grammar g = new Grammar( 431 "parser grammar P;\n"+ 432 "a : (A|B{;})+;"); 433 String expecting = 434 "RuleStart_a_0->PlusBlockStart_5\n" + 435 "PlusBlockStart_5->s2\n" + 436 "PlusBlockStart_5->s3\n" + 437 "s2-A->BlockEnd_6\n" + 438 "s3-B->s4\n" + 439 "BlockEnd_6->PlusLoopBack_7\n" + 440 "s4-action_0:-1->BlockEnd_6\n" + 441 "PlusLoopBack_7->PlusBlockStart_5\n" + 442 "PlusLoopBack_7->s8\n" + 443 "s8->RuleStop_a_1\n" + 444 "RuleStop_a_1-EOF->s9\n"; 445 checkRuleATN(g, "a", expecting); 446 } testAorBorEmptyPlus()447 @Test public void testAorBorEmptyPlus() throws Exception { 448 Grammar g = new Grammar( 449 "parser grammar P;\n"+ 450 "a : (A | B | )+ ;"); 451 String expecting = 452 "RuleStart_a_0->PlusBlockStart_5\n" + 453 "PlusBlockStart_5->s2\n" + 454 "PlusBlockStart_5->s3\n" + 455 "PlusBlockStart_5->s4\n" + 456 "s2-A->BlockEnd_6\n" + 457 "s3-B->BlockEnd_6\n" + 458 "s4->BlockEnd_6\n" + 459 "BlockEnd_6->PlusLoopBack_7\n" + 460 "PlusLoopBack_7->PlusBlockStart_5\n" + 461 "PlusLoopBack_7->s8\n" + 462 "s8->RuleStop_a_1\n" + 463 "RuleStop_a_1-EOF->s9\n"; 464 checkRuleATN(g, "a", expecting); 465 } testEmptyOrEmpty()466 @Test public void testEmptyOrEmpty() throws Exception { 467 Grammar g = new Grammar( 468 "parser grammar P;\n"+ 469 "a : | ;"); 470 String expecting = 471 "RuleStart_a_0->BlockStart_4\n"+ 472 "BlockStart_4->s2\n"+ 473 "BlockStart_4->s3\n"+ 474 "s2->BlockEnd_5\n"+ 475 "s3->BlockEnd_5\n"+ 476 "BlockEnd_5->RuleStop_a_1\n"+ 477 "RuleStop_a_1-EOF->s6\n"; 478 checkRuleATN(g, "a", expecting); 479 } testAStar()480 @Test public void testAStar() throws Exception { 481 Grammar g = new Grammar( 482 "parser grammar P;\n"+ 483 "a : A*;"); 484 String expecting = 485 "RuleStart_a_0->StarLoopEntry_5\n" + 486 "StarLoopEntry_5->StarBlockStart_3\n" + 487 "StarLoopEntry_5->s6\n" + 488 "StarBlockStart_3->s2\n" + 489 "s6->RuleStop_a_1\n" + 490 "s2-A->BlockEnd_4\n" + 491 "RuleStop_a_1-EOF->s8\n" + 492 "BlockEnd_4->StarLoopBack_7\n" + 493 "StarLoopBack_7->StarLoopEntry_5\n"; 494 checkRuleATN(g, "a", expecting); 495 } testNestedAstar()496 @Test public void testNestedAstar() throws Exception { 497 Grammar g = new Grammar( 498 "parser grammar P;\n"+ 499 "a : (COMMA ID*)*;"); 500 String expecting = 501 "RuleStart_a_0->StarLoopEntry_11\n" + 502 "StarLoopEntry_11->StarBlockStart_9\n" + 503 "StarLoopEntry_11->s12\n" + 504 "StarBlockStart_9->s2\n" + 505 "s12->RuleStop_a_1\n" + 506 "s2-COMMA->StarLoopEntry_6\n" + 507 "RuleStop_a_1-EOF->s14\n" + 508 "StarLoopEntry_6->StarBlockStart_4\n" + 509 "StarLoopEntry_6->s7\n" + 510 "StarBlockStart_4->s3\n" + 511 "s7->BlockEnd_10\n" + 512 "s3-ID->BlockEnd_5\n" + 513 "BlockEnd_10->StarLoopBack_13\n" + 514 "BlockEnd_5->StarLoopBack_8\n" + 515 "StarLoopBack_13->StarLoopEntry_11\n" + 516 "StarLoopBack_8->StarLoopEntry_6\n"; 517 checkRuleATN(g, "a", expecting); 518 } testAorBstar()519 @Test public void testAorBstar() throws Exception { 520 Grammar g = new Grammar( 521 "parser grammar P;\n"+ 522 "a : (A | B{;})* ;"); 523 String expecting = 524 "RuleStart_a_0->StarLoopEntry_7\n" + 525 "StarLoopEntry_7->StarBlockStart_5\n" + 526 "StarLoopEntry_7->s8\n" + 527 "StarBlockStart_5->s2\n" + 528 "StarBlockStart_5->s3\n" + 529 "s8->RuleStop_a_1\n" + 530 "s2-A->BlockEnd_6\n" + 531 "s3-B->s4\n" + 532 "RuleStop_a_1-EOF->s10\n" + 533 "BlockEnd_6->StarLoopBack_9\n" + 534 "s4-action_0:-1->BlockEnd_6\n" + 535 "StarLoopBack_9->StarLoopEntry_7\n"; 536 checkRuleATN(g, "a", expecting); 537 } testPredicatedAorB()538 @Test public void testPredicatedAorB() throws Exception { 539 Grammar g = new Grammar( 540 "parser grammar P;\n"+ 541 "a : {p1}? A | {p2}? B ;"); 542 String expecting = 543 "RuleStart_a_0->BlockStart_6\n" + 544 "BlockStart_6->s2\n" + 545 "BlockStart_6->s4\n" + 546 "s2-pred_0:0->s3\n" + 547 "s4-pred_0:1->s5\n" + 548 "s3-A->BlockEnd_7\n" + 549 "s5-B->BlockEnd_7\n" + 550 "BlockEnd_7->RuleStop_a_1\n" + 551 "RuleStop_a_1-EOF->s8\n"; 552 checkRuleATN(g, "a", expecting); 553 } 554 testParserRuleRefInLexerRule()555 @Test public void testParserRuleRefInLexerRule() throws Exception { 556 boolean threwException = false; 557 ErrorQueue errorQueue = new ErrorQueue(); 558 try { 559 String gstr = 560 "grammar U;\n"+ 561 "a : A;\n"+ 562 "A : a;\n"; 563 564 Tool tool = new Tool(); 565 tool.removeListeners(); 566 tool.addListener(errorQueue); 567 assertEquals(0, errorQueue.size()); 568 GrammarRootAST grammarRootAST = tool.parseGrammarFromString(gstr); 569 assertEquals(0, errorQueue.size()); 570 Grammar g = tool.createGrammar(grammarRootAST); 571 assertEquals(0, errorQueue.size()); 572 g.fileName = "<string>"; 573 tool.process(g, false); 574 } 575 catch (Exception e) { 576 threwException = true; 577 e.printStackTrace(); 578 } 579 System.out.println(errorQueue); 580 assertEquals(1, errorQueue.errors.size()); 581 assertEquals(ErrorType.PARSER_RULE_REF_IN_LEXER_RULE, errorQueue.errors.get(0).getErrorType()); 582 assertEquals("[a, A]", Arrays.toString(errorQueue.errors.get(0).getArgs())); 583 assertTrue(!threwException); 584 } 585 586 /** Test for https://github.com/antlr/antlr4/issues/1369 587 * Repeated edges: 588 589 RuleStop_e_3->BlockEnd_26 590 RuleStop_e_3->BlockEnd_26 591 RuleStop_e_3->BlockEnd_26 592 593 * @throws Exception 594 */ testForRepeatedTransitionsToStopState()595 @Test public void testForRepeatedTransitionsToStopState() throws Exception { 596 String gstr = 597 "grammar T;\n"+ 598 "\t s : e EOF;\n"+ 599 "\t e :<assoc=right> e '*' e\n"+ 600 "\t |<assoc=right> e '+' e\n"+ 601 "\t |<assoc=right> e '?' e ':' e\n"+ 602 "\t |<assoc=right> e '=' e\n"+ 603 "\t | ID\n"+ 604 "\t ;\n"+ 605 "\t ID : 'a'..'z'+ ;\n"+ 606 "\t WS : (' '|'\\n') -> skip ;"; 607 Grammar g = new Grammar(gstr); 608 String expecting = 609 "RuleStart_e_2->s7\n"+ 610 "s7-action_1:-1->s8\n"+ 611 "s8-ID->s9\n"+ 612 "s9->StarLoopEntry_27\n"+ 613 "StarLoopEntry_27->StarBlockStart_25\n"+ 614 "StarLoopEntry_27->s28\n"+ 615 "StarBlockStart_25->s10\n"+ 616 "StarBlockStart_25->s13\n"+ 617 "StarBlockStart_25->s16\n"+ 618 "StarBlockStart_25->s22\n"+ 619 "s28->RuleStop_e_3\n"+ 620 "s10-5 >= _p->s11\n"+ 621 "s13-4 >= _p->s14\n"+ 622 "s16-3 >= _p->s17\n"+ 623 "s22-2 >= _p->s23\n"+ 624 "RuleStop_e_3->s5\n"+ 625 "RuleStop_e_3->BlockEnd_26\n"+ 626 "RuleStop_e_3->s19\n"+ 627 "RuleStop_e_3->s21\n"+ 628 "s11-'*'->s12\n"+ 629 "s14-'+'->s15\n"+ 630 "s17-'?'->s18\n"+ 631 "s23-'='->s24\n"+ 632 "s12-e->RuleStart_e_2\n"+ 633 "s15-e->RuleStart_e_2\n"+ 634 "s18-e->RuleStart_e_2\n"+ 635 "s24-e->RuleStart_e_2\n"+ 636 "BlockEnd_26->StarLoopBack_29\n"+ 637 "s19-':'->s20\n"+ 638 "StarLoopBack_29->StarLoopEntry_27\n"+ 639 "s20-e->RuleStart_e_2\n"+ 640 "s21->BlockEnd_26\n"; 641 checkRuleATN(g, "e", expecting); 642 } 643 644 645 /* 646 @Test public void testMultiplePredicates() throws Exception { 647 Grammar g = new Grammar( 648 "parser grammar P;\n"+ 649 "a : {p1}? {p1a}? A | {p2}? B | {p3} b;\n" + 650 "b : {p4}? B ;"); 651 String expecting = 652 "\n"; 653 checkRule(g, "a", expecting); 654 } 655 @Test public void testSets() throws Exception { 656 Grammar g = new Grammar( 657 "parser grammar P;\n"+ 658 "a : ( A | B )+ ;\n" + 659 "b : ( A | B{;} )+ ;\n" + 660 "c : (A|B) (A|B) ;\n" + 661 "d : ( A | B )* ;\n" + 662 "e : ( A | B )? ;"); 663 String expecting = 664 "\n"; 665 checkRule(g, "a", expecting); 666 expecting = 667 "\n"; 668 checkRule(g, "b", expecting); 669 expecting = 670 "\n"; 671 checkRule(g, "c", expecting); 672 expecting = 673 "\n"; 674 checkRule(g, "d", expecting); 675 expecting = 676 "\n"; 677 checkRule(g, "e", expecting); 678 } 679 @Test public void testNotSet() throws Exception { 680 Grammar g = new Grammar( 681 "parser grammar P;\n"+ 682 "tokens { A; B; C; }\n"+ 683 "a : ~A ;\n"); 684 String expecting = 685 "\n"; 686 checkRule(g, "a", expecting); 687 } 688 @Test public void testNotSingletonBlockSet() throws Exception { 689 Grammar g = new Grammar( 690 "parser grammar P;\n"+ 691 "tokens { A; B; C; }\n"+ 692 "a : ~(A) ;\n"); 693 String expecting = 694 "\n"; 695 checkRule(g, "a", expecting); 696 } 697 @Test public void testNotCharSet() throws Exception { 698 Grammar g = new Grammar( 699 "lexer grammar P;\n"+ 700 "A : ~'3' ;\n"); 701 String expecting = 702 "RuleStart_A_1->s5\n" + 703 "s5-{'\\u0000'..'2', '4'..'\\uFFFE'}->s6\n" + 704 "s6->RuleStop_A_2\n"; 705 checkRule(g, "A", expecting); 706 } 707 @Test public void testNotBlockSet() throws Exception { 708 Grammar g = new Grammar( 709 "lexer grammar P;\n"+ 710 "A : ~('3'|'b') ;\n"); 711 String expecting = 712 "\n"; 713 checkRule(g, "A", expecting); 714 } 715 @Test public void testNotSetLoop() throws Exception { 716 Grammar g = new Grammar( 717 "lexer grammar P;\n"+ 718 "A : ~('3')* ;\n"); 719 String expecting = 720 "\n"; 721 checkRule(g, "A", expecting); 722 } 723 @Test public void testNotBlockSetLoop() throws Exception { 724 Grammar g = new Grammar( 725 "lexer grammar P;\n"+ 726 "A : ~('3'|'b')* ;\n"); 727 String expecting = 728 "\n"; 729 checkRule(g, "A", expecting); 730 } 731 @Test public void testLabeledNotSet() throws Exception { 732 Grammar g = new Grammar( 733 "parser grammar P;\n"+ 734 "tokens { A; B; C; }\n"+ 735 "a : t=~A ;\n"); 736 String expecting = 737 ".s0->.s1\n" + 738 ".s1->.s2\n" + 739 ".s2-B..C->.s3\n" + 740 ".s3->:s4\n" + 741 ":s4-EOF->.s5\n"; 742 checkRule(g, "a", expecting); 743 } 744 @Test public void testLabeledNotCharSet() throws Exception { 745 Grammar g = new Grammar( 746 "lexer grammar P;\n"+ 747 "A : t=~'3' ;\n"); 748 String expecting = 749 ".s0->.s1\n" + 750 ".s1->.s2\n" + 751 ".s2-{'\\u0000'..'2', '4'..'\\uFFFF'}->.s3\n" + 752 ".s3->:s4\n" + 753 ":s4-<EOT>->.s5\n"; 754 checkRule(g, "A", expecting); 755 } 756 @Test public void testLabeledNotBlockSet() throws Exception { 757 Grammar g = new Grammar( 758 "lexer grammar P;\n"+ 759 "A : t=~('3'|'b') ;\n"); 760 String expecting = 761 ".s0->.s1\n" + 762 ".s1->.s2\n" + 763 ".s2-{'\\u0000'..'2', '4'..'a', 'c'..'\\uFFFF'}->.s3\n" + 764 ".s3->:s4\n" + 765 ":s4-<EOT>->.s5\n"; 766 checkRule(g, "A", expecting); 767 } 768 @Test public void testEscapedCharLiteral() throws Exception { 769 Grammar g = new Grammar( 770 "grammar P;\n"+ 771 "a : '\\n';"); 772 String expecting = 773 ".s0->.s1\n" + 774 ".s1->.s2\n" + 775 ".s2-'\\n'->.s3\n" + 776 ".s3->:s4\n" + 777 ":s4-EOF->.s5\n"; 778 checkRule(g, "a", expecting); 779 } 780 @Test public void testEscapedStringLiteral() throws Exception { 781 Grammar g = new Grammar( 782 "grammar P;\n"+ 783 "a : 'a\\nb\\u0030c\\'';"); 784 String expecting = 785 "RuleStart_a_0->s2\n" + 786 "s2-'a\\nb\\u0030c\\''->s3\n" + 787 "s3->RuleStop_a_1\n" + 788 "RuleStop_a_1-EOF->s4\n"; 789 checkRule(g, "a", expecting); 790 } 791 */ 792 testDefaultMode()793 @Test public void testDefaultMode() throws Exception { 794 LexerGrammar g = new LexerGrammar( 795 "lexer grammar L;\n"+ 796 "A : 'a' ;\n" + 797 "X : 'x' ;\n" + 798 "mode FOO;\n" + 799 "B : 'b' ;\n" + 800 "C : 'c' ;\n"); 801 String expecting = 802 "s0->RuleStart_A_2\n" + 803 "s0->RuleStart_X_4\n" + 804 "RuleStart_A_2->s10\n" + 805 "RuleStart_X_4->s12\n" + 806 "s10-'a'->s11\n" + 807 "s12-'x'->s13\n" + 808 "s11->RuleStop_A_3\n" + 809 "s13->RuleStop_X_5\n"; 810 checkTokensRule(g, "DEFAULT_MODE", expecting); 811 } 812 testMode()813 @Test public void testMode() throws Exception { 814 LexerGrammar g = new LexerGrammar( 815 "lexer grammar L;\n"+ 816 "A : 'a' ;\n" + 817 "X : 'x' ;\n" + 818 "mode FOO;\n" + 819 "B : 'b' ;\n" + 820 "C : 'c' ;\n"); 821 String expecting = 822 "s1->RuleStart_B_6\n" + 823 "s1->RuleStart_C_8\n" + 824 "RuleStart_B_6->s14\n" + 825 "RuleStart_C_8->s16\n" + 826 "s14-'b'->s15\n" + 827 "s16-'c'->s17\n" + 828 "s15->RuleStop_B_7\n" + 829 "s17->RuleStop_C_9\n"; 830 checkTokensRule(g, "FOO", expecting); 831 } checkTokensRule(LexerGrammar g, String modeName, String expecting)832 void checkTokensRule(LexerGrammar g, String modeName, String expecting) { 833 // if ( g.ast!=null && !g.ast.hasErrors ) { 834 // System.out.println(g.ast.toStringTree()); 835 // Tool antlr = new Tool(); 836 // SemanticPipeline sem = new SemanticPipeline(g); 837 // sem.process(); 838 // if ( g.getImportedGrammars()!=null ) { // process imported grammars (if any) 839 // for (Grammar imp : g.getImportedGrammars()) { 840 // antlr.processNonCombinedGrammar(imp); 841 // } 842 // } 843 // } 844 if ( modeName==null ) modeName = "DEFAULT_MODE"; 845 if ( g.modes.get(modeName)==null ) { 846 System.err.println("no such mode "+modeName); 847 return; 848 } 849 ParserATNFactory f = new LexerATNFactory(g); 850 ATN nfa = f.createATN(); 851 ATNState startState = nfa.modeNameToStartState.get(modeName); 852 ATNPrinter serializer = new ATNPrinter(g, startState); 853 String result = serializer.asString(); 854 //System.out.print(result); 855 assertEquals(expecting, result); 856 } 857 } 858