Merge branch 'fix-194'
This commit is contained in:
commit
71cc6fba8a
|
@ -143,6 +143,16 @@ public class LexerATNFactory extends ParserATNFactory {
|
|||
ST cmdST = codegenTemplates.getInstanceOf("Lexer" +
|
||||
CharSupport.capitalize(ID.getText())+
|
||||
"Command");
|
||||
if (cmdST == null) {
|
||||
g.tool.errMgr.grammarError(ErrorType.INVALID_LEXER_COMMAND, g.fileName, ID.token, ID.getText());
|
||||
return "";
|
||||
}
|
||||
|
||||
if (cmdST.impl.formalArguments == null || !cmdST.impl.formalArguments.containsKey("arg")) {
|
||||
g.tool.errMgr.grammarError(ErrorType.UNWANTED_LEXER_COMMAND_ARGUMENT, g.fileName, ID.token, ID.getText());
|
||||
return "";
|
||||
}
|
||||
|
||||
cmdST.add("arg", arg.getText());
|
||||
return cmdST.render();
|
||||
}
|
||||
|
@ -152,6 +162,16 @@ public class LexerATNFactory extends ParserATNFactory {
|
|||
ST cmdST = codegenTemplates.getInstanceOf("Lexer" +
|
||||
CharSupport.capitalize(ID.getText())+
|
||||
"Command");
|
||||
if (cmdST == null) {
|
||||
g.tool.errMgr.grammarError(ErrorType.INVALID_LEXER_COMMAND, g.fileName, ID.token, ID.getText());
|
||||
return "";
|
||||
}
|
||||
|
||||
if (cmdST.impl.formalArguments != null && cmdST.impl.formalArguments.containsKey("arg")) {
|
||||
g.tool.errMgr.grammarError(ErrorType.MISSING_LEXER_COMMAND_ARGUMENT, g.fileName, ID.token, ID.getText());
|
||||
return "";
|
||||
}
|
||||
|
||||
return cmdST.render();
|
||||
}
|
||||
|
||||
|
|
|
@ -171,6 +171,42 @@ public enum ErrorType {
|
|||
* </pre>
|
||||
*/
|
||||
EPSILON_LR_FOLLOW(148, "left recursive rule '<arg>' contains a left recursive alternative which can be followed by the empty string", ErrorSeverity.ERROR),
|
||||
/**
|
||||
* Each lexer command requires an explicit implementation in the target
|
||||
* templates. This error indicates that the command was incorrectly written
|
||||
* or is not supported by the current target.
|
||||
* <p/>
|
||||
* The following rule produces this error.
|
||||
*
|
||||
* <pre>
|
||||
* X : 'foo' -> type(Foo); // ok
|
||||
* Y : 'foo' -> token(Foo); // error 149 (token is not a supported lexer command)
|
||||
* </pre>
|
||||
*/
|
||||
INVALID_LEXER_COMMAND(149, "lexer command '<arg>' does not exist or is not supported by the current target", ErrorSeverity.ERROR),
|
||||
/**
|
||||
* Some lexer commands require an argument.
|
||||
* <p/>
|
||||
* The following rule produces this error.
|
||||
*
|
||||
* <pre>
|
||||
* X : 'foo' -> type(Foo); // ok
|
||||
* Y : 'foo' -> type; // error 150 (the type command requires an argument)
|
||||
* </pre>
|
||||
*/
|
||||
MISSING_LEXER_COMMAND_ARGUMENT(150, "missing argument for lexer command '<arg>'", ErrorSeverity.ERROR),
|
||||
/**
|
||||
* A lexer command which does not take parameters was invoked with an
|
||||
* argument.
|
||||
* <p/>
|
||||
* The following rule produces this error.
|
||||
*
|
||||
* <pre>
|
||||
* X : 'foo' -> popMode; // ok
|
||||
* Y : 'foo' -> popMode(A); // error 151 (the popMode command does not take an argument)
|
||||
* </pre>
|
||||
*/
|
||||
UNWANTED_LEXER_COMMAND_ARGUMENT(151, "lexer command '<arg>' does not take any arguments", ErrorSeverity.ERROR),
|
||||
|
||||
// Backward incompatibility errors
|
||||
V3_TREE_GRAMMAR(200, "tree grammars are not supported in ANTLR 4", ErrorSeverity.ERROR),
|
||||
|
|
|
@ -756,7 +756,7 @@ public class Grammar implements AttributeResolver {
|
|||
*/
|
||||
public static void setNodeOptions(GrammarAST node, GrammarAST options) {
|
||||
GrammarASTWithOptions t = (GrammarASTWithOptions)node;
|
||||
if ( t.getChildCount()==0 ) return;
|
||||
if ( t.getChildCount()==0 || options.getChildCount()==0 ) return;
|
||||
for (Object o : options.getChildren()) {
|
||||
GrammarAST c = (GrammarAST)o;
|
||||
if ( c.getType()==ANTLRParser.ASSIGN ) {
|
||||
|
|
|
@ -293,7 +293,7 @@ public class GrammarTransformPipeline {
|
|||
// COPY OPTIONS
|
||||
GrammarAST optionsRoot =
|
||||
(GrammarAST)combinedAST.getFirstChildWithType(ANTLRParser.OPTIONS);
|
||||
if ( optionsRoot!=null ) {
|
||||
if ( optionsRoot!=null && optionsRoot.getChildCount()!=0 ) {
|
||||
GrammarAST lexerOptionsRoot = (GrammarAST)adaptor.dupNode(optionsRoot);
|
||||
lexerAST.addChild(lexerOptionsRoot);
|
||||
GrammarAST[] options = optionsRoot.getChildren().toArray(new GrammarAST[0]);
|
||||
|
|
|
@ -664,4 +664,21 @@ public class TestCompositeGrammars extends BaseTest {
|
|||
assertEquals("", found);
|
||||
}
|
||||
|
||||
@Test public void testImportedGrammarWithEmptyOptions() throws Exception {
|
||||
String slave =
|
||||
"parser grammar S;\n" +
|
||||
"options {}\n" +
|
||||
"a : B ;\n";
|
||||
mkdir(tmpdir);
|
||||
writeFile(tmpdir, "S.g4", slave);
|
||||
String master =
|
||||
"grammar M;\n" +
|
||||
"import S;\n" +
|
||||
"s : a ;\n" +
|
||||
"B : 'b' ;" +
|
||||
"WS : (' '|'\\n') -> skip ;\n" ;
|
||||
String found = execParser("M.g4", master, "MParser", "MLexer",
|
||||
"s", "b", debug);
|
||||
assertEquals("", found);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -172,4 +172,93 @@ public class TestToolSyntaxErrors extends BaseTest {
|
|||
super.testErrors(pair, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a regression test for antlr/antlr4#194
|
||||
* "NullPointerException on 'options{}' in grammar file"
|
||||
* https://github.com/antlr/antlr4/issues/194
|
||||
*/
|
||||
@Test public void testEmptyGrammarOptions() {
|
||||
String[] pair = new String[] {
|
||||
"grammar A;\n" +
|
||||
"options {}\n" +
|
||||
"a : 'x' ;\n",
|
||||
|
||||
""
|
||||
};
|
||||
super.testErrors(pair, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a "related" regression test for antlr/antlr4#194
|
||||
* "NullPointerException on 'options{}' in grammar file"
|
||||
* https://github.com/antlr/antlr4/issues/194
|
||||
*/
|
||||
@Test public void testEmptyRuleOptions() {
|
||||
String[] pair = new String[] {
|
||||
"grammar A;\n" +
|
||||
"a options{} : 'x' ;\n",
|
||||
|
||||
""
|
||||
};
|
||||
super.testErrors(pair, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a "related" regression test for antlr/antlr4#194
|
||||
* "NullPointerException on 'options{}' in grammar file"
|
||||
* https://github.com/antlr/antlr4/issues/194
|
||||
*/
|
||||
@Test public void testEmptyBlockOptions() {
|
||||
String[] pair = new String[] {
|
||||
"grammar A;\n" +
|
||||
"a : (options{} : 'x') ;\n",
|
||||
|
||||
""
|
||||
};
|
||||
super.testErrors(pair, true);
|
||||
}
|
||||
|
||||
@Test public void testEmptyTokensBlock() {
|
||||
String[] pair = new String[] {
|
||||
"grammar A;\n" +
|
||||
"tokens {}\n" +
|
||||
"a : 'x' ;\n",
|
||||
|
||||
""
|
||||
};
|
||||
super.testErrors(pair, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a regression test for antlr/antlr4#190
|
||||
* "NullPointerException building lexer grammar using bogus 'token' action"
|
||||
* https://github.com/antlr/antlr4/issues/190
|
||||
*/
|
||||
@Test public void testInvalidLexerCommand() {
|
||||
String[] pair = new String[] {
|
||||
"grammar A;\n" +
|
||||
"tokens{Foo}\n" +
|
||||
"b : Foo ;\n" +
|
||||
"X : 'foo' -> popmode;\n" + // "meant" to use -> popMode
|
||||
"Y : 'foo' -> token(Foo);", // "meant" to use -> type(Foo)
|
||||
|
||||
"error(" + ErrorType.INVALID_LEXER_COMMAND.code + "): A.g4:4:13: lexer command 'popmode' does not exist or is not supported by the current target\n" +
|
||||
"error(" + ErrorType.INVALID_LEXER_COMMAND.code + "): A.g4:5:13: lexer command 'token' does not exist or is not supported by the current target\n"
|
||||
};
|
||||
super.testErrors(pair, true);
|
||||
}
|
||||
|
||||
@Test public void testLexerCommandArgumentValidation() {
|
||||
String[] pair = new String[] {
|
||||
"grammar A;\n" +
|
||||
"tokens{Foo}\n" +
|
||||
"b : Foo ;\n" +
|
||||
"X : 'foo' -> popMode(Foo);\n" + // "meant" to use -> popMode
|
||||
"Y : 'foo' -> type;", // "meant" to use -> type(Foo)
|
||||
|
||||
"error(" + ErrorType.UNWANTED_LEXER_COMMAND_ARGUMENT.code + "): A.g4:4:13: lexer command 'popMode' does not take any arguments\n" +
|
||||
"error(" + ErrorType.MISSING_LEXER_COMMAND_ARGUMENT.code + "): A.g4:5:13: missing argument for lexer command 'type'\n"
|
||||
};
|
||||
super.testErrors(pair, true);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue