1 /*
2  * [The "BSD license"]
3  *  Copyright (c) 2010 Terence Parr
4  *  All rights reserved.
5  *
6  *  Redistribution and use in source and binary forms, with or without
7  *  modification, are permitted provided that the following conditions
8  *  are met:
9  *  1. Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *      notice, this list of conditions and the following disclaimer in the
13  *      documentation and/or other materials provided with the distribution.
14  *  3. The name of the author may not be used to endorse or promote products
15  *      derived from this software without specific prior written permission.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 package org.antlr.test;
29 
30 import org.antlr.Tool;
31 import org.antlr.analysis.Label;
32 import org.antlr.codegen.CodeGenerator;
33 import org.stringtemplate.v4.ST;
34 import org.antlr.tool.*;
35 import org.junit.Test;
36 
37 import java.util.*;
38 
39 public class TestSymbolDefinitions extends BaseTest {
40 
41 	/** Public default constructor used by TestRig */
TestSymbolDefinitions()42 	public TestSymbolDefinitions() {
43 	}
44 
testParserSimpleTokens()45 	@Test public void testParserSimpleTokens() throws Exception {
46 		Grammar g = new Grammar(
47 				"parser grammar t;\n"+
48 				"a : A | B;\n" +
49 				"b : C ;");
50 		String rules = "a, b";
51 		String tokenNames = "A, B, C";
52 		checkSymbols(g, rules, tokenNames);
53 	}
54 
testParserTokensSection()55 	@Test public void testParserTokensSection() throws Exception {
56 		Grammar g = new Grammar(
57 				"parser grammar t;\n" +
58 				"tokens {\n" +
59 				"  C;\n" +
60 				"  D;" +
61 				"}\n"+
62 				"a : A | B;\n" +
63 				"b : C ;");
64 		String rules = "a, b";
65 		String tokenNames = "A, B, C, D";
66 		checkSymbols(g, rules, tokenNames);
67 	}
68 
testLexerTokensSection()69 	@Test public void testLexerTokensSection() throws Exception {
70 		Grammar g = new Grammar(
71 				"lexer grammar t;\n" +
72 				"tokens {\n" +
73 				"  C;\n" +
74 				"  D;" +
75 				"}\n"+
76 				"A : 'a';\n" +
77 				"C : 'c' ;");
78 		String rules = "A, C, Tokens";
79 		String tokenNames = "A, C, D";
80 		checkSymbols(g, rules, tokenNames);
81 	}
82 
testTokensSectionWithAssignmentSection()83 	@Test public void testTokensSectionWithAssignmentSection() throws Exception {
84 		Grammar g = new Grammar(
85 				"grammar t;\n" +
86 				"tokens {\n" +
87 				"  C='c';\n" +
88 				"  D;" +
89 				"}\n"+
90 				"a : A | B;\n" +
91 				"b : C ;");
92 		String rules = "a, b";
93 		String tokenNames = "A, B, C, D, 'c'";
94 		checkSymbols(g, rules, tokenNames);
95 	}
96 
testCombinedGrammarLiterals()97 	@Test public void testCombinedGrammarLiterals() throws Exception {
98 		Grammar g = new Grammar(
99 				"grammar t;\n"+
100 				"a : 'begin' b 'end';\n" +
101 				"b : C ';' ;\n" +
102 				"ID : 'a' ;\n" +
103 				"FOO : 'foo' ;\n" +  // "foo" is not a token name
104 				"C : 'c' ;\n");        // nor is 'c'
105 		String rules = "a, b";
106 		String tokenNames = "C, FOO, ID, 'begin', 'end', ';'";
107 		checkSymbols(g, rules, tokenNames);
108 	}
109 
testLiteralInParserAndLexer()110 	@Test public void testLiteralInParserAndLexer() throws Exception {
111 		// 'x' is token and char in lexer rule
112 		Grammar g = new Grammar(
113 				"grammar t;\n" +
114 				"a : 'x' E ; \n" +
115 				"E: 'x' '0' ;\n");        // nor is 'c'
116 		String literals = "['x']";
117 		String foundLiterals = g.getStringLiterals().toString();
118 		assertEquals(literals, foundLiterals);
119 
120 		String implicitLexer =
121 			"lexer grammar t;" + newline +
122 			"T__5 : 'x' ;" + newline +
123 			"" + newline +
124 			"// $ANTLR src \"<string>\" 3" + newline +
125 			"E: 'x' '0' ;";
126 		assertEquals(implicitLexer, g.getLexerGrammar());
127 	}
128 
testCombinedGrammarWithRefToLiteralButNoTokenIDRef()129 	@Test public void testCombinedGrammarWithRefToLiteralButNoTokenIDRef() throws Exception {
130 		Grammar g = new Grammar(
131 				"grammar t;\n"+
132 				"a : 'a' ;\n" +
133 				"A : 'a' ;\n");
134 		String rules = "a";
135 		String tokenNames = "A, 'a'";
136 		checkSymbols(g, rules, tokenNames);
137 	}
138 
testSetDoesNotMissTokenAliases()139 	@Test public void testSetDoesNotMissTokenAliases() throws Exception {
140 		Grammar g = new Grammar(
141 				"grammar t;\n"+
142 				"a : 'a'|'b' ;\n" +
143 				"A : 'a' ;\n" +
144 				"B : 'b' ;\n");
145 		String rules = "a";
146 		String tokenNames = "A, 'a', B, 'b'";
147 		checkSymbols(g, rules, tokenNames);
148 	}
149 
testSimplePlusEqualLabel()150 	@Test public void testSimplePlusEqualLabel() throws Exception {
151 		Grammar g = new Grammar(
152 				"parser grammar t;\n"+
153 				"a : ids+=ID ( COMMA ids+=ID )* ;\n");
154 		String rule = "a";
155 		String tokenLabels = "ids";
156 		String ruleLabels = null;
157 		checkPlusEqualsLabels(g, rule, tokenLabels, ruleLabels);
158 	}
159 
testMixedPlusEqualLabel()160 	@Test public void testMixedPlusEqualLabel() throws Exception {
161 		Grammar g = new Grammar(
162 				"grammar t;\n"+
163 				"options {output=AST;}\n" +
164 				"a : id+=ID ( ',' e+=expr )* ;\n" +
165 				"expr : 'e';\n" +
166 				"ID : 'a';\n");
167 		String rule = "a";
168 		String tokenLabels = "id";
169 		String ruleLabels = "e";
170 		checkPlusEqualsLabels(g, rule, tokenLabels, ruleLabels);
171 	}
172 
173 	// T E S T  L I T E R A L  E S C A P E S
174 
testParserCharLiteralWithEscape()175 	@Test public void testParserCharLiteralWithEscape() throws Exception {
176 		Grammar g = new Grammar(
177 				"grammar t;\n"+
178 				"a : '\\n';\n");
179 		Set literals = g.getStringLiterals();
180 		// must store literals how they appear in the antlr grammar
181 		assertEquals("'\\n'", literals.toArray()[0]);
182 	}
183 
testTokenInTokensSectionAndTokenRuleDef()184 	@Test public void testTokenInTokensSectionAndTokenRuleDef() throws Exception {
185 		// this must return A not I to the parser; calling a nonfragment rule
186 		// from a nonfragment rule does not set the overall token.
187 		String grammar =
188 			"grammar P;\n" +
189 			"tokens { B='}'; }\n"+
190 			"a : A B {System.out.println(input);} ;\n"+
191 			"A : 'a' ;\n" +
192 			"B : '}' ;\n"+
193 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;";
194 		String found = execParser("P.g", grammar, "PParser", "PLexer",
195 								  "a", "a}", false);
196 		assertEquals("a}\n", found);
197 	}
198 
testTokenInTokensSectionAndTokenRuleDef2()199 	@Test public void testTokenInTokensSectionAndTokenRuleDef2() throws Exception {
200 		// this must return A not I to the parser; calling a nonfragment rule
201 		// from a nonfragment rule does not set the overall token.
202 		String grammar =
203 			"grammar P;\n" +
204 			"tokens { B='}'; }\n"+
205 			"a : A '}' {System.out.println(input);} ;\n"+
206 			"A : 'a' ;\n" +
207 			"B : '}' {/* */} ;\n"+
208 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;";
209 		String found = execParser("P.g", grammar, "PParser", "PLexer",
210 								  "a", "a}", false);
211 		assertEquals("a}\n", found);
212 	}
213 
214 
testRefToRuleWithNoReturnValue()215 	@Test public void testRefToRuleWithNoReturnValue() throws Exception {
216 		ErrorQueue equeue = new ErrorQueue();
217 		ErrorManager.setErrorListener(equeue);
218 
219 		String grammarStr =
220 			"grammar P;\n" +
221 			"a : x=b ;\n" +
222 			"b : B ;\n" +
223 			"B : 'b' ;\n";
224 		Grammar g = new Grammar(grammarStr);
225 
226 		Tool antlr = newTool();
227 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
228 		g.setCodeGenerator(generator);
229 		ST recogST = generator.genRecognizer();
230 		String code = recogST.render();
231 		assertTrue("not expecting label", code.indexOf("x=b();")<0);
232 
233 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
234 	}
235 
236 	// T E S T  E R R O R S
237 
testParserStringLiterals()238 	@Test public void testParserStringLiterals() throws Exception {
239 		ErrorQueue equeue = new ErrorQueue();
240 		ErrorManager.setErrorListener(equeue);
241 		Grammar g = new Grammar(
242 				"parser grammar t;\n"+
243 				"a : 'begin' b ;\n" +
244 				"b : C ;");
245 		Object expectedArg = "'begin'";
246 		int expectedMsgID = ErrorManager.MSG_LITERAL_NOT_ASSOCIATED_WITH_LEXER_RULE;
247 		GrammarSemanticsMessage expectedMessage =
248 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
249 		checkGrammarSemanticsError(equeue, expectedMessage);
250 	}
251 
testParserCharLiterals()252 	@Test public void testParserCharLiterals() throws Exception {
253 		ErrorQueue equeue = new ErrorQueue();
254 		ErrorManager.setErrorListener(equeue);
255 		Grammar g = new Grammar(
256 				"parser grammar t;\n"+
257 				"a : '(' b ;\n" +
258 				"b : C ;");
259 		Object expectedArg = "'('";
260 		int expectedMsgID = ErrorManager.MSG_LITERAL_NOT_ASSOCIATED_WITH_LEXER_RULE;
261 		GrammarSemanticsMessage expectedMessage =
262 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
263 		checkGrammarSemanticsError(equeue, expectedMessage);
264 	}
265 
testEmptyNotChar()266 	@Test public void testEmptyNotChar() throws Exception {
267 		ErrorQueue equeue = new ErrorQueue();
268 		ErrorManager.setErrorListener(equeue);
269 		Grammar g = new Grammar(
270 				"grammar foo;\n" +
271 				"a : (~'x')+ ;\n");
272 		g.buildNFA();
273 		Object expectedArg = "'x'";
274 		int expectedMsgID = ErrorManager.MSG_EMPTY_COMPLEMENT;
275 		GrammarSemanticsMessage expectedMessage =
276 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
277 		checkGrammarSemanticsError(equeue, expectedMessage);
278 	}
279 
testEmptyNotToken()280 	@Test public void testEmptyNotToken() throws Exception {
281 		ErrorQueue equeue = new ErrorQueue();
282 		ErrorManager.setErrorListener(equeue);
283 		Grammar g = new Grammar(
284 				"grammar foo;\n" +
285 				"a : (~A)+ ;\n");
286 		g.buildNFA();
287 		Object expectedArg = "A";
288 		int expectedMsgID = ErrorManager.MSG_EMPTY_COMPLEMENT;
289 		GrammarSemanticsMessage expectedMessage =
290 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
291 		checkGrammarSemanticsError(equeue, expectedMessage);
292 	}
293 
testEmptyNotSet()294 	@Test public void testEmptyNotSet() throws Exception {
295 		ErrorQueue equeue = new ErrorQueue();
296 		ErrorManager.setErrorListener(equeue);
297 		Grammar g = new Grammar(
298 				"grammar foo;\n" +
299 				"a : (~(A|B))+ ;\n");
300 		g.buildNFA();
301 		Object expectedArg = null;
302 		int expectedMsgID = ErrorManager.MSG_EMPTY_COMPLEMENT;
303 		GrammarSemanticsMessage expectedMessage =
304 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
305 		checkGrammarSemanticsError(equeue, expectedMessage);
306 	}
307 
testStringLiteralInParserTokensSection()308 	@Test public void testStringLiteralInParserTokensSection() throws Exception {
309 		ErrorQueue equeue = new ErrorQueue();
310 		ErrorManager.setErrorListener(equeue); // unique listener per thread
311 		Grammar g = new Grammar(
312 				"parser grammar t;\n" +
313 				"tokens {\n" +
314 				"  B='begin';\n" +
315 				"}\n"+
316 				"a : A B;\n" +
317 				"b : C ;");
318 		Object expectedArg = "'begin'";
319 		int expectedMsgID = ErrorManager.MSG_LITERAL_NOT_ASSOCIATED_WITH_LEXER_RULE;
320 		GrammarSemanticsMessage expectedMessage =
321 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
322 		checkGrammarSemanticsError(equeue, expectedMessage);
323 	}
324 
testCharLiteralInParserTokensSection()325 	@Test public void testCharLiteralInParserTokensSection() throws Exception {
326 		ErrorQueue equeue = new ErrorQueue();
327 		ErrorManager.setErrorListener(equeue); // unique listener per thread
328 		Grammar g = new Grammar(
329 				"parser grammar t;\n" +
330 				"tokens {\n" +
331 				"  B='(';\n" +
332 				"}\n"+
333 				"a : A B;\n" +
334 				"b : C ;");
335 		Object expectedArg = "'('";
336 		int expectedMsgID = ErrorManager.MSG_LITERAL_NOT_ASSOCIATED_WITH_LEXER_RULE;
337 		GrammarSemanticsMessage expectedMessage =
338 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
339 		checkGrammarSemanticsError(equeue, expectedMessage);
340 	}
341 
testCharLiteralInLexerTokensSection()342 	@Test public void testCharLiteralInLexerTokensSection() throws Exception {
343 		ErrorQueue equeue = new ErrorQueue();
344 		ErrorManager.setErrorListener(equeue); // unique listener per thread
345 		Grammar g = new Grammar(
346 				"lexer grammar t;\n" +
347 				"tokens {\n" +
348 				"  B='(';\n" +
349 				"}\n"+
350 				"ID : 'a';\n");
351 		Object expectedArg = "'('";
352 		int expectedMsgID = ErrorManager.MSG_CANNOT_ALIAS_TOKENS_IN_LEXER;
353 		GrammarSemanticsMessage expectedMessage =
354 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
355 		checkGrammarSemanticsError(equeue, expectedMessage);
356 	}
357 
testRuleRedefinition()358 	@Test public void testRuleRedefinition() throws Exception {
359 		ErrorQueue equeue = new ErrorQueue();
360 		ErrorManager.setErrorListener(equeue); // unique listener per thread
361 		Grammar g = new Grammar(
362 				"parser grammar t;\n"+
363 				"a : A | B;\n" +
364 				"a : C ;");
365 
366 		Object expectedArg = "a";
367 		int expectedMsgID = ErrorManager.MSG_RULE_REDEFINITION;
368 		GrammarSemanticsMessage expectedMessage =
369 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
370 		checkGrammarSemanticsError(equeue, expectedMessage);
371 	}
372 
testLexerRuleRedefinition()373 	@Test public void testLexerRuleRedefinition() throws Exception {
374 		ErrorQueue equeue = new ErrorQueue();
375 		ErrorManager.setErrorListener(equeue); // unique listener per thread
376 		Grammar g = new Grammar(
377 				"lexer grammar t;\n"+
378 				"ID : 'a' ;\n" +
379 				"ID : 'd' ;");
380 
381 		Object expectedArg = "ID";
382 		int expectedMsgID = ErrorManager.MSG_RULE_REDEFINITION;
383 		GrammarSemanticsMessage expectedMessage =
384 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
385 		checkGrammarSemanticsError(equeue, expectedMessage);
386 	}
387 
testCombinedRuleRedefinition()388 	@Test public void testCombinedRuleRedefinition() throws Exception {
389 		ErrorQueue equeue = new ErrorQueue();
390 		ErrorManager.setErrorListener(equeue); // unique listener per thread
391 		Grammar g = new Grammar(
392 				"grammar t;\n"+
393 				"x : ID ;\n" +
394 				"ID : 'a' ;\n" +
395 				"x : ID ID ;");
396 
397 		Object expectedArg = "x";
398 		int expectedMsgID = ErrorManager.MSG_RULE_REDEFINITION;
399 		GrammarSemanticsMessage expectedMessage =
400 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
401 		checkGrammarSemanticsError(equeue, expectedMessage);
402 	}
403 
testUndefinedToken()404 	@Test public void testUndefinedToken() throws Exception {
405 		ErrorQueue equeue = new ErrorQueue();
406 		ErrorManager.setErrorListener(equeue); // unique listener per thread
407 		Grammar g = new Grammar(
408 				"grammar t;\n"+
409 				"x : ID ;");
410 
411 		Object expectedArg = "ID";
412 		int expectedMsgID = ErrorManager.MSG_NO_TOKEN_DEFINITION;
413 		GrammarSemanticsMessage expectedMessage =
414 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
415 		checkGrammarSemanticsWarning(equeue, expectedMessage);
416 	}
417 
testUndefinedTokenOkInParser()418 	@Test public void testUndefinedTokenOkInParser() throws Exception {
419 		ErrorQueue equeue = new ErrorQueue();
420 		ErrorManager.setErrorListener(equeue); // unique listener per thread
421 		Grammar g = new Grammar(
422 				"parser grammar t;\n"+
423 				"x : ID ;");
424 		assertEquals("should not be an error", 0, equeue.errors.size());
425 	}
426 
testUndefinedRule()427 	@Test public void testUndefinedRule() throws Exception {
428 		ErrorQueue equeue = new ErrorQueue();
429 		ErrorManager.setErrorListener(equeue); // unique listener per thread
430 		Grammar g = new Grammar(
431 				"grammar t;\n"+
432 				"x : r ;");
433 
434 		Object expectedArg = "r";
435 		int expectedMsgID = ErrorManager.MSG_UNDEFINED_RULE_REF;
436 		GrammarSemanticsMessage expectedMessage =
437 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
438 		checkGrammarSemanticsError(equeue, expectedMessage);
439 	}
440 
testLexerRuleInParser()441 	@Test public void testLexerRuleInParser() throws Exception {
442 		ErrorQueue equeue = new ErrorQueue();
443 		ErrorManager.setErrorListener(equeue); // unique listener per thread
444 		Grammar g = new Grammar(
445 				"parser grammar t;\n"+
446 				"X : ;");
447 
448 		Object expectedArg = "X";
449 		int expectedMsgID = ErrorManager.MSG_LEXER_RULES_NOT_ALLOWED;
450 		GrammarSemanticsMessage expectedMessage =
451 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
452 		checkGrammarSemanticsError(equeue, expectedMessage);
453 	}
454 
testParserRuleInLexer()455 	@Test public void testParserRuleInLexer() throws Exception {
456 		ErrorQueue equeue = new ErrorQueue();
457 		ErrorManager.setErrorListener(equeue); // unique listener per thread
458 		Grammar g = new Grammar(
459 				"lexer grammar t;\n"+
460 				"a : ;");
461 
462 		Object expectedArg = "a";
463 		int expectedMsgID = ErrorManager.MSG_PARSER_RULES_NOT_ALLOWED;
464 		GrammarSemanticsMessage expectedMessage =
465 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
466 		checkGrammarSemanticsError(equeue, expectedMessage);
467 	}
468 
testRuleScopeConflict()469 	@Test public void testRuleScopeConflict() throws Exception {
470 		ErrorQueue equeue = new ErrorQueue();
471 		ErrorManager.setErrorListener(equeue); // unique listener per thread
472 		Grammar g = new Grammar(
473 			"grammar t;\n"+
474 			"scope a {\n" +
475 			"  int n;\n" +
476 			"}\n" +
477 			"a : \n" +
478 			"  ;\n");
479 
480 		Object expectedArg = "a";
481 		int expectedMsgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE;
482 		GrammarSemanticsMessage expectedMessage =
483 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
484 		checkGrammarSemanticsError(equeue, expectedMessage);
485 	}
486 
testTokenRuleScopeConflict()487 	@Test public void testTokenRuleScopeConflict() throws Exception {
488 		ErrorQueue equeue = new ErrorQueue();
489 		ErrorManager.setErrorListener(equeue); // unique listener per thread
490 		Grammar g = new Grammar(
491 			"grammar t;\n"+
492 			"scope ID {\n" +
493 			"  int n;\n" +
494 			"}\n" +
495 			"ID : 'a'\n" +
496 			"  ;\n");
497 
498 		Object expectedArg = "ID";
499 		int expectedMsgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE;
500 		GrammarSemanticsMessage expectedMessage =
501 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
502 		checkGrammarSemanticsError(equeue, expectedMessage);
503 	}
504 
testTokenScopeConflict()505 	@Test public void testTokenScopeConflict() throws Exception {
506 		ErrorQueue equeue = new ErrorQueue();
507 		ErrorManager.setErrorListener(equeue); // unique listener per thread
508 		Grammar g = new Grammar(
509 			"grammar t;\n"+
510 			"tokens { ID; }\n"+
511 			"scope ID {\n" +
512 			"  int n;\n" +
513 			"}\n" +
514 			"a : \n" +
515 			"  ;\n");
516 
517 		Object expectedArg = "ID";
518 		int expectedMsgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE;
519 		GrammarSemanticsMessage expectedMessage =
520 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
521 		checkGrammarSemanticsError(equeue, expectedMessage);
522 	}
523 
testTokenRuleScopeConflictInLexerGrammar()524 	@Test public void testTokenRuleScopeConflictInLexerGrammar() throws Exception {
525 		ErrorQueue equeue = new ErrorQueue();
526 		ErrorManager.setErrorListener(equeue); // unique listener per thread
527 		Grammar g = new Grammar(
528 			"lexer grammar t;\n"+
529 			"scope ID {\n" +
530 			"  int n;\n" +
531 			"}\n" +
532 			"ID : 'a'\n" +
533 			"  ;\n");
534 
535 		Object expectedArg = "ID";
536 		int expectedMsgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE;
537 		GrammarSemanticsMessage expectedMessage =
538 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
539 		checkGrammarSemanticsError(equeue, expectedMessage);
540 	}
541 
testTokenLabelScopeConflict()542 	@Test public void testTokenLabelScopeConflict() throws Exception {
543 		ErrorQueue equeue = new ErrorQueue();
544 		ErrorManager.setErrorListener(equeue); // unique listener per thread
545 		Grammar g = new Grammar(
546 			"parser grammar t;\n"+
547 			"scope s {\n" +
548 			"  int n;\n" +
549 			"}\n" +
550 			"a : s=ID \n" +
551 			"  ;\n");
552 
553 		Object expectedArg = "s";
554 		int expectedMsgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE;
555 		GrammarSemanticsMessage expectedMessage =
556 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
557 		checkGrammarSemanticsError(equeue, expectedMessage);
558 	}
559 
testRuleLabelScopeConflict()560 	@Test public void testRuleLabelScopeConflict() throws Exception {
561 		ErrorQueue equeue = new ErrorQueue();
562 		ErrorManager.setErrorListener(equeue); // unique listener per thread
563 		Grammar g = new Grammar(
564 			"parser grammar t;\n"+
565 			"scope s {\n" +
566 			"  int n;\n" +
567 			"}\n" +
568 			"a : s=b \n" +
569 			"  ;\n" +
570 			"b : ;\n");
571 
572 		Object expectedArg = "s";
573 		int expectedMsgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE;
574 		GrammarSemanticsMessage expectedMessage =
575 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
576 		checkGrammarSemanticsError(equeue, expectedMessage);
577 	}
578 
testLabelAndRuleNameConflict()579 	@Test public void testLabelAndRuleNameConflict() throws Exception {
580 		ErrorQueue equeue = new ErrorQueue();
581 		ErrorManager.setErrorListener(equeue); // unique listener per thread
582 		Grammar g = new Grammar(
583 			"parser grammar t;\n"+
584 			"a : c=b \n" +
585 			"  ;\n" +
586 			"b : ;\n" +
587 			"c : ;\n");
588 
589 		Object expectedArg = "c";
590 		int expectedMsgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE;
591 		GrammarSemanticsMessage expectedMessage =
592 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
593 		checkGrammarSemanticsError(equeue, expectedMessage);
594 	}
595 
testLabelAndTokenNameConflict()596 	@Test public void testLabelAndTokenNameConflict() throws Exception {
597 		ErrorQueue equeue = new ErrorQueue();
598 		ErrorManager.setErrorListener(equeue); // unique listener per thread
599 		Grammar g = new Grammar(
600 			"parser grammar t;\n"+
601 			"a : ID=b \n" +
602 			"  ;\n" +
603 			"b : ID ;\n" +
604 			"c : ;\n");
605 
606 		Object expectedArg = "ID";
607 		int expectedMsgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_TOKEN;
608 		GrammarSemanticsMessage expectedMessage =
609 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
610 		checkGrammarSemanticsError(equeue, expectedMessage);
611 	}
612 
testLabelAndArgConflict()613 	@Test public void testLabelAndArgConflict() throws Exception {
614 		ErrorQueue equeue = new ErrorQueue();
615 		ErrorManager.setErrorListener(equeue); // unique listener per thread
616 		Grammar g = new Grammar(
617 			"parser grammar t;\n"+
618 			"a[int i] returns [int x]: i=ID \n" +
619 			"  ;\n");
620 
621 		Object expectedArg = "i";
622 		int expectedMsgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE_ARG_RETVAL;
623 		GrammarSemanticsMessage expectedMessage =
624 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
625 		checkGrammarSemanticsError(equeue, expectedMessage);
626 	}
627 
testLabelAndParameterConflict()628 	@Test public void testLabelAndParameterConflict() throws Exception {
629 		ErrorQueue equeue = new ErrorQueue();
630 		ErrorManager.setErrorListener(equeue); // unique listener per thread
631 		Grammar g = new Grammar(
632 			"parser grammar t;\n"+
633 			"a[int i] returns [int x]: x=ID \n" +
634 			"  ;\n");
635 
636 		Object expectedArg = "x";
637 		int expectedMsgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE_ARG_RETVAL;
638 		GrammarSemanticsMessage expectedMessage =
639 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
640 		checkGrammarSemanticsError(equeue, expectedMessage);
641 	}
642 
testLabelRuleScopeConflict()643 	@Test public void testLabelRuleScopeConflict() throws Exception {
644 		ErrorQueue equeue = new ErrorQueue();
645 		ErrorManager.setErrorListener(equeue); // unique listener per thread
646 		Grammar g = new Grammar(
647 			"parser grammar t;\n"+
648 			"a\n" +
649 			"scope {" +
650 			"  int n;" +
651 			"}\n" +
652 			"  : n=ID\n" +
653 			"  ;\n");
654 
655 		Object expectedArg = "n";
656 		Object expectedArg2 = "a";
657 		int expectedMsgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE_SCOPE_ATTRIBUTE;
658 		GrammarSemanticsMessage expectedMessage =
659 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
660 		checkGrammarSemanticsError(equeue, expectedMessage);
661 	}
662 
testRuleScopeArgConflict()663 	@Test public void testRuleScopeArgConflict() throws Exception {
664 		ErrorQueue equeue = new ErrorQueue();
665 		ErrorManager.setErrorListener(equeue); // unique listener per thread
666 		Grammar g = new Grammar(
667 			"parser grammar t;\n"+
668 			"a[int n]\n" +
669 			"scope {" +
670 			"  int n;" +
671 			"}\n" +
672 			"  : \n" +
673 			"  ;\n");
674 
675 		Object expectedArg = "n";
676 		Object expectedArg2 = "a";
677 		int expectedMsgID = ErrorManager.MSG_ATTRIBUTE_CONFLICTS_WITH_RULE_ARG_RETVAL;
678 		GrammarSemanticsMessage expectedMessage =
679 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
680 		checkGrammarSemanticsError(equeue, expectedMessage);
681 	}
682 
testRuleScopeReturnValueConflict()683 	@Test public void testRuleScopeReturnValueConflict() throws Exception {
684 		ErrorQueue equeue = new ErrorQueue();
685 		ErrorManager.setErrorListener(equeue); // unique listener per thread
686 		Grammar g = new Grammar(
687 			"parser grammar t;\n"+
688 			"a returns [int n]\n" +
689 			"scope {" +
690 			"  int n;" +
691 			"}\n" +
692 			"  : \n" +
693 			"  ;\n");
694 
695 		Object expectedArg = "n";
696 		Object expectedArg2 = "a";
697 		int expectedMsgID = ErrorManager.MSG_ATTRIBUTE_CONFLICTS_WITH_RULE_ARG_RETVAL;
698 		GrammarSemanticsMessage expectedMessage =
699 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
700 		checkGrammarSemanticsError(equeue, expectedMessage);
701 	}
702 
testRuleScopeRuleNameConflict()703 	@Test public void testRuleScopeRuleNameConflict() throws Exception {
704 		ErrorQueue equeue = new ErrorQueue();
705 		ErrorManager.setErrorListener(equeue); // unique listener per thread
706 		Grammar g = new Grammar(
707 			"parser grammar t;\n"+
708 			"a\n" +
709 			"scope {" +
710 			"  int a;" +
711 			"}\n" +
712 			"  : \n" +
713 			"  ;\n");
714 
715 		Object expectedArg = "a";
716 		Object expectedArg2 = null;
717 		int expectedMsgID = ErrorManager.MSG_ATTRIBUTE_CONFLICTS_WITH_RULE;
718 		GrammarSemanticsMessage expectedMessage =
719 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
720 		checkGrammarSemanticsError(equeue, expectedMessage);
721 	}
722 
testBadGrammarOption()723 	@Test public void testBadGrammarOption() throws Exception {
724 		ErrorQueue equeue = new ErrorQueue();
725 		ErrorManager.setErrorListener(equeue); // unique listener per thread
726 		Tool antlr = newTool();
727 		Grammar g = new Grammar(antlr,
728 								"grammar t;\n"+
729 								"options {foo=3; language=Java;}\n" +
730 								"a : 'a';\n");
731 
732 		Object expectedArg = "foo";
733 		int expectedMsgID = ErrorManager.MSG_ILLEGAL_OPTION;
734 		GrammarSemanticsMessage expectedMessage =
735 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
736 		checkGrammarSemanticsError(equeue, expectedMessage);
737 	}
738 
testBadRuleOption()739 	@Test public void testBadRuleOption() throws Exception {
740 		ErrorQueue equeue = new ErrorQueue();
741 		ErrorManager.setErrorListener(equeue); // unique listener per thread
742 		Grammar g = new Grammar(
743 				"grammar t;\n"+
744 				"a\n"+
745 				"options {k=3; tokenVocab=blort;}\n" +
746 				"  : 'a';\n");
747 
748 		Object expectedArg = "tokenVocab";
749 		int expectedMsgID = ErrorManager.MSG_ILLEGAL_OPTION;
750 		GrammarSemanticsMessage expectedMessage =
751 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
752 		checkGrammarSemanticsError(equeue, expectedMessage);
753 	}
754 
testBadSubRuleOption()755 	@Test public void testBadSubRuleOption() throws Exception {
756 		ErrorQueue equeue = new ErrorQueue();
757 		ErrorManager.setErrorListener(equeue); // unique listener per thread
758 		Grammar g = new Grammar(
759 				"grammar t;\n"+
760 				"a : ( options {k=3; language=Java;}\n" +
761 				"    : 'a'\n" +
762 				"    | 'b'\n" +
763 				"    )\n" +
764 				"  ;\n");
765 		Object expectedArg = "language";
766 		int expectedMsgID = ErrorManager.MSG_ILLEGAL_OPTION;
767 		GrammarSemanticsMessage expectedMessage =
768 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
769 		checkGrammarSemanticsError(equeue, expectedMessage);
770 	}
771 
testTokenVocabStringUsedInLexer()772 	@Test public void testTokenVocabStringUsedInLexer() throws Exception {
773 		ErrorQueue equeue = new ErrorQueue();
774 		ErrorManager.setErrorListener(equeue);
775 		String tokens =
776 			"';'=4\n";
777         mkdir(tmpdir);
778         writeFile(tmpdir, "T.tokens", tokens);
779 
780 		String importer =
781 			"lexer grammar B; \n" +
782 			"options\t{tokenVocab=T;} \n" +
783 			"SEMI:';' ; \n" ;
784 		writeFile(tmpdir, "B.g", importer);
785 		Tool antlr = newTool(new String[] {"-lib", tmpdir});
786 		CompositeGrammar composite = new CompositeGrammar();
787 		Grammar g = new Grammar(antlr,tmpdir+"/B.g",composite);
788 		g.parseAndBuildAST();
789 		g.composite.assignTokenTypes();
790 
791 		String expectedTokenIDToTypeMap = "[SEMI=4]";
792 		String expectedStringLiteralToTypeMap = "{';'=4}";
793 		String expectedTypeToTokenList = "[SEMI]";
794 
795 		assertEquals(expectedTokenIDToTypeMap,
796 					 realElements(g.composite.tokenIDToTypeMap).toString());
797 		assertEquals(expectedStringLiteralToTypeMap, g.composite.stringLiteralToTypeMap.toString());
798 		assertEquals(expectedTypeToTokenList,
799 					 realElements(g.composite.typeToTokenList).toString());
800 
801 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
802 	}
803 
testTokenVocabStringUsedInCombined()804 	@Test public void testTokenVocabStringUsedInCombined() throws Exception {
805 		ErrorQueue equeue = new ErrorQueue();
806 		ErrorManager.setErrorListener(equeue);
807 		String tokens =
808 			"';'=4\n";
809         mkdir(tmpdir);
810 		writeFile(tmpdir, "T.tokens", tokens);
811 
812 		String importer =
813 			"grammar B; \n" +
814 			"options\t{tokenVocab=T;} \n" +
815 			"SEMI:';' ; \n" ;
816 		writeFile(tmpdir, "B.g", importer);
817 		Tool antlr = newTool(new String[] {"-lib", tmpdir});
818 		CompositeGrammar composite = new CompositeGrammar();
819 		Grammar g = new Grammar(antlr,tmpdir+"/B.g",composite);
820 		g.parseAndBuildAST();
821 		g.composite.assignTokenTypes();
822 
823 		String expectedTokenIDToTypeMap = "[SEMI=4]";
824 		String expectedStringLiteralToTypeMap = "{';'=4}";
825 		String expectedTypeToTokenList = "[SEMI]";
826 
827 		assertEquals(expectedTokenIDToTypeMap,
828 					 realElements(g.composite.tokenIDToTypeMap).toString());
829 		assertEquals(expectedStringLiteralToTypeMap, g.composite.stringLiteralToTypeMap.toString());
830 		assertEquals(expectedTypeToTokenList,
831 					 realElements(g.composite.typeToTokenList).toString());
832 
833 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
834 	}
835 
checkPlusEqualsLabels(Grammar g, String ruleName, String tokenLabelsStr, String ruleLabelsStr)836 	protected void checkPlusEqualsLabels(Grammar g,
837 										 String ruleName,
838 										 String tokenLabelsStr,
839 										 String ruleLabelsStr)
840 		throws Exception
841 	{
842 		// make sure expected += labels are there
843 		Rule r = g.getRule(ruleName);
844 		StringTokenizer st = new StringTokenizer(tokenLabelsStr, ", ");
845 		Set tokenLabels = null;
846 		while ( st.hasMoreTokens() ) {
847 			if ( tokenLabels==null ) {
848 				tokenLabels = new HashSet();
849 			}
850 			String labelName = st.nextToken();
851 			tokenLabels.add(labelName);
852 		}
853 		Set ruleLabels = null;
854 		if ( ruleLabelsStr!=null ) {
855 			st = new StringTokenizer(ruleLabelsStr, ", ");
856 			ruleLabels = new HashSet();
857 			while ( st.hasMoreTokens() ) {
858 				String labelName = st.nextToken();
859 				ruleLabels.add(labelName);
860 			}
861 		}
862 		assertTrue("token += labels mismatch; "+tokenLabels+"!="+r.tokenListLabels,
863 				   (tokenLabels!=null && r.tokenListLabels!=null) ||
864 				   (tokenLabels==null && r.tokenListLabels==null));
865 		assertTrue("rule += labels mismatch; "+ruleLabels+"!="+r.ruleListLabels,
866 				   (ruleLabels!=null && r.ruleListLabels!=null) ||
867 				   (ruleLabels==null && r.ruleListLabels==null));
868 		if ( tokenLabels!=null ) {
869 			assertEquals(tokenLabels, r.tokenListLabels.keySet());
870 		}
871 		if ( ruleLabels!=null ) {
872 			assertEquals(ruleLabels, r.ruleListLabels.keySet());
873 		}
874 	}
875 
checkSymbols(Grammar g, String rulesStr, String tokensStr)876 	protected void checkSymbols(Grammar g,
877 								String rulesStr,
878 								String tokensStr)
879 		throws Exception
880 	{
881 		Set tokens = g.getTokenDisplayNames();
882 
883 		// make sure expected tokens are there
884 		StringTokenizer st = new StringTokenizer(tokensStr, ", ");
885 		while ( st.hasMoreTokens() ) {
886 			String tokenName = st.nextToken();
887 			assertTrue("token "+tokenName+" expected",
888 					   g.getTokenType(tokenName)!=Label.INVALID);
889 			tokens.remove(tokenName);
890 		}
891 		// make sure there are not any others (other than <EOF> etc...)
892 		for (Iterator iter = tokens.iterator(); iter.hasNext();) {
893 			String tokenName = (String) iter.next();
894 			assertTrue("unexpected token name "+tokenName,
895 					   g.getTokenType(tokenName)<Label.MIN_TOKEN_TYPE);
896 		}
897 
898 		// make sure all expected rules are there
899 		st = new StringTokenizer(rulesStr, ", ");
900 		int n = 0;
901 		while ( st.hasMoreTokens() ) {
902 			String ruleName = st.nextToken();
903 			assertNotNull("rule "+ruleName+" expected", g.getRule(ruleName));
904 			n++;
905 		}
906 		Collection rules = g.getRules();
907 		//System.out.println("rules="+rules);
908 		// make sure there are no extra rules
909 		assertEquals("number of rules mismatch; expecting "+n+"; found "+rules.size(), n, rules.size());
910 
911 	}
912 
913 }
914