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 */
28package org.antlr.test;
29
30import org.antlr.Tool;
31import org.antlr.analysis.Label;
32import org.antlr.codegen.CodeGenerator;
33import org.stringtemplate.v4.ST;
34import org.antlr.tool.*;
35import org.junit.Test;
36
37import java.util.*;
38
39public 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