Fixed issue with duplicated commands in lexer rule.

This commit is contained in:
Ivan Kochurkin 2016-11-28 19:48:35 +03:00
parent a1def96500
commit bd1111ffa3
3 changed files with 47 additions and 3 deletions

View File

@ -247,4 +247,27 @@ public class TestSymbolIssues extends BaseJavaToolTest {
testErrors(test, false);
}
// https://github.com/antlr/antlr4/issues/1388
@Test public void testDuplicatedCommands() throws Exception {
String[] test = {
"lexer grammar Lexer;\n" +
"channels { CHANNEL1, CHANNEL2 }\n" +
"tokens { TEST1, TEST2 }\n" +
"TOKEN: 'aaaa' -> mode(MODE1), mode(MODE2);\n" +
"mode MODE1;\n" +
"MODE1_TOKEN: 'bbbb';\n" +
"mode MODE2;\n" +
"MODE2_TOKEN: 'bbbb';\n" +
"MODE2_TOKEN1: 'cccc' -> type(TEST1), type(TEST2);\n" +
"MODE2_TOKEN2: 'dddd' -> channel(CHANNEL1), channel(CHANNEL2), channel(DEFAULT_TOKEN_CHANNEL);",
"warning(" + ErrorType.DUPLICATED_COMMAND.code + "): Lexer.g4:4:30: duplicated command mode\n" +
"warning(" + ErrorType.DUPLICATED_COMMAND.code + "): Lexer.g4:9:37: duplicated command type\n" +
"warning(" + ErrorType.DUPLICATED_COMMAND.code + "): Lexer.g4:10:43: duplicated command channel\n" +
"warning(" + ErrorType.DUPLICATED_COMMAND.code + "): Lexer.g4:10:62: duplicated command channel\n"
};
testErrors(test, false);
}
}

View File

@ -95,6 +95,8 @@ public class LexerATNFactory extends ParserATNFactory {
COMMON_CONSTANTS.put("MIN_CHAR_VALUE", Lexer.MIN_CHAR_VALUE);
}
private List<String> ruleCommands = new ArrayList<String>();
/**
* Maps from an action index to a {@link LexerAction} object.
*/
@ -159,6 +161,12 @@ public class LexerATNFactory extends ParserATNFactory {
return atn;
}
@Override
public Handle rule(GrammarAST ruleAST, String name, Handle blk) {
ruleCommands.clear();
return super.rule(ruleAST, name, blk);
}
@Override
public Handle action(ActionAST action) {
int ruleIndex = currentRule.index;
@ -389,7 +397,7 @@ public class LexerATNFactory extends ParserATNFactory {
@Override
public Handle tokenRef(TerminalAST node) {
// Ref to EOF in lexer yields char transition on -1
if ( node.getText().equals("EOF") ) {
if (node.getText().equals("EOF") ) {
ATNState left = newState(node);
ATNState right = newState(node);
left.addTransition(new AtomTransition(right, IntStream.EOF));
@ -398,9 +406,14 @@ public class LexerATNFactory extends ParserATNFactory {
return _ruleRef(node);
}
protected LexerAction createLexerAction(GrammarAST ID, GrammarAST arg) {
private LexerAction createLexerAction(GrammarAST ID, GrammarAST arg) {
String command = ID.getText();
if (ruleCommands.contains(command)) {
g.tool.errMgr.grammarError(ErrorType.DUPLICATED_COMMAND, g.fileName, ID.getToken(), command);
}
ruleCommands.add(command);
if ("skip".equals(command) && arg == null) {
return LexerSkipAction.INSTANCE;
}

View File

@ -975,6 +975,14 @@ public enum ErrorType {
* <pre>C: 'test' '';</pre>
*/
EMPTY_STRINGS_NOT_ALLOWED(171, "string literals cannot be empty", ErrorSeverity.ERROR),
/*
* Compiler Warning 172.
*
* <p>lexer rule has a duplicated commands</p>
*
* <p>TOKEN: 'asdf' -> mode(MODE1), mode(MODE2);</p>
* */
DUPLICATED_COMMAND(172, "duplicated command <arg>", ErrorSeverity.WARNING),
/*
* Backward incompatibility errors