/* * [The "BSD license"] * Copyright (c) 2010 Terence Parr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.antlr.test; import org.antlr.Tool; import org.antlr.analysis.Label; import org.antlr.codegen.CodeGenerator; import org.stringtemplate.v4.ST; import org.antlr.tool.*; import org.junit.Test; import java.util.*; public class TestSymbolDefinitions extends BaseTest { /** Public default constructor used by TestRig */ public TestSymbolDefinitions() { } @Test public void testParserSimpleTokens() throws Exception { Grammar g = new Grammar( "parser grammar t;\n"+ "a : A | B;\n" + "b : C ;"); String rules = "a, b"; String tokenNames = "A, B, C"; checkSymbols(g, rules, tokenNames); } @Test public void testParserTokensSection() throws Exception { Grammar g = new Grammar( "parser grammar t;\n" + "tokens {\n" + " C;\n" + " D;" + "}\n"+ "a : A | B;\n" + "b : C ;"); String rules = "a, b"; String tokenNames = "A, B, C, D"; checkSymbols(g, rules, tokenNames); } @Test public void testLexerTokensSection() throws Exception { Grammar g = new Grammar( "lexer grammar t;\n" + "tokens {\n" + " C;\n" + " D;" + "}\n"+ "A : 'a';\n" + "C : 'c' ;"); String rules = "A, C, Tokens"; String tokenNames = "A, C, D"; checkSymbols(g, rules, tokenNames); } @Test public void testTokensSectionWithAssignmentSection() throws Exception { Grammar g = new Grammar( "grammar t;\n" + "tokens {\n" + " C='c';\n" + " D;" + "}\n"+ "a : A | B;\n" + "b : C ;"); String rules = "a, b"; String tokenNames = "A, B, C, D, 'c'"; checkSymbols(g, rules, tokenNames); } @Test public void testCombinedGrammarLiterals() throws Exception { Grammar g = new Grammar( "grammar t;\n"+ "a : 'begin' b 'end';\n" + "b : C ';' ;\n" + "ID : 'a' ;\n" + "FOO : 'foo' ;\n" + // "foo" is not a token name "C : 'c' ;\n"); // nor is 'c' String rules = "a, b"; String tokenNames = "C, FOO, ID, 'begin', 'end', ';'"; checkSymbols(g, rules, tokenNames); } @Test public void testLiteralInParserAndLexer() throws Exception { // 'x' is token and char in lexer rule Grammar g = new Grammar( "grammar t;\n" + "a : 'x' E ; \n" + "E: 'x' '0' ;\n"); // nor is 'c' String literals = "['x']"; String foundLiterals = g.getStringLiterals().toString(); assertEquals(literals, foundLiterals); String implicitLexer = "lexer grammar t;" + newline + "T__5 : 'x' ;" + newline + "" + newline + "// $ANTLR src \"\" 3" + newline + "E: 'x' '0' ;"; assertEquals(implicitLexer, g.getLexerGrammar()); } @Test public void testCombinedGrammarWithRefToLiteralButNoTokenIDRef() throws Exception { Grammar g = new Grammar( "grammar t;\n"+ "a : 'a' ;\n" + "A : 'a' ;\n"); String rules = "a"; String tokenNames = "A, 'a'"; checkSymbols(g, rules, tokenNames); } @Test public void testSetDoesNotMissTokenAliases() throws Exception { Grammar g = new Grammar( "grammar t;\n"+ "a : 'a'|'b' ;\n" + "A : 'a' ;\n" + "B : 'b' ;\n"); String rules = "a"; String tokenNames = "A, 'a', B, 'b'"; checkSymbols(g, rules, tokenNames); } @Test public void testSimplePlusEqualLabel() throws Exception { Grammar g = new Grammar( "parser grammar t;\n"+ "a : ids+=ID ( COMMA ids+=ID )* ;\n"); String rule = "a"; String tokenLabels = "ids"; String ruleLabels = null; checkPlusEqualsLabels(g, rule, tokenLabels, ruleLabels); } @Test public void testMixedPlusEqualLabel() throws Exception { Grammar g = new Grammar( "grammar t;\n"+ "options {output=AST;}\n" + "a : id+=ID ( ',' e+=expr )* ;\n" + "expr : 'e';\n" + "ID : 'a';\n"); String rule = "a"; String tokenLabels = "id"; String ruleLabels = "e"; checkPlusEqualsLabels(g, rule, tokenLabels, ruleLabels); } // T E S T L I T E R A L E S C A P E S @Test public void testParserCharLiteralWithEscape() throws Exception { Grammar g = new Grammar( "grammar t;\n"+ "a : '\\n';\n"); Set literals = g.getStringLiterals(); // must store literals how they appear in the antlr grammar assertEquals("'\\n'", literals.toArray()[0]); } @Test public void testTokenInTokensSectionAndTokenRuleDef() throws Exception { // this must return A not I to the parser; calling a nonfragment rule // from a nonfragment rule does not set the overall token. String grammar = "grammar P;\n" + "tokens { B='}'; }\n"+ "a : A B {System.out.println(input);} ;\n"+ "A : 'a' ;\n" + "B : '}' ;\n"+ "WS : (' '|'\\n') {$channel=HIDDEN;} ;"; String found = execParser("P.g", grammar, "PParser", "PLexer", "a", "a}", false); assertEquals("a}\n", found); } @Test public void testTokenInTokensSectionAndTokenRuleDef2() throws Exception { // this must return A not I to the parser; calling a nonfragment rule // from a nonfragment rule does not set the overall token. String grammar = "grammar P;\n" + "tokens { B='}'; }\n"+ "a : A '}' {System.out.println(input);} ;\n"+ "A : 'a' ;\n" + "B : '}' {/* */} ;\n"+ "WS : (' '|'\\n') {$channel=HIDDEN;} ;"; String found = execParser("P.g", grammar, "PParser", "PLexer", "a", "a}", false); assertEquals("a}\n", found); } @Test public void testRefToRuleWithNoReturnValue() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); String grammarStr = "grammar P;\n" + "a : x=b ;\n" + "b : B ;\n" + "B : 'b' ;\n"; Grammar g = new Grammar(grammarStr); Tool antlr = newTool(); CodeGenerator generator = new CodeGenerator(antlr, g, "Java"); g.setCodeGenerator(generator); ST recogST = generator.genRecognizer(); String code = recogST.render(); assertTrue("not expecting label", code.indexOf("x=b();")<0); assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size()); } // T E S T E R R O R S @Test public void testParserStringLiterals() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); Grammar g = new Grammar( "parser grammar t;\n"+ "a : 'begin' b ;\n" + "b : C ;"); Object expectedArg = "'begin'"; int expectedMsgID = ErrorManager.MSG_LITERAL_NOT_ASSOCIATED_WITH_LEXER_RULE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testParserCharLiterals() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); Grammar g = new Grammar( "parser grammar t;\n"+ "a : '(' b ;\n" + "b : C ;"); Object expectedArg = "'('"; int expectedMsgID = ErrorManager.MSG_LITERAL_NOT_ASSOCIATED_WITH_LEXER_RULE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testEmptyNotChar() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); Grammar g = new Grammar( "grammar foo;\n" + "a : (~'x')+ ;\n"); g.buildNFA(); Object expectedArg = "'x'"; int expectedMsgID = ErrorManager.MSG_EMPTY_COMPLEMENT; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testEmptyNotToken() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); Grammar g = new Grammar( "grammar foo;\n" + "a : (~A)+ ;\n"); g.buildNFA(); Object expectedArg = "A"; int expectedMsgID = ErrorManager.MSG_EMPTY_COMPLEMENT; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testEmptyNotSet() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); Grammar g = new Grammar( "grammar foo;\n" + "a : (~(A|B))+ ;\n"); g.buildNFA(); Object expectedArg = null; int expectedMsgID = ErrorManager.MSG_EMPTY_COMPLEMENT; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testStringLiteralInParserTokensSection() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n" + "tokens {\n" + " B='begin';\n" + "}\n"+ "a : A B;\n" + "b : C ;"); Object expectedArg = "'begin'"; int expectedMsgID = ErrorManager.MSG_LITERAL_NOT_ASSOCIATED_WITH_LEXER_RULE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testCharLiteralInParserTokensSection() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n" + "tokens {\n" + " B='(';\n" + "}\n"+ "a : A B;\n" + "b : C ;"); Object expectedArg = "'('"; int expectedMsgID = ErrorManager.MSG_LITERAL_NOT_ASSOCIATED_WITH_LEXER_RULE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testCharLiteralInLexerTokensSection() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "lexer grammar t;\n" + "tokens {\n" + " B='(';\n" + "}\n"+ "ID : 'a';\n"); Object expectedArg = "'('"; int expectedMsgID = ErrorManager.MSG_CANNOT_ALIAS_TOKENS_IN_LEXER; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testRuleRedefinition() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "a : A | B;\n" + "a : C ;"); Object expectedArg = "a"; int expectedMsgID = ErrorManager.MSG_RULE_REDEFINITION; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testLexerRuleRedefinition() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "lexer grammar t;\n"+ "ID : 'a' ;\n" + "ID : 'd' ;"); Object expectedArg = "ID"; int expectedMsgID = ErrorManager.MSG_RULE_REDEFINITION; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testCombinedRuleRedefinition() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "grammar t;\n"+ "x : ID ;\n" + "ID : 'a' ;\n" + "x : ID ID ;"); Object expectedArg = "x"; int expectedMsgID = ErrorManager.MSG_RULE_REDEFINITION; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testUndefinedToken() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "grammar t;\n"+ "x : ID ;"); Object expectedArg = "ID"; int expectedMsgID = ErrorManager.MSG_NO_TOKEN_DEFINITION; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsWarning(equeue, expectedMessage); } @Test public void testUndefinedTokenOkInParser() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "x : ID ;"); assertEquals("should not be an error", 0, equeue.errors.size()); } @Test public void testUndefinedRule() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "grammar t;\n"+ "x : r ;"); Object expectedArg = "r"; int expectedMsgID = ErrorManager.MSG_UNDEFINED_RULE_REF; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testLexerRuleInParser() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "X : ;"); Object expectedArg = "X"; int expectedMsgID = ErrorManager.MSG_LEXER_RULES_NOT_ALLOWED; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testParserRuleInLexer() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "lexer grammar t;\n"+ "a : ;"); Object expectedArg = "a"; int expectedMsgID = ErrorManager.MSG_PARSER_RULES_NOT_ALLOWED; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testRuleScopeConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "grammar t;\n"+ "scope a {\n" + " int n;\n" + "}\n" + "a : \n" + " ;\n"); Object expectedArg = "a"; int expectedMsgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testTokenRuleScopeConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "grammar t;\n"+ "scope ID {\n" + " int n;\n" + "}\n" + "ID : 'a'\n" + " ;\n"); Object expectedArg = "ID"; int expectedMsgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testTokenScopeConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "grammar t;\n"+ "tokens { ID; }\n"+ "scope ID {\n" + " int n;\n" + "}\n" + "a : \n" + " ;\n"); Object expectedArg = "ID"; int expectedMsgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testTokenRuleScopeConflictInLexerGrammar() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "lexer grammar t;\n"+ "scope ID {\n" + " int n;\n" + "}\n" + "ID : 'a'\n" + " ;\n"); Object expectedArg = "ID"; int expectedMsgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testTokenLabelScopeConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "scope s {\n" + " int n;\n" + "}\n" + "a : s=ID \n" + " ;\n"); Object expectedArg = "s"; int expectedMsgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testRuleLabelScopeConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "scope s {\n" + " int n;\n" + "}\n" + "a : s=b \n" + " ;\n" + "b : ;\n"); Object expectedArg = "s"; int expectedMsgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testLabelAndRuleNameConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "a : c=b \n" + " ;\n" + "b : ;\n" + "c : ;\n"); Object expectedArg = "c"; int expectedMsgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testLabelAndTokenNameConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "a : ID=b \n" + " ;\n" + "b : ID ;\n" + "c : ;\n"); Object expectedArg = "ID"; int expectedMsgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_TOKEN; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testLabelAndArgConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "a[int i] returns [int x]: i=ID \n" + " ;\n"); Object expectedArg = "i"; int expectedMsgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE_ARG_RETVAL; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testLabelAndParameterConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "a[int i] returns [int x]: x=ID \n" + " ;\n"); Object expectedArg = "x"; int expectedMsgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE_ARG_RETVAL; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testLabelRuleScopeConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "a\n" + "scope {" + " int n;" + "}\n" + " : n=ID\n" + " ;\n"); Object expectedArg = "n"; Object expectedArg2 = "a"; int expectedMsgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE_SCOPE_ATTRIBUTE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testRuleScopeArgConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "a[int n]\n" + "scope {" + " int n;" + "}\n" + " : \n" + " ;\n"); Object expectedArg = "n"; Object expectedArg2 = "a"; int expectedMsgID = ErrorManager.MSG_ATTRIBUTE_CONFLICTS_WITH_RULE_ARG_RETVAL; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testRuleScopeReturnValueConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "a returns [int n]\n" + "scope {" + " int n;" + "}\n" + " : \n" + " ;\n"); Object expectedArg = "n"; Object expectedArg2 = "a"; int expectedMsgID = ErrorManager.MSG_ATTRIBUTE_CONFLICTS_WITH_RULE_ARG_RETVAL; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testRuleScopeRuleNameConflict() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "parser grammar t;\n"+ "a\n" + "scope {" + " int a;" + "}\n" + " : \n" + " ;\n"); Object expectedArg = "a"; Object expectedArg2 = null; int expectedMsgID = ErrorManager.MSG_ATTRIBUTE_CONFLICTS_WITH_RULE; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testBadGrammarOption() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Tool antlr = newTool(); Grammar g = new Grammar(antlr, "grammar t;\n"+ "options {foo=3; language=Java;}\n" + "a : 'a';\n"); Object expectedArg = "foo"; int expectedMsgID = ErrorManager.MSG_ILLEGAL_OPTION; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testBadRuleOption() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "grammar t;\n"+ "a\n"+ "options {k=3; tokenVocab=blort;}\n" + " : 'a';\n"); Object expectedArg = "tokenVocab"; int expectedMsgID = ErrorManager.MSG_ILLEGAL_OPTION; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testBadSubRuleOption() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); // unique listener per thread Grammar g = new Grammar( "grammar t;\n"+ "a : ( options {k=3; language=Java;}\n" + " : 'a'\n" + " | 'b'\n" + " )\n" + " ;\n"); Object expectedArg = "language"; int expectedMsgID = ErrorManager.MSG_ILLEGAL_OPTION; GrammarSemanticsMessage expectedMessage = new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); checkGrammarSemanticsError(equeue, expectedMessage); } @Test public void testTokenVocabStringUsedInLexer() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); String tokens = "';'=4\n"; mkdir(tmpdir); writeFile(tmpdir, "T.tokens", tokens); String importer = "lexer grammar B; \n" + "options\t{tokenVocab=T;} \n" + "SEMI:';' ; \n" ; writeFile(tmpdir, "B.g", importer); Tool antlr = newTool(new String[] {"-lib", tmpdir}); CompositeGrammar composite = new CompositeGrammar(); Grammar g = new Grammar(antlr,tmpdir+"/B.g",composite); g.parseAndBuildAST(); g.composite.assignTokenTypes(); String expectedTokenIDToTypeMap = "[SEMI=4]"; String expectedStringLiteralToTypeMap = "{';'=4}"; String expectedTypeToTokenList = "[SEMI]"; assertEquals(expectedTokenIDToTypeMap, realElements(g.composite.tokenIDToTypeMap).toString()); assertEquals(expectedStringLiteralToTypeMap, g.composite.stringLiteralToTypeMap.toString()); assertEquals(expectedTypeToTokenList, realElements(g.composite.typeToTokenList).toString()); assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size()); } @Test public void testTokenVocabStringUsedInCombined() throws Exception { ErrorQueue equeue = new ErrorQueue(); ErrorManager.setErrorListener(equeue); String tokens = "';'=4\n"; mkdir(tmpdir); writeFile(tmpdir, "T.tokens", tokens); String importer = "grammar B; \n" + "options\t{tokenVocab=T;} \n" + "SEMI:';' ; \n" ; writeFile(tmpdir, "B.g", importer); Tool antlr = newTool(new String[] {"-lib", tmpdir}); CompositeGrammar composite = new CompositeGrammar(); Grammar g = new Grammar(antlr,tmpdir+"/B.g",composite); g.parseAndBuildAST(); g.composite.assignTokenTypes(); String expectedTokenIDToTypeMap = "[SEMI=4]"; String expectedStringLiteralToTypeMap = "{';'=4}"; String expectedTypeToTokenList = "[SEMI]"; assertEquals(expectedTokenIDToTypeMap, realElements(g.composite.tokenIDToTypeMap).toString()); assertEquals(expectedStringLiteralToTypeMap, g.composite.stringLiteralToTypeMap.toString()); assertEquals(expectedTypeToTokenList, realElements(g.composite.typeToTokenList).toString()); assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size()); } protected void checkPlusEqualsLabels(Grammar g, String ruleName, String tokenLabelsStr, String ruleLabelsStr) throws Exception { // make sure expected += labels are there Rule r = g.getRule(ruleName); StringTokenizer st = new StringTokenizer(tokenLabelsStr, ", "); Set tokenLabels = null; while ( st.hasMoreTokens() ) { if ( tokenLabels==null ) { tokenLabels = new HashSet(); } String labelName = st.nextToken(); tokenLabels.add(labelName); } Set ruleLabels = null; if ( ruleLabelsStr!=null ) { st = new StringTokenizer(ruleLabelsStr, ", "); ruleLabels = new HashSet(); while ( st.hasMoreTokens() ) { String labelName = st.nextToken(); ruleLabels.add(labelName); } } assertTrue("token += labels mismatch; "+tokenLabels+"!="+r.tokenListLabels, (tokenLabels!=null && r.tokenListLabels!=null) || (tokenLabels==null && r.tokenListLabels==null)); assertTrue("rule += labels mismatch; "+ruleLabels+"!="+r.ruleListLabels, (ruleLabels!=null && r.ruleListLabels!=null) || (ruleLabels==null && r.ruleListLabels==null)); if ( tokenLabels!=null ) { assertEquals(tokenLabels, r.tokenListLabels.keySet()); } if ( ruleLabels!=null ) { assertEquals(ruleLabels, r.ruleListLabels.keySet()); } } protected void checkSymbols(Grammar g, String rulesStr, String tokensStr) throws Exception { Set tokens = g.getTokenDisplayNames(); // make sure expected tokens are there StringTokenizer st = new StringTokenizer(tokensStr, ", "); while ( st.hasMoreTokens() ) { String tokenName = st.nextToken(); assertTrue("token "+tokenName+" expected", g.getTokenType(tokenName)!=Label.INVALID); tokens.remove(tokenName); } // make sure there are not any others (other than etc...) for (Iterator iter = tokens.iterator(); iter.hasNext();) { String tokenName = (String) iter.next(); assertTrue("unexpected token name "+tokenName, g.getTokenType(tokenName)