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