Home | History | Annotate | Download | only in test
      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 */
     42 	public TestSymbolDefinitions() {
     43 	}
     44 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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