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.ErrorType;
10 import org.antlr.v4.tool.LexerGrammar;
11 import org.junit.Before;
12 import org.junit.Test;
13 
14 import static org.junit.Assert.assertEquals;
15 
16 /** */
17 public class TestSymbolIssues extends BaseJavaToolTest {
18     static String[] A = {
19         // INPUT
20         "grammar A;\n" +
21         "options { opt='sss'; k=3; }\n" +
22         "\n" +
23         "@members {foo}\n" +
24         "@members {bar}\n" +
25         "@lexer::header {package jj;}\n" +
26         "@lexer::header {package kk;}\n" +
27         "\n" +
28         "a[int i] returns [foo f] : X ID a[3] b[34] c ;\n" +
29         "b returns [int g] : Y 'y' 'if' a ;\n" +
30         "c : FJKD ;\n" +
31         "\n" +
32         "ID : 'a'..'z'+ ID ;",
33         // YIELDS
34 			"error(" + ErrorType.ACTION_REDEFINITION.code + "): A.g4:5:1: redefinition of members action\n" +
35 			"error(" + ErrorType.ACTION_REDEFINITION.code + "): A.g4:7:1: redefinition of header action\n" +
36 			"warning(" + ErrorType.ILLEGAL_OPTION.code + "): A.g4:2:10: unsupported option opt\n" +
37 			"warning(" + ErrorType.ILLEGAL_OPTION.code + "): A.g4:2:21: unsupported option k\n" +
38 			"error(" + ErrorType.ACTION_REDEFINITION.code + "): A.g4:5:1: redefinition of members action\n" +
39 			"warning(" + ErrorType.IMPLICIT_TOKEN_DEFINITION.code + "): A.g4:9:27: implicit definition of token X in parser\n" +
40 			"warning(" + ErrorType.IMPLICIT_TOKEN_DEFINITION.code + "): A.g4:10:20: implicit definition of token Y in parser\n" +
41 			"warning(" + ErrorType.IMPLICIT_TOKEN_DEFINITION.code + "): A.g4:11:4: implicit definition of token FJKD in parser\n" +
42 			"error(" + ErrorType.RULE_HAS_NO_ARGS.code + "): A.g4:9:37: rule b has no defined parameters\n" +
43 			"error(" + ErrorType.MISSING_RULE_ARGS.code + "): A.g4:10:31: missing argument(s) on rule reference: a\n"
44     };
45 
46     static String[] B = {
47         // INPUT
48         "parser grammar B;\n" +
49         "tokens { ID, FOO, X, Y }\n" +
50         "\n" +
51         "a : s=ID b+=ID X=ID '.' ;\n" +
52         "\n" +
53         "b : x=ID x+=ID ;\n" +
54         "\n" +
55         "s : FOO ;",
56         // YIELDS
57 		"error(" + ErrorType.LABEL_CONFLICTS_WITH_RULE.code + "): B.g4:4:4: label s conflicts with rule with same name\n" +
58 		"error(" + ErrorType.LABEL_CONFLICTS_WITH_RULE.code + "): B.g4:4:9: label b conflicts with rule with same name\n" +
59 		"error(" + ErrorType.LABEL_CONFLICTS_WITH_TOKEN.code + "): B.g4:4:15: label X conflicts with token with same name\n" +
60 		"error(" + ErrorType.LABEL_TYPE_CONFLICT.code + "): B.g4:6:9: label x type mismatch with previous definition: TOKEN_LIST_LABEL!=TOKEN_LABEL\n" +
61 		"error(" + ErrorType.IMPLICIT_STRING_DEFINITION.code + "): B.g4:4:20: cannot create implicit token for string literal in non-combined grammar: '.'\n"
62     };
63 
64     static String[] D = {
65         // INPUT
66         "parser grammar D;\n" +
67 		"tokens{ID}\n" +
68         "a[int j] \n" +
69         "        :       i=ID j=ID ;\n" +
70         "\n" +
71         "b[int i] returns [int i] : ID ;\n" +
72         "\n" +
73         "c[int i] returns [String k]\n" +
74         "        :       ID ;",
75 
76         // YIELDS
77         "error(" + ErrorType.LABEL_CONFLICTS_WITH_ARG.code + "): D.g4:4:21: label j conflicts with parameter with same name\n" +
78 		"error(" + ErrorType.RETVAL_CONFLICTS_WITH_ARG.code + "): D.g4:6:22: return value i conflicts with parameter with same name\n"
79     };
80 
81 	static String[] E = {
82 		// INPUT
83 		"grammar E;\n" +
84 		"tokens {\n" +
85 		"	A, A,\n" +
86 		"	B,\n" +
87 		"	C\n" +
88 		"}\n" +
89 		"a : A ;\n",
90 
91 		// YIELDS
92 		"warning(" + ErrorType.TOKEN_NAME_REASSIGNMENT.code + "): E.g4:3:4: token name A is already defined\n"
93 	};
94 
95 	static String[] F = {
96 		// INPUT
97 		"lexer grammar F;\n" +
98 		"A: 'a';\n" +
99 		"mode M1;\n" +
100 		"A1: 'a';\n" +
101 		"mode M2;\n" +
102 		"A2: 'a';\n" +
103 		"M1: 'b';\n",
104 
105 		// YIELDS
106 		"error(" + ErrorType.MODE_CONFLICTS_WITH_TOKEN.code + "): F.g4:3:0: mode M1 conflicts with token with same name\n"
107 	};
108 
109 	@Before
110 	@Override
testSetUp()111 	public void testSetUp() throws Exception {
112 		super.testSetUp();
113 	}
114 
testA()115     @Test public void testA() { super.testErrors(A, false); }
testB()116     @Test public void testB() { super.testErrors(B, false); }
testD()117 	@Test public void testD() { super.testErrors(D, false); }
testE()118 	@Test public void testE() { super.testErrors(E, false); }
testF()119 	@Test public void testF() { super.testErrors(F, false); }
120 
testStringLiteralRedefs()121 	@Test public void testStringLiteralRedefs() throws Exception {
122 		String grammar =
123 			"lexer grammar L;\n" +
124 			"A : 'a' ;\n" +
125 			"mode X;\n"+
126 			"B : 'a' ;\n"+
127 			"mode Y;\n"+
128 			"C : 'a' ;\n";
129 
130 		LexerGrammar g = new LexerGrammar(grammar);
131 
132 		String expectedTokenIDToTypeMap = "{EOF=-1, A=1, B=2, C=3}";
133 		String expectedStringLiteralToTypeMap = "{}";
134 		String expectedTypeToTokenList = "[A, B, C]";
135 
136 		assertEquals(expectedTokenIDToTypeMap, g.tokenNameToTypeMap.toString());
137 		assertEquals(expectedStringLiteralToTypeMap, g.stringLiteralToTypeMap.toString());
138 		assertEquals(expectedTypeToTokenList, realElements(g.typeToTokenList).toString());
139 	}
140 
testEmptyLexerModeDetection()141 	@Test public void testEmptyLexerModeDetection() throws Exception {
142 		String[] test = {
143 			"lexer grammar L;\n" +
144 			"A : 'a';\n" +
145 			"mode X;\n" +
146 			"fragment B : 'b';",
147 
148 			"error(" + ErrorType.MODE_WITHOUT_RULES.code + "): L.g4:3:5: lexer mode X must contain at least one non-fragment rule\n"
149 		};
150 
151 		testErrors(test, false);
152 	}
153 
testEmptyLexerRuleDetection()154 	@Test public void testEmptyLexerRuleDetection() throws Exception {
155 		String[] test = {
156 			"lexer grammar L;\n" +
157 			"A : 'a';\n" +
158 			"WS : [ \t]* -> skip;\n" +
159 			"mode X;\n" +
160 			"  B : C;\n" +
161 			"  fragment C : A | (A C)?;",
162 
163 			"warning(" + ErrorType.EPSILON_TOKEN.code + "): L.g4:3:0: non-fragment lexer rule WS can match the empty string\n" +
164 			"warning(" + ErrorType.EPSILON_TOKEN.code + "): L.g4:5:2: non-fragment lexer rule B can match the empty string\n"
165 		};
166 
167 		testErrors(test, false);
168 	}
169 
testTokensModesChannelsDeclarationConflictsWithReserved()170 	@Test public void testTokensModesChannelsDeclarationConflictsWithReserved() throws Exception {
171 		String[] test = {
172 			"lexer grammar L;\n" +
173 			"channels { SKIP, HIDDEN, channel0 }\n" +
174 			"A: 'a';\n" +
175 			"mode MAX_CHAR_VALUE;\n" +
176 			"MIN_CHAR_VALUE: 'a';\n" +
177 			"mode DEFAULT_MODE;\n" +
178 			"B: 'b';\n" +
179 			"mode M;\n" +
180 			"C: 'c';",
181 
182 			"error(" + ErrorType.RESERVED_RULE_NAME.code + "): L.g4:5:0: cannot declare a rule with reserved name MIN_CHAR_VALUE\n" +
183 			"error(" + ErrorType.MODE_CONFLICTS_WITH_COMMON_CONSTANTS.code + "): L.g4:4:0: cannot use or declare mode with reserved name MAX_CHAR_VALUE\n" +
184 			"error(" + ErrorType.CHANNEL_CONFLICTS_WITH_COMMON_CONSTANTS.code + "): L.g4:2:11: cannot use or declare channel with reserved name SKIP\n" +
185 			"error(" + ErrorType.CHANNEL_CONFLICTS_WITH_COMMON_CONSTANTS.code + "): L.g4:2:17: cannot use or declare channel with reserved name HIDDEN\n"
186 		};
187 
188 		testErrors(test, false);
189 	}
190 
testTokensModesChannelsUsingConflictsWithReserved()191 	@Test public void testTokensModesChannelsUsingConflictsWithReserved() throws Exception {
192 		String[] test = {
193 			"lexer grammar L;\n" +
194 			"A: 'a' -> channel(SKIP);\n" +
195 			"B: 'b' -> type(MORE);\n" +
196 			"C: 'c' -> mode(SKIP);\n" +
197 			"D: 'd' -> channel(HIDDEN);\n" +
198 			"E: 'e' -> type(EOF);\n" +
199 			"F: 'f' -> pushMode(DEFAULT_MODE);",
200 
201 			"error(" + ErrorType.CHANNEL_CONFLICTS_WITH_COMMON_CONSTANTS.code + "): L.g4:2:18: cannot use or declare channel with reserved name SKIP\n" +
202 			"error(" + ErrorType.TOKEN_CONFLICTS_WITH_COMMON_CONSTANTS.code + "): L.g4:3:15: cannot use or declare token with reserved name MORE\n" +
203 			"error(" + ErrorType.MODE_CONFLICTS_WITH_COMMON_CONSTANTS.code + "): L.g4:4:15: cannot use or declare mode with reserved name SKIP\n"
204 		};
205 
206 		testErrors(test, false);
207 	}
208 
209 	// https://github.com/antlr/antlr4/issues/1411
testWrongIdForTypeChannelModeCommand()210 	@Test public void testWrongIdForTypeChannelModeCommand() throws Exception {
211 		String[] test = {
212 			"lexer grammar L;\n" +
213 			"tokens { TOKEN1 }\n" +
214 			"channels { CHANNEL1 }\n" +
215 			"TOKEN: 'asdf' -> type(CHANNEL1), channel(MODE1), mode(TOKEN1);\n" +
216 			"mode MODE1;\n" +
217 			"MODE1_TOKEN: 'qwer';",
218 
219 			"error(" + ErrorType.CONSTANT_VALUE_IS_NOT_A_RECOGNIZED_TOKEN_NAME.code + "): L.g4:4:22: CHANNEL1 is not a recognized token name\n" +
220 			"error(" + ErrorType.CONSTANT_VALUE_IS_NOT_A_RECOGNIZED_CHANNEL_NAME.code + "): L.g4:4:41: MODE1 is not a recognized channel name\n" +
221 			"error(" + ErrorType.CONSTANT_VALUE_IS_NOT_A_RECOGNIZED_MODE_NAME.code + "): L.g4:4:54: TOKEN1 is not a recognized mode name\n"
222 		};
223 
224 		testErrors(test, false);
225 	}
226 
227 	// https://github.com/antlr/antlr4/issues/1388
testDuplicatedCommands()228 	@Test public void testDuplicatedCommands() throws Exception {
229 		String[] test = {
230 			"lexer grammar Lexer;\n" +
231 			"channels { CHANNEL1, CHANNEL2 }\n" +
232 			"tokens { TEST1, TEST2 }\n" +
233 			"TOKEN: 'a' -> mode(MODE1), mode(MODE2);\n" +
234 			"TOKEN1: 'b' -> pushMode(MODE1), mode(MODE2);\n" +
235 			"TOKEN2: 'c' -> pushMode(MODE1), pushMode(MODE2); // pushMode is not duplicate\n" +
236 			"TOKEN3: 'd' -> popMode, popMode;                 // popMode is not duplicate\n" +
237 			"mode MODE1;\n" +
238 			"MODE1_TOKEN: 'e';\n" +
239 			"mode MODE2;\n" +
240 			"MODE2_TOKEN: 'f';\n" +
241 			"MODE2_TOKEN1: 'g' -> type(TEST1), type(TEST2);\n" +
242 			"MODE2_TOKEN2: 'h' -> channel(CHANNEL1), channel(CHANNEL2), channel(DEFAULT_TOKEN_CHANNEL);",
243 
244 			"warning(" + ErrorType.DUPLICATED_COMMAND.code + "): Lexer.g4:4:27: duplicated command mode\n" +
245 			"warning(" + ErrorType.DUPLICATED_COMMAND.code + "): Lexer.g4:12:34: duplicated command type\n" +
246 			"warning(" + ErrorType.DUPLICATED_COMMAND.code + "): Lexer.g4:13:40: duplicated command channel\n" +
247 			"warning(" + ErrorType.DUPLICATED_COMMAND.code + "): Lexer.g4:13:59: duplicated command channel\n"
248 		};
249 
250 		testErrors(test, false);
251 	}
252 
253 	// https://github.com/antlr/antlr4/issues/1388
testIncompatibleCommands()254 	@Test public void testIncompatibleCommands() throws Exception {
255 		String[] test = {
256 				"lexer grammar L;\n" +
257 				"channels { CHANNEL1 }\n" +
258 				"tokens { TYPE1 }\n" +
259 				"// Incompatible\n" +
260 				"T00: 'a00' -> skip, more;\n" +
261 				"T01: 'a01' -> skip, type(TYPE1);\n" +
262 				"T02: 'a02' -> skip, channel(CHANNEL1);\n" +
263 				"T03: 'a03' -> more, type(TYPE1);\n" +
264 				"T04: 'a04' -> more, channel(CHANNEL1);\n" +
265 				"T05: 'a05' -> more, skip;\n" +
266 				"T06: 'a06' -> type(TYPE1), skip;\n" +
267 				"T07: 'a07' -> type(TYPE1), more;\n" +
268 				"T08: 'a08' -> channel(CHANNEL1), skip;\n" +
269 				"T09: 'a09' -> channel(CHANNEL1), more;\n" +
270 				"// Allowed\n" +
271 				"T10: 'a10' -> type(TYPE1), channel(CHANNEL1);\n" +
272 				"T11: 'a11' -> channel(CHANNEL1), type(TYPE1);",
273 
274 				"warning(" + ErrorType.INCOMPATIBLE_COMMANDS.code + "): L.g4:5:20: incompatible commands skip and more\n" +
275 				"warning(" + ErrorType.INCOMPATIBLE_COMMANDS.code + "): L.g4:6:20: incompatible commands skip and type\n" +
276 				"warning(" + ErrorType.INCOMPATIBLE_COMMANDS.code + "): L.g4:7:20: incompatible commands skip and channel\n" +
277 				"warning(" + ErrorType.INCOMPATIBLE_COMMANDS.code + "): L.g4:8:20: incompatible commands more and type\n" +
278 				"warning(" + ErrorType.INCOMPATIBLE_COMMANDS.code + "): L.g4:9:20: incompatible commands more and channel\n" +
279 				"warning(" + ErrorType.INCOMPATIBLE_COMMANDS.code + "): L.g4:10:20: incompatible commands more and skip\n" +
280 				"warning(" + ErrorType.INCOMPATIBLE_COMMANDS.code + "): L.g4:11:27: incompatible commands type and skip\n" +
281 				"warning(" + ErrorType.INCOMPATIBLE_COMMANDS.code + "): L.g4:12:27: incompatible commands type and more\n" +
282 				"warning(" + ErrorType.INCOMPATIBLE_COMMANDS.code + "): L.g4:13:33: incompatible commands channel and skip\n" +
283 				"warning(" + ErrorType.INCOMPATIBLE_COMMANDS.code + "): L.g4:14:33: incompatible commands channel and more\n"
284 		};
285 
286 		testErrors(test, false);
287 	}
288 
289 	// https://github.com/antlr/antlr4/issues/1409
testLabelsForTokensWithMixedTypes()290 	@Test public void testLabelsForTokensWithMixedTypes() {
291 		String[] test = {
292 				"grammar L;\n" +
293 				"\n" +
294 				"rule1                                      // Correct (Alternatives)\n" +
295 				"    : t1=a  #aLabel\n" +
296 				"    | t1=b  #bLabel\n" +
297 				"    ;\n" +
298 				"rule2                         //Incorrect type casting in generated code (RULE_LABEL)\n" +
299 				"    : t2=a | t2=b\n" +
300 				"    ;\n" +
301 				"rule3\n" +
302 				"    : t3+=a+ b t3+=c+     //Incorrect type casting in generated code (RULE_LIST_LABEL)\n" +
303 				"    ;\n" +
304 				"rule4\n" +
305 				"    : a t4=A b t4=B c                  // Correct (TOKEN_LABEL)\n" +
306 				"    ;\n" +
307 				"rule5\n" +
308 				"    : a t5+=A b t5+=B c                // Correct (TOKEN_LIST_LABEL)\n" +
309 				"    ;\n" +
310 				"rule6                     // Correct (https://github.com/antlr/antlr4/issues/1543)\n" +
311 				"    : t6=a                          #t6_1_Label\n" +
312 				"    | t6=rule6 b (t61=c)? t62=rule6 #t6_2_Label\n" +
313 				"    | t6=A     a (t61=B)? t62=A     #t6_3_Label\n" +
314 				"    ;\n" +
315 				"rule7                     // Incorrect (https://github.com/antlr/antlr4/issues/1543)\n" +
316 				"    : a\n" +
317 				"    | t7=rule7 b (t71=c)? t72=rule7 \n" +
318 				"    | t7=A     a (t71=B)? t72=A     \n" +
319 				"    ;\n" +
320 				"rule8                     // Correct (https://github.com/antlr/antlr4/issues/1543)\n" +
321 				"    : a\n" +
322 				"    | t8=rule8 a t8=rule8\n" +
323 				"    | t8=rule8 b t8=rule8\n" +
324 				"    ;\n" +
325 				"a: A;\n" +
326 				"b: B;\n" +
327 				"c: C;\n" +
328 				"A: 'a';\n" +
329 				"B: 'b';\n" +
330 				"C: 'c';\n",
331 
332 				"error(" + ErrorType.LABEL_TYPE_CONFLICT.code + "): L.g4:8:13: label t2=b type mismatch with previous definition: t2=a\n" +
333 				"error(" + ErrorType.LABEL_TYPE_CONFLICT.code + "): L.g4:11:15: label t3+=c type mismatch with previous definition: t3+=a\n" +
334 
335 				"error(" + ErrorType.LABEL_TYPE_CONFLICT.code + "): L.g4:24:0: label t7 type mismatch with previous definition: TOKEN_LABEL!=RULE_LABEL\n" +
336 				"error(" + ErrorType.LABEL_TYPE_CONFLICT.code + "): L.g4:24:0: label t71 type mismatch with previous definition: RULE_LABEL!=TOKEN_LABEL\n" +
337 				"error(" + ErrorType.LABEL_TYPE_CONFLICT.code + "): L.g4:24:0: label t72 type mismatch with previous definition: RULE_LABEL!=TOKEN_LABEL\n"
338 		};
339 
340 		testErrors(test, false);
341 	}
342 
343 	// https://github.com/antlr/antlr4/issues/1543
testLabelsForTokensWithMixedTypesLRWithLabels()344 	@Test public void testLabelsForTokensWithMixedTypesLRWithLabels() {
345 		String[] test = {
346 				"grammar L;\n" +
347 				"\n" +
348 				"expr\n" +
349 				"    : left=A '+' right=A        #primary\n" +
350 				"    | left=expr '-' right=expr  #sub\n" +
351 				"    ;\n" +
352 				"\n" +
353 				"A: 'a';\n" +
354 				"B: 'b';\n" +
355 				"C: 'c';\n",
356 
357 				""
358 		};
359 
360 		testErrors(test, false);
361 	}
362 
363 	// https://github.com/antlr/antlr4/issues/1543
364 	@Test
testLabelsForTokensWithMixedTypesLRWithoutLabels()365 	public void testLabelsForTokensWithMixedTypesLRWithoutLabels() {
366 		String[] test = {
367 				"grammar L;\n" +
368 				"\n" +
369 				"expr\n" +
370 				"    : left=A '+' right=A\n" +
371 				"    | left=expr '-' right=expr\n" +
372 				"    ;\n" +
373 				"\n" +
374 				"A: 'a';\n" +
375 				"B: 'b';\n" +
376 				"C: 'c';\n",
377 
378 				"error(" + ErrorType.LABEL_TYPE_CONFLICT.code + "): L.g4:3:0: label left type mismatch with previous definition: TOKEN_LABEL!=RULE_LABEL\n" +
379 				"error(" + ErrorType.LABEL_TYPE_CONFLICT.code + "): L.g4:3:0: label right type mismatch with previous definition: RULE_LABEL!=TOKEN_LABEL\n"
380 		};
381 
382 		testErrors(test, false);
383 	}
384 
testCharsCollision()385 	@Test public void testCharsCollision() throws  Exception {
386 		String[] test = {
387 				"lexer grammar L;\n" +
388 				"TOKEN_RANGE:      [aa-f];\n" +
389 				"TOKEN_RANGE_2:    [A-FD-J];\n" +
390 				"TOKEN_RANGE_3:    'Z' | 'K'..'R' | 'O'..'V';\n" +
391 				"TOKEN_RANGE_4:    'g'..'l' | [g-l];\n" +
392 				"TOKEN_RANGE_WITHOUT_COLLISION: '_' | [a-zA-Z];\n" +
393 				"TOKEN_RANGE_WITH_ESCAPED_CHARS: [\\n-\\r] | '\\n'..'\\r';",
394 
395 				"warning(" + ErrorType.CHARACTERS_COLLISION_IN_SET.code + "): L.g4:2:18: chars 'a'..'f' used multiple times in set [aa-f]\n" +
396 				"warning(" + ErrorType.CHARACTERS_COLLISION_IN_SET.code + "): L.g4:3:18: chars 'D'..'J' used multiple times in set [A-FD-J]\n" +
397 				"warning(" + ErrorType.CHARACTERS_COLLISION_IN_SET.code + "): L.g4:4:13: chars 'O'..'V' used multiple times in set 'Z' | 'K'..'R' | 'O'..'V'\n" +
398 				"warning(" + ErrorType.CHARACTERS_COLLISION_IN_SET.code + "): L.g4::: chars 'g' used multiple times in set 'g'..'l'\n" +
399 				"warning(" + ErrorType.CHARACTERS_COLLISION_IN_SET.code + "): L.g4::: chars '\\n' used multiple times in set '\\n'..'\\r'\n"
400 		};
401 
402 		testErrors(test, false);
403 	}
404 
testUnreachableTokens()405 	@Test public void testUnreachableTokens() {
406 		String[] test = {
407 				"lexer grammar Test;\n" +
408 				"TOKEN1: 'as' 'df' | 'qwer';\n" +
409 				"TOKEN2: [0-9];\n" +
410 				"TOKEN3: 'asdf';\n" +
411 				"TOKEN4: 'q' 'w' 'e' 'r' | A;\n" +
412 				"TOKEN5: 'aaaa';\n" +
413 				"TOKEN6: 'asdf';\n" +
414 				"TOKEN7: 'qwer'+;\n" +
415 				"TOKEN8: 'a' 'b' | 'b' | 'a' 'b';\n" +
416 				"fragment\n" +
417 				"TOKEN9: 'asdf' | 'qwer' | 'qwer';\n" +
418 				"TOKEN10: '\\r\\n' | '\\r\\n';\n" +
419 				"TOKEN11: '\\r\\n';\n" +
420 				"\n" +
421 				"mode MODE1;\n" +
422 				"TOKEN12: 'asdf';\n" +
423 				"\n" +
424 				"fragment A: 'A';",
425 
426 				"warning(" + ErrorType.TOKEN_UNREACHABLE.code + "): Test.g4:4:0: One of the token TOKEN3 values unreachable. asdf is always overlapped by token TOKEN1\n" +
427 				"warning(" + ErrorType.TOKEN_UNREACHABLE.code + "): Test.g4:5:0: One of the token TOKEN4 values unreachable. qwer is always overlapped by token TOKEN1\n" +
428 				"warning(" + ErrorType.TOKEN_UNREACHABLE.code + "): Test.g4:7:0: One of the token TOKEN6 values unreachable. asdf is always overlapped by token TOKEN1\n" +
429 				"warning(" + ErrorType.TOKEN_UNREACHABLE.code + "): Test.g4:7:0: One of the token TOKEN6 values unreachable. asdf is always overlapped by token TOKEN3\n" +
430 				"warning(" + ErrorType.TOKEN_UNREACHABLE.code + "): Test.g4:9:0: One of the token TOKEN8 values unreachable. ab is always overlapped by token TOKEN8\n" +
431 				"warning(" + ErrorType.TOKEN_UNREACHABLE.code + "): Test.g4:11:0: One of the token TOKEN9 values unreachable. qwer is always overlapped by token TOKEN9\n" +
432 				"warning(" + ErrorType.TOKEN_UNREACHABLE.code + "): Test.g4:12:0: One of the token TOKEN10 values unreachable. \\r\\n is always overlapped by token TOKEN10\n" +
433 				"warning(" + ErrorType.TOKEN_UNREACHABLE.code + "): Test.g4:13:0: One of the token TOKEN11 values unreachable. \\r\\n is always overlapped by token TOKEN10\n" +
434 				"warning(" + ErrorType.TOKEN_UNREACHABLE.code + "): Test.g4:13:0: One of the token TOKEN11 values unreachable. \\r\\n is always overlapped by token TOKEN10\n"
435 		};
436 
437 		testErrors(test, false);
438 	}
439 }
440