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 7 package org.antlr.v4.test.tool; 8 9 import org.antlr.v4.Tool; 10 import org.antlr.v4.tool.ErrorType; 11 import org.junit.Assert; 12 import org.junit.Before; 13 import org.junit.Test; 14 15 public class TestToolSyntaxErrors extends BaseJavaToolTest { 16 static String[] A = { 17 // INPUT 18 "grammar A;\n" + 19 "", 20 // YIELDS 21 "error(" + ErrorType.NO_RULES.code + "): A.g4::: grammar A has no rules\n", 22 23 "lexer grammar A;\n" + 24 "", 25 "error(" + ErrorType.NO_RULES.code + "): A.g4::: grammar A has no rules\n", 26 27 "A;", 28 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:1:0: syntax error: 'A' came as a complete surprise to me\n", 29 30 "grammar ;", 31 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:1:8: syntax error: ';' came as a complete surprise to me while looking for an identifier\n", 32 33 "grammar A\n" + 34 "a : ID ;\n", 35 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:0: syntax error: missing SEMI at 'a'\n", 36 37 "grammar A;\n" + 38 "a : ID ;;\n"+ 39 "b : B ;", 40 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:8: syntax error: ';' came as a complete surprise to me\n", 41 42 "grammar A;;\n" + 43 "a : ID ;\n", 44 "error(" + ErrorType.SYNTAX_ERROR.code + "): A;.g4:1:10: syntax error: ';' came as a complete surprise to me\n", 45 46 "grammar A;\n" + 47 "a @init : ID ;\n", 48 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:8: syntax error: mismatched input ':' expecting ACTION while matching rule preamble\n", 49 50 "grammar A;\n" + 51 "a ( A | B ) D ;\n" + 52 "b : B ;", 53 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:3: syntax error: '(' came as a complete surprise to me while matching rule preamble\n" + 54 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:11: syntax error: mismatched input ')' expecting SEMI while matching a rule\n" + 55 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:15: syntax error: mismatched input ';' expecting COLON while matching a lexer rule\n", 56 }; 57 58 @Before 59 @Override testSetUp()60 public void testSetUp() throws Exception { 61 super.testSetUp(); 62 } 63 64 @Test AllErrorCodesDistinct()65 public void AllErrorCodesDistinct() { 66 ErrorType[] errorTypes = ErrorType.class.getEnumConstants(); 67 for (int i = 0; i < errorTypes.length; i++) { 68 for (int j = i + 1; j < errorTypes.length; j++) { 69 Assert.assertNotEquals(errorTypes[i].code, errorTypes[j].code); 70 } 71 } 72 } 73 testA()74 @Test public void testA() { super.testErrors(A, true); } 75 testExtraColon()76 @Test public void testExtraColon() { 77 String[] pair = new String[] { 78 "grammar A;\n" + 79 "a : : A ;\n" + 80 "b : B ;", 81 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:4: syntax error: ':' came as a complete surprise to me while matching alternative\n", 82 }; 83 super.testErrors(pair, true); 84 } 85 testMissingRuleSemi()86 @Test public void testMissingRuleSemi() { 87 String[] pair = new String[] { 88 "grammar A;\n" + 89 "a : A \n" + 90 "b : B ;", 91 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:3:0: syntax error: unterminated rule (missing ';') detected at 'b :' while looking for rule element\n", 92 }; 93 super.testErrors(pair, true); 94 } 95 testMissingRuleSemi2()96 @Test public void testMissingRuleSemi2() { 97 String[] pair = new String[] { 98 "lexer grammar A;\n" + 99 "A : 'a' \n" + 100 "B : 'b' ;", 101 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:3:0: syntax error: unterminated rule (missing ';') detected at 'B :' while looking for lexer rule element\n", 102 }; 103 super.testErrors(pair, true); 104 } 105 testMissingRuleSemi3()106 @Test public void testMissingRuleSemi3() { 107 String[] pair = new String[] { 108 "grammar A;\n" + 109 "a : A \n" + 110 "b[int i] returns [int y] : B ;", 111 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:3:9: syntax error: unterminated rule (missing ';') detected at 'returns int y' while looking for rule element\n" 112 }; 113 super.testErrors(pair, true); 114 } 115 testMissingRuleSemi4()116 @Test public void testMissingRuleSemi4() { 117 String[] pair = new String[] { 118 "grammar A;\n" + 119 "a : b \n" + 120 " catch [Exception e] {...}\n" + 121 "b : B ;\n", 122 123 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:4: syntax error: unterminated rule (missing ';') detected at 'b catch' while looking for rule element\n" 124 }; 125 super.testErrors(pair, true); 126 } 127 testMissingRuleSemi5()128 @Test public void testMissingRuleSemi5() { 129 String[] pair = new String[] { 130 "grammar A;\n" + 131 "a : A \n" + 132 " catch [Exception e] {...}\n", 133 134 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:4: syntax error: unterminated rule (missing ';') detected at 'A catch' while looking for rule element\n" 135 }; 136 super.testErrors(pair, true); 137 } 138 testBadRulePrequelStart()139 @Test public void testBadRulePrequelStart() { 140 String[] pair = new String[] { 141 "grammar A;\n" + 142 "a @ options {k=1;} : A ;\n" + 143 "b : B ;", 144 145 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:4: syntax error: 'options {' came as a complete surprise to me while looking for an identifier\n" 146 }; 147 super.testErrors(pair, true); 148 } 149 testBadRulePrequelStart2()150 @Test public void testBadRulePrequelStart2() { 151 String[] pair = new String[] { 152 "grammar A;\n" + 153 "a } : A ;\n" + 154 "b : B ;", 155 156 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:2: syntax error: '}' came as a complete surprise to me while matching rule preamble\n" 157 }; 158 super.testErrors(pair, true); 159 } 160 testModeInParser()161 @Test public void testModeInParser() { 162 String[] pair = new String[] { 163 "grammar A;\n" + 164 "a : A ;\n" + 165 "mode foo;\n" + 166 "b : B ;", 167 168 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:4:0: syntax error: 'b' came as a complete surprise to me\n" + 169 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:4:6: syntax error: mismatched input ';' expecting COLON while matching a lexer rule\n" 170 }; 171 super.testErrors(pair, true); 172 } 173 174 /** 175 * This is a regression test for antlr/antlr4#243 176 * "Generate a good message for unterminated strings" 177 * https://github.com/antlr/antlr4/issues/243 178 */ testUnterminatedStringLiteral()179 @Test public void testUnterminatedStringLiteral() { 180 String[] pair = new String[] { 181 "grammar A;\n" + 182 "a : 'x\n" + 183 " ;\n", 184 185 "error(" + ErrorType.UNTERMINATED_STRING_LITERAL.code + "): A.g4:2:4: unterminated string literal\n" 186 }; 187 super.testErrors(pair, true); 188 } 189 190 /** 191 * This is a regression test for antlr/antlr4#262 192 * "Parser Rule Name Starting With an Underscore" 193 * https://github.com/antlr/antlr4/issues/262 194 */ testParserRuleNameStartingWithUnderscore()195 @Test public void testParserRuleNameStartingWithUnderscore() { 196 String[] pair = new String[] { 197 "grammar A;\n" + 198 "_a : 'x' ;\n", 199 200 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:0: syntax error: '_' came as a complete surprise to me\n" 201 }; 202 super.testErrors(pair, true); 203 } 204 205 /** 206 * This is a regression test for antlr/antlr4#194 207 * "NullPointerException on 'options{}' in grammar file" 208 * https://github.com/antlr/antlr4/issues/194 209 */ testEmptyGrammarOptions()210 @Test public void testEmptyGrammarOptions() { 211 String[] pair = new String[] { 212 "grammar A;\n" + 213 "options {}\n" + 214 "a : 'x' ;\n", 215 216 "" 217 }; 218 super.testErrors(pair, true); 219 } 220 221 /** 222 * This is a "related" regression test for antlr/antlr4#194 223 * "NullPointerException on 'options{}' in grammar file" 224 * https://github.com/antlr/antlr4/issues/194 225 */ testEmptyRuleOptions()226 @Test public void testEmptyRuleOptions() { 227 String[] pair = new String[] { 228 "grammar A;\n" + 229 "a options{} : 'x' ;\n", 230 231 "" 232 }; 233 super.testErrors(pair, true); 234 } 235 236 /** 237 * This is a "related" regression test for antlr/antlr4#194 238 * "NullPointerException on 'options{}' in grammar file" 239 * https://github.com/antlr/antlr4/issues/194 240 */ testEmptyBlockOptions()241 @Test public void testEmptyBlockOptions() { 242 String[] pair = new String[] { 243 "grammar A;\n" + 244 "a : (options{} : 'x') ;\n", 245 246 "" 247 }; 248 super.testErrors(pair, true); 249 } 250 testEmptyTokensBlock()251 @Test public void testEmptyTokensBlock() { 252 String[] pair = new String[] { 253 "grammar A;\n" + 254 "tokens {}\n" + 255 "a : 'x' ;\n", 256 257 "" 258 }; 259 super.testErrors(pair, true); 260 } 261 262 /** 263 * This is a regression test for antlr/antlr4#190 264 * "NullPointerException building lexer grammar using bogus 'token' action" 265 * https://github.com/antlr/antlr4/issues/190 266 */ testInvalidLexerCommand()267 @Test public void testInvalidLexerCommand() { 268 String[] pair = new String[] { 269 "grammar A;\n" + 270 "tokens{Foo}\n" + 271 "b : Foo ;\n" + 272 "X : 'foo1' -> popmode;\n" + // "meant" to use -> popMode 273 "Y : 'foo2' -> token(Foo);", // "meant" to use -> type(Foo) 274 275 "error(" + ErrorType.INVALID_LEXER_COMMAND.code + "): A.g4:4:14: lexer command popmode does not exist or is not supported by the current target\n" + 276 "error(" + ErrorType.INVALID_LEXER_COMMAND.code + "): A.g4:5:14: lexer command token does not exist or is not supported by the current target\n" 277 }; 278 super.testErrors(pair, true); 279 } 280 testLexerCommandArgumentValidation()281 @Test public void testLexerCommandArgumentValidation() { 282 String[] pair = new String[] { 283 "grammar A;\n" + 284 "tokens{Foo}\n" + 285 "b : Foo ;\n" + 286 "X : 'foo1' -> popMode(Foo);\n" + // "meant" to use -> popMode 287 "Y : 'foo2' -> type;", // "meant" to use -> type(Foo) 288 289 "error(" + ErrorType.UNWANTED_LEXER_COMMAND_ARGUMENT.code + "): A.g4:4:14: lexer command popMode does not take any arguments\n" + 290 "error(" + ErrorType.MISSING_LEXER_COMMAND_ARGUMENT.code + "): A.g4:5:14: missing argument for lexer command type\n" 291 }; 292 super.testErrors(pair, true); 293 } 294 testRuleRedefinition()295 @Test public void testRuleRedefinition() { 296 String[] pair = new String[] { 297 "grammar Oops;\n" + 298 "\n" + 299 "ret_ty : A ;\n" + 300 "ret_ty : B ;\n" + 301 "\n" + 302 "A : 'a' ;\n" + 303 "B : 'b' ;\n", 304 305 "error(" + ErrorType.RULE_REDEFINITION.code + "): Oops.g4:4:0: rule ret_ty redefinition; previous at line 3\n" 306 }; 307 super.testErrors(pair, true); 308 } 309 testEpsilonClosureAnalysis()310 @Test public void testEpsilonClosureAnalysis() { 311 String grammar = 312 "grammar A;\n" 313 + "x : ;\n" 314 + "y1 : x+;\n" 315 + "y2 : x*;\n" 316 + "z1 : ('foo' | 'bar'? 'bar2'?)*;\n" 317 + "z2 : ('foo' | 'bar' 'bar2'? | 'bar2')*;\n"; 318 String expected = 319 "error(" + ErrorType.EPSILON_CLOSURE.code + "): A.g4:3:0: rule y1 contains a closure with at least one alternative that can match an empty string\n" + 320 "error(" + ErrorType.EPSILON_CLOSURE.code + "): A.g4:4:0: rule y2 contains a closure with at least one alternative that can match an empty string\n" + 321 "error(" + ErrorType.EPSILON_CLOSURE.code + "): A.g4:5:0: rule z1 contains a closure with at least one alternative that can match an empty string\n"; 322 323 String[] pair = new String[] { 324 grammar, 325 expected 326 }; 327 328 super.testErrors(pair, true); 329 } 330 331 // Test for https://github.com/antlr/antlr4/issues/1203 testEpsilonNestedClosureAnalysis()332 @Test public void testEpsilonNestedClosureAnalysis() { 333 String grammar = 334 "grammar T;\n"+ 335 "s : (a a)* ;\n"+ 336 "a : 'foo'* ;\n"; 337 String expected = 338 "error(" + ErrorType.EPSILON_CLOSURE.code + "): T.g4:2:0: rule s contains a closure with at least one alternative that can match an empty string\n"; 339 340 String[] pair = new String[] { 341 grammar, 342 expected 343 }; 344 345 super.testErrors(pair, true); 346 } 347 348 // Test for https://github.com/antlr/antlr4/issues/1203 testEpsilonOptionalAndClosureAnalysis()349 @Test public void testEpsilonOptionalAndClosureAnalysis() { 350 String grammar = 351 "grammar T;\n"+ 352 "s : (a a)? ;\n"+ 353 "a : 'foo'* ;\n"; 354 String expected = 355 "warning(" + ErrorType.EPSILON_OPTIONAL.code + "): T.g4:2:0: rule s contains an optional block with at least one alternative that can match an empty string\n"; 356 357 String[] pair = new String[] { 358 grammar, 359 expected 360 }; 361 362 super.testErrors(pair, true); 363 } 364 testEpsilonOptionalAnalysis()365 @Test public void testEpsilonOptionalAnalysis() { 366 String grammar = 367 "grammar A;\n" 368 + "x : ;\n" 369 + "y : x?;\n" 370 + "z1 : ('foo' | 'bar'? 'bar2'?)?;\n" 371 + "z2 : ('foo' | 'bar' 'bar2'? | 'bar2')?;\n"; 372 String expected = 373 "warning(" + ErrorType.EPSILON_OPTIONAL.code + "): A.g4:3:0: rule y contains an optional block with at least one alternative that can match an empty string\n" + 374 "warning(" + ErrorType.EPSILON_OPTIONAL.code + "): A.g4:4:0: rule z1 contains an optional block with at least one alternative that can match an empty string\n"; 375 376 String[] pair = new String[] { 377 grammar, 378 expected 379 }; 380 381 super.testErrors(pair, true); 382 } 383 384 /** 385 * This is a regression test for antlr/antlr4#315 386 * "Inconsistent lexer error msg for actions" 387 * https://github.com/antlr/antlr4/issues/315 388 */ testActionAtEndOfOneLexerAlternative()389 @Test public void testActionAtEndOfOneLexerAlternative() { 390 String grammar = 391 "grammar A;\n" + 392 "stat : 'start' CharacterLiteral 'end' EOF;\n" + 393 "\n" + 394 "// Lexer\n" + 395 "\n" + 396 "CharacterLiteral\n" + 397 " : '\\'' SingleCharacter '\\''\n" + 398 " | '\\'' ~[\\r\\n] {notifyErrorListeners(\"unclosed character literal\");}\n" + 399 " ;\n" + 400 "\n" + 401 "fragment\n" + 402 "SingleCharacter\n" + 403 " : ~['\\\\\\r\\n]\n" + 404 " ;\n" + 405 "\n" + 406 "WS : [ \\r\\t\\n]+ -> skip ;\n"; 407 String expected = 408 ""; 409 410 String[] pair = new String[] { grammar, expected }; 411 super.testErrors(pair, true); 412 } 413 414 /** 415 * This is a regression test for antlr/antlr4#308 "NullPointer exception" 416 * https://github.com/antlr/antlr4/issues/308 417 */ testDoubleQuotedStringLiteral()418 @Test public void testDoubleQuotedStringLiteral() { 419 String grammar = 420 "lexer grammar A;\n" 421 + "WHITESPACE : (\" \" | \"\\t\" | \"\\n\" | \"\\r\" | \"\\f\");\n"; 422 String expected = 423 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:14: syntax error: '\"' came as a complete surprise to me\n" + 424 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:16: syntax error: '\"' came as a complete surprise to me\n" + 425 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:20: syntax error: '\"' came as a complete surprise to me\n" + 426 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:21: syntax error: '\\' came as a complete surprise to me\n" + 427 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:23: syntax error: '\"' came as a complete surprise to me\n" + 428 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:27: syntax error: '\"' came as a complete surprise to me\n" + 429 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:28: syntax error: '\\' came as a complete surprise to me\n" + 430 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:30: syntax error: '\"' came as a complete surprise to me\n" + 431 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:34: syntax error: '\"' came as a complete surprise to me\n" + 432 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:35: syntax error: '\\' came as a complete surprise to me\n" + 433 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:37: syntax error: '\"' came as a complete surprise to me\n" + 434 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:41: syntax error: '\"' came as a complete surprise to me\n" + 435 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:42: syntax error: '\\' came as a complete surprise to me\n" + 436 "error(" + ErrorType.SYNTAX_ERROR.code + "): A.g4:2:44: syntax error: '\"' came as a complete surprise to me\n"; 437 438 String[] pair = new String[] { 439 grammar, 440 expected 441 }; 442 443 super.testErrors(pair, true); 444 } 445 446 /** 447 * This is a regression test for https://github.com/antlr/antlr4/issues/1815 448 * "Null ptr exception in SqlBase.g4" 449 */ testDoubleQuoteInTwoStringLiterals()450 @Test public void testDoubleQuoteInTwoStringLiterals() { 451 String grammar = 452 "lexer grammar A;\n" + 453 "STRING : '\\\"' '\\\"' 'x' ;"; 454 String expected = 455 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): A.g4:2:10: invalid escape sequence \\\"\n"+ 456 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): A.g4:2:15: invalid escape sequence \\\"\n"; 457 458 String[] pair = new String[] { 459 grammar, 460 expected 461 }; 462 463 super.testErrors(pair, true); 464 } 465 466 /** 467 * This test ensures that the {@link ErrorType#INVALID_ESCAPE_SEQUENCE} 468 * error is not reported for escape sequences that are known to be valid. 469 */ testValidEscapeSequences()470 @Test public void testValidEscapeSequences() { 471 String grammar = 472 "lexer grammar A;\n" + 473 "NORMAL_ESCAPE : '\\b \\t \\n \\f \\r \\' \\\\';\n" + 474 "UNICODE_ESCAPE : '\\u0001 \\u00A1 \\u00a1 \\uaaaa \\uAAAA';\n"; 475 String expected = 476 ""; 477 478 String[] pair = new String[] { 479 grammar, 480 expected 481 }; 482 483 super.testErrors(pair, true); 484 } 485 486 /** 487 * This is a regression test for antlr/antlr4#507 "NullPointerException When 488 * Generating Code from Grammar". 489 * https://github.com/antlr/antlr4/issues/507 490 */ testInvalidEscapeSequences()491 @Test public void testInvalidEscapeSequences() { 492 String grammar = 493 "lexer grammar A;\n" + 494 "RULE : 'Foo \\uAABG \\x \\u';\n"; 495 String expected = 496 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): A.g4:2:12: invalid escape sequence \\uAABG\n" + 497 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): A.g4:2:19: invalid escape sequence \\x\n" + 498 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): A.g4:2:22: invalid escape sequence \\u\n" + 499 "warning("+ErrorType.EPSILON_TOKEN.code+"): A.g4:2:0: non-fragment lexer rule RULE can match the empty string\n"; 500 501 String[] pair = new String[] { 502 grammar, 503 expected 504 }; 505 506 super.testErrors(pair, true); 507 } 508 509 /** 510 * This is a regression test for antlr/antlr4#959 "NullPointerException". 511 * https://github.com/antlr/antlr4/issues/959 512 */ testNotAllowedEmptyStrings()513 @Test public void testNotAllowedEmptyStrings() { 514 String grammar = 515 "lexer grammar T;\n" + 516 "Error0: '''test''';\n" + 517 "Error1: '' 'test';\n" + 518 "Error2: 'test' '';\n" + 519 "Error3: '';\n" + 520 "NotError: ' ';"; 521 String expected = 522 "error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): T.g4:2:8: string literals and sets cannot be empty: ''\n" + 523 "error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): T.g4:2:16: string literals and sets cannot be empty: ''\n" + 524 "error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): T.g4:3:8: string literals and sets cannot be empty: ''\n" + 525 "error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): T.g4:4:15: string literals and sets cannot be empty: ''\n" + 526 "error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): T.g4:5:8: string literals and sets cannot be empty: ''\n"; 527 528 String[] pair = new String[] { 529 grammar, 530 expected 531 }; 532 533 super.testErrors(pair, true); 534 } 535 testInvalidCharSetsAndStringLiterals()536 @Test public void testInvalidCharSetsAndStringLiterals() { 537 String grammar = 538 "lexer grammar Test;\n" + 539 "INVALID_STRING_LITERAL: '\\\"' | '\\]' | '\\u24';\n" + 540 "INVALID_STRING_LITERAL_RANGE: 'GH'..'LM';\n" + 541 "INVALID_CHAR_SET: [\\u24\\uA2][\\{];\n" + //https://github.com/antlr/antlr4/issues/1077 542 "EMPTY_STRING_LITERAL_RANGE: 'F'..'A' | 'Z';\n" + 543 "EMPTY_CHAR_SET: [f-az][];\n" + 544 "START_HYPHEN_IN_CHAR_SET: [-z];\n" + 545 "END_HYPHEN_IN_CHAR_SET: [a-];\n" + 546 "SINGLE_HYPHEN_IN_CHAR_SET: [-];\n" + 547 "VALID_STRING_LITERALS: '\\u1234' | '\\t' | '\\'';\n" + 548 "VALID_CHAR_SET: [`\\-=\\]];"; 549 550 String expected = 551 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:2:31: invalid escape sequence \\\"\n" + 552 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:2:38: invalid escape sequence \\]\n" + 553 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:2:45: invalid escape sequence \\u24\n" + 554 "error(" + ErrorType.INVALID_LITERAL_IN_LEXER_SET.code + "): Test.g4:3:30: multi-character literals are not allowed in lexer sets: 'GH'\n" + 555 "error(" + ErrorType.INVALID_LITERAL_IN_LEXER_SET.code + "): Test.g4:3:36: multi-character literals are not allowed in lexer sets: 'LM'\n" + 556 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:4:30: invalid escape sequence \\u24\\u\n" + 557 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:4:40: invalid escape sequence \\{\n" + 558 "error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): Test.g4:5:33: string literals and sets cannot be empty: 'F'..'A'\n" + 559 "error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): Test.g4:6:30: string literals and sets cannot be empty: 'f'..'a'\n" + 560 "error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): Test.g4:6:36: string literals and sets cannot be empty: []\n" + 561 "warning("+ ErrorType.EPSILON_TOKEN.code + "): Test.g4:2:0: non-fragment lexer rule INVALID_STRING_LITERAL can match the empty string\n"; 562 563 String[] pair = new String[] { 564 grammar, 565 expected 566 }; 567 568 super.testErrors(pair, true); 569 } 570 testInvalidUnicodeEscapesInCharSet()571 @Test public void testInvalidUnicodeEscapesInCharSet() { 572 String grammar = 573 "lexer grammar Test;\n" + 574 "INVALID_EXTENDED_UNICODE_EMPTY: [\\u{}];\n" + 575 "INVALID_EXTENDED_UNICODE_NOT_TERMINATED: [\\u{];\n" + 576 "INVALID_EXTENDED_UNICODE_TOO_LONG: [\\u{110000}];\n" + 577 "INVALID_UNICODE_PROPERTY_EMPTY: [\\p{}];\n" + 578 "INVALID_UNICODE_PROPERTY_NOT_TERMINATED: [\\p{];\n" + 579 "INVALID_INVERTED_UNICODE_PROPERTY_EMPTY: [\\P{}];\n" + 580 "INVALID_UNICODE_PROPERTY_UNKNOWN: [\\p{NotAProperty}];\n" + 581 "INVALID_INVERTED_UNICODE_PROPERTY_UNKNOWN: [\\P{NotAProperty}];\n" + 582 "UNICODE_PROPERTY_NOT_ALLOWED_IN_RANGE: [\\p{Uppercase_Letter}-\\p{Lowercase_Letter}];\n" + 583 "UNICODE_PROPERTY_NOT_ALLOWED_IN_RANGE_2: [\\p{Letter}-Z];\n" + 584 "UNICODE_PROPERTY_NOT_ALLOWED_IN_RANGE_3: [A-\\p{Number}];\n" + 585 "INVERTED_UNICODE_PROPERTY_NOT_ALLOWED_IN_RANGE: [\\P{Uppercase_Letter}-\\P{Number}];\n"; 586 587 String expected = 588 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:2:32: invalid escape sequence \\u{}\n"+ 589 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:3:41: invalid escape sequence \\u{\n"+ 590 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:4:35: invalid escape sequence \\u{110\n"+ 591 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:5:32: invalid escape sequence \\p{}\n"+ 592 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:6:41: invalid escape sequence \\p{\n"+ 593 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:7:41: invalid escape sequence \\P{}\n"+ 594 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:8:34: invalid escape sequence \\p{NotAProperty}\n"+ 595 "warning(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:9:43: invalid escape sequence \\P{NotAProperty}\n"+ 596 "error(" + ErrorType.UNICODE_PROPERTY_NOT_ALLOWED_IN_RANGE.code + "): Test.g4:10:39: unicode property escapes not allowed in lexer charset range: [\\p{Uppercase_Letter}-\\p{Lowercase_Letter}]\n" + 597 "error(" + ErrorType.UNICODE_PROPERTY_NOT_ALLOWED_IN_RANGE.code + "): Test.g4:11:41: unicode property escapes not allowed in lexer charset range: [\\p{Letter}-Z]\n" + 598 "error(" + ErrorType.UNICODE_PROPERTY_NOT_ALLOWED_IN_RANGE.code + "): Test.g4:12:41: unicode property escapes not allowed in lexer charset range: [A-\\p{Number}]\n" + 599 "error(" + ErrorType.UNICODE_PROPERTY_NOT_ALLOWED_IN_RANGE.code + "): Test.g4:13:48: unicode property escapes not allowed in lexer charset range: [\\P{Uppercase_Letter}-\\P{Number}]\n"; 600 601 String[] pair = new String[] { 602 grammar, 603 expected 604 }; 605 606 super.testErrors(pair, true); 607 } 608 609 /** 610 * This test ensures the {@link ErrorType#UNRECOGNIZED_ASSOC_OPTION} warning 611 * is produced as described in the documentation. 612 */ testUnrecognizedAssocOption()613 @Test public void testUnrecognizedAssocOption() { 614 String grammar = 615 "grammar A;\n" + 616 "x : 'x'\n" + 617 " | x '+'<assoc=right> x // warning 157\n" + 618 " |<assoc=right> x '*' x // ok\n" + 619 " ;\n"; 620 String expected = 621 "warning(" + ErrorType.UNRECOGNIZED_ASSOC_OPTION.code + "): A.g4:3:10: rule x contains an assoc terminal option in an unrecognized location\n"; 622 623 String[] pair = new String[] { 624 grammar, 625 expected 626 }; 627 628 super.testErrors(pair, true); 629 } 630 631 /** 632 * This test ensures the {@link ErrorType#FRAGMENT_ACTION_IGNORED} warning 633 * is produced as described in the documentation. 634 */ testFragmentActionIgnored()635 @Test public void testFragmentActionIgnored() { 636 String grammar = 637 "lexer grammar A;\n" + 638 "X1 : 'x' -> more // ok\n" + 639 " ;\n" + 640 "Y1 : 'x' {more();} // ok\n" + 641 " ;\n" + 642 "fragment\n" + 643 "X2 : 'x' -> more // warning 158\n" + 644 " ;\n" + 645 "fragment\n" + 646 "Y2 : 'x' {more();} // warning 158\n" + 647 " ;\n"; 648 String expected = 649 "warning(" + ErrorType.FRAGMENT_ACTION_IGNORED.code + "): A.g4:7:12: fragment rule X2 contains an action or command which can never be executed\n" + 650 "warning(" + ErrorType.FRAGMENT_ACTION_IGNORED.code + "): A.g4:10:9: fragment rule Y2 contains an action or command which can never be executed\n"; 651 652 String[] pair = new String[] { 653 grammar, 654 expected 655 }; 656 657 super.testErrors(pair, true); 658 } 659 660 /** 661 * This is a regression test for antlr/antlr4#500 "Array Index Out Of 662 * Bounds". 663 * https://github.com/antlr/antlr4/issues/500 664 */ testTokenNamedEOF()665 @Test public void testTokenNamedEOF() { 666 String grammar = 667 "lexer grammar A;\n" + 668 "WS : ' ';\n" + 669 " EOF : 'a';\n"; 670 String expected = 671 "error(" + ErrorType.RESERVED_RULE_NAME.code + "): A.g4:3:1: cannot declare a rule with reserved name EOF\n"; 672 673 String[] pair = new String[] { 674 grammar, 675 expected 676 }; 677 678 super.testErrors(pair, true); 679 } 680 681 /** 682 * This is a regression test for antlr/antlr4#649 "unknown target causes 683 * null ptr exception.". 684 * https://github.com/antlr/antlr4/issues/649 685 * Stops before processing the lexer 686 */ testInvalidLanguageInGrammarWithLexerCommand()687 @Test public void testInvalidLanguageInGrammarWithLexerCommand() throws Exception { 688 String grammar = 689 "grammar T;\n" + 690 "options { language=Foo; }\n" + 691 "start : 'T' EOF;\n" + 692 "Something : 'something' -> channel(CUSTOM);"; 693 String expected = 694 "error(" + ErrorType.CANNOT_CREATE_TARGET_GENERATOR.code + "): ANTLR cannot generate Foo code as of version " + Tool.VERSION + "\n"; 695 String[] pair = new String[] { 696 grammar, 697 expected 698 }; 699 700 super.testErrors(pair, true); 701 } 702 703 /** 704 * This is a regression test for antlr/antlr4#649 "unknown target causes 705 * null ptr exception.". 706 * https://github.com/antlr/antlr4/issues/649 707 */ testInvalidLanguageInGrammar()708 @Test public void testInvalidLanguageInGrammar() throws Exception { 709 String grammar = 710 "grammar T;\n" + 711 "options { language=Foo; }\n" + 712 "start : 'T' EOF;\n"; 713 String expected = 714 "error(" + ErrorType.CANNOT_CREATE_TARGET_GENERATOR.code + "): ANTLR cannot generate Foo code as of version " + Tool.VERSION + "\n"; 715 716 String[] pair = new String[] { 717 grammar, 718 expected 719 }; 720 721 super.testErrors(pair, true); 722 } 723 testChannelDefinitionInLexer()724 @Test public void testChannelDefinitionInLexer() throws Exception { 725 String grammar = 726 "lexer grammar T;\n" + 727 "\n" + 728 "channels {\n" + 729 " WHITESPACE_CHANNEL,\n" + 730 " COMMENT_CHANNEL\n" + 731 "}\n" + 732 "\n" + 733 "COMMENT: '//' ~[\\n]+ -> channel(COMMENT_CHANNEL);\n" + 734 "WHITESPACE: [ \\t]+ -> channel(WHITESPACE_CHANNEL);\n"; 735 736 String expected = ""; 737 738 String[] pair = { grammar, expected }; 739 super.testErrors(pair, true); 740 } 741 testChannelDefinitionInParser()742 @Test public void testChannelDefinitionInParser() throws Exception { 743 String grammar = 744 "parser grammar T;\n" + 745 "\n" + 746 "channels {\n" + 747 " WHITESPACE_CHANNEL,\n" + 748 " COMMENT_CHANNEL\n" + 749 "}\n" + 750 "\n" + 751 "start : EOF;\n"; 752 753 String expected = 754 "error(" + ErrorType.CHANNELS_BLOCK_IN_PARSER_GRAMMAR.code + "): T.g4:3:0: custom channels are not supported in parser grammars\n"; 755 756 String[] pair = { grammar, expected }; 757 super.testErrors(pair, true); 758 } 759 testChannelDefinitionInCombined()760 @Test public void testChannelDefinitionInCombined() throws Exception { 761 String grammar = 762 "grammar T;\n" + 763 "\n" + 764 "channels {\n" + 765 " WHITESPACE_CHANNEL,\n" + 766 " COMMENT_CHANNEL\n" + 767 "}\n" + 768 "\n" + 769 "start : EOF;\n" + 770 "\n" + 771 "COMMENT: '//' ~[\\n]+ -> channel(COMMENT_CHANNEL);\n" + 772 "WHITESPACE: [ \\t]+ -> channel(WHITESPACE_CHANNEL);\n"; 773 774 String expected = 775 "error(" + ErrorType.CONSTANT_VALUE_IS_NOT_A_RECOGNIZED_CHANNEL_NAME.code + "): T.g4:10:35: COMMENT_CHANNEL is not a recognized channel name\n" + 776 "error(" + ErrorType.CONSTANT_VALUE_IS_NOT_A_RECOGNIZED_CHANNEL_NAME.code + "): T.g4:11:35: WHITESPACE_CHANNEL is not a recognized channel name\n" + 777 "error(" + ErrorType.CHANNELS_BLOCK_IN_COMBINED_GRAMMAR.code + "): T.g4:3:0: custom channels are not supported in combined grammars\n"; 778 779 String[] pair = { grammar, expected }; 780 super.testErrors(pair, true); 781 } 782 783 /** 784 * This is a regression test for antlr/antlr4#497 now that antlr/antlr4#309 785 * is resolved. 786 * https://github.com/antlr/antlr4/issues/497 787 * https://github.com/antlr/antlr4/issues/309 788 */ testChannelDefinitions()789 @Test public void testChannelDefinitions() throws Exception { 790 String grammar = 791 "lexer grammar T;\n" + 792 "\n" + 793 "channels {\n" + 794 " WHITESPACE_CHANNEL,\n" + 795 " COMMENT_CHANNEL\n" + 796 "}\n" + 797 "\n" + 798 "COMMENT: '//' ~[\\n]+ -> channel(COMMENT_CHANNEL);\n" + 799 "WHITESPACE: [ \\t]+ -> channel(WHITESPACE_CHANNEL);\n" + 800 "NEWLINE: '\\r'? '\\n' -> channel(NEWLINE_CHANNEL);"; 801 802 // WHITESPACE_CHANNEL and COMMENT_CHANNEL are defined, but NEWLINE_CHANNEL is not 803 String expected = 804 "error(" + ErrorType.CONSTANT_VALUE_IS_NOT_A_RECOGNIZED_CHANNEL_NAME.code + "): T.g4:10:34: NEWLINE_CHANNEL is not a recognized channel name\n"; 805 806 String[] pair = { grammar, expected }; 807 super.testErrors(pair, true); 808 } 809 810 // Test for https://github.com/antlr/antlr4/issues/1556 testRangeInParserGrammar()811 @Test public void testRangeInParserGrammar() { 812 String grammar = 813 "grammar T;\n"+ 814 "a: 'A'..'Z' ;\n"; 815 String expected = 816 "error(" + ErrorType.TOKEN_RANGE_IN_PARSER.code + "): T.g4:2:4: token ranges not allowed in parser: 'A'..'Z'\n"; 817 818 String[] pair = new String[] { 819 grammar, 820 expected 821 }; 822 823 super.testErrors(pair, true); 824 } 825 } 826