diff options
Diffstat (limited to 'tool/src/org/antlr')
12 files changed, 133 insertions, 18 deletions
diff --git a/tool/src/org/antlr/v4/automata/LexerATNFactory.java b/tool/src/org/antlr/v4/automata/LexerATNFactory.java index 4feff0a..a5e80e4 100644 --- a/tool/src/org/antlr/v4/automata/LexerATNFactory.java +++ b/tool/src/org/antlr/v4/automata/LexerATNFactory.java @@ -83,7 +83,7 @@ public class LexerATNFactory extends ParserATNFactory { * actions, but are required during code generation for creating * {@link LexerAction} instances that are usable by a lexer interpreter. */ - protected static final Map<String, Integer> COMMON_CONSTANTS = new HashMap<String, Integer>(); + public static final Map<String, Integer> COMMON_CONSTANTS = new HashMap<String, Integer>(); static { COMMON_CONSTANTS.put("HIDDEN", Lexer.HIDDEN); COMMON_CONSTANTS.put("DEFAULT_TOKEN_CHANNEL", Lexer.DEFAULT_TOKEN_CHANNEL); @@ -112,6 +112,10 @@ public class LexerATNFactory extends ParserATNFactory { codegenTemplates = gen.getTemplates(); } + public static Set<String> getCommonConstants() { + return COMMON_CONSTANTS.keySet(); + } + @Override public ATN createATN() { // BUILD ALL START STATES (ONE PER MODE) @@ -243,8 +247,8 @@ public class LexerATNFactory extends ParserATNFactory { // fall back to standard action generation for the command ST cmdST = codegenTemplates.getInstanceOf("Lexer" + - CharSupport.capitalize(ID.getText())+ - "Command"); + CharSupport.capitalize(ID.getText()) + + "Command"); if (cmdST == null) { g.tool.errMgr.grammarError(ErrorType.INVALID_LEXER_COMMAND, g.fileName, ID.token, ID.getText()); return epsilon(ID); @@ -407,6 +411,7 @@ public class LexerATNFactory extends ParserATNFactory { } else if ("mode".equals(command) && arg != null) { String modeName = arg.getText(); + checkMode(modeName, arg.token); Integer mode = getConstantValue(modeName, arg.getToken()); if (mode == null) { return null; @@ -416,6 +421,7 @@ public class LexerATNFactory extends ParserATNFactory { } else if ("pushMode".equals(command) && arg != null) { String modeName = arg.getText(); + checkMode(modeName, arg.token); Integer mode = getConstantValue(modeName, arg.getToken()); if (mode == null) { return null; @@ -425,6 +431,7 @@ public class LexerATNFactory extends ParserATNFactory { } else if ("type".equals(command) && arg != null) { String typeName = arg.getText(); + checkToken(typeName, arg.token); Integer type = getConstantValue(typeName, arg.getToken()); if (type == null) { return null; @@ -434,6 +441,7 @@ public class LexerATNFactory extends ParserATNFactory { } else if ("channel".equals(command) && arg != null) { String channelName = arg.getText(); + checkChannel(channelName, arg.token); Integer channel = getConstantValue(channelName, arg.getToken()); if (channel == null) { return null; @@ -446,6 +454,23 @@ public class LexerATNFactory extends ParserATNFactory { } } + protected void checkMode(String modeName, Token token) { + if (!modeName.equals("DEFAULT_MODE") && COMMON_CONSTANTS.containsKey(modeName)) { + g.tool.errMgr.grammarError(ErrorType.MODE_CONFLICTS_WITH_COMMON_CONSTANTS, g.fileName, token, token.getText()); + } + } + + protected void checkToken(String tokenName, Token token) { + if (!tokenName.equals("EOF") && COMMON_CONSTANTS.containsKey(tokenName)) { + g.tool.errMgr.grammarError(ErrorType.TOKEN_CONFLICTS_WITH_COMMON_CONSTANTS, g.fileName, token, token.getText()); + } + } + + protected void checkChannel(String channelName, Token token) { + if (!channelName.equals("HIDDEN") && !channelName.equals("DEFAULT_TOKEN_CHANNEL") && COMMON_CONSTANTS.containsKey(channelName)) { + g.tool.errMgr.grammarError(ErrorType.CHANNEL_CONFLICTS_WITH_COMMON_CONSTANTS, g.fileName, token, token.getText()); + } + } protected Integer getConstantValue(String name, Token token) { if (name == null) { diff --git a/tool/src/org/antlr/v4/codegen/ActionTranslator.java b/tool/src/org/antlr/v4/codegen/ActionTranslator.java index 2a12e8e..f1e5452 100644 --- a/tool/src/org/antlr/v4/codegen/ActionTranslator.java +++ b/tool/src/org/antlr/v4/codegen/ActionTranslator.java @@ -158,8 +158,10 @@ public class ActionTranslator implements ActionSplitterListener { translator.rf = rf; factory.getGrammar().tool.log("action-translator", "translate " + action); String altLabel = node.getAltLabel(); - if ( rf!=null ) translator.nodeContext = rf.ruleCtx; - if ( altLabel!=null ) translator.nodeContext = rf.altLabelCtxs.get(altLabel); + if ( rf!=null ) { + translator.nodeContext = rf.ruleCtx; + if ( altLabel!=null ) translator.nodeContext = rf.altLabelCtxs.get(altLabel); + } ANTLRStringStream in = new ANTLRStringStream(action); in.setLine(tokenWithinAction.getLine()); in.setCharPositionInLine(tokenWithinAction.getCharPositionInLine()); diff --git a/tool/src/org/antlr/v4/codegen/target/CSharpTarget.java b/tool/src/org/antlr/v4/codegen/target/CSharpTarget.java index 09df962..bfebe4b 100644 --- a/tool/src/org/antlr/v4/codegen/target/CSharpTarget.java +++ b/tool/src/org/antlr/v4/codegen/target/CSharpTarget.java @@ -51,7 +51,7 @@ public class CSharpTarget extends Target { @Override public String getVersion() { - return "4.5.1"; // crossing fingers that it's close enough. + return "4.5.2"; // crossing fingers that it's close enough. } @Override diff --git a/tool/src/org/antlr/v4/codegen/target/JavaScriptTarget.java b/tool/src/org/antlr/v4/codegen/target/JavaScriptTarget.java index 26fa4fe..71926ac 100644 --- a/tool/src/org/antlr/v4/codegen/target/JavaScriptTarget.java +++ b/tool/src/org/antlr/v4/codegen/target/JavaScriptTarget.java @@ -74,7 +74,7 @@ public class JavaScriptTarget extends Target { @Override public String getVersion() { - return "4.5.1"; + return "4.5.2"; } public Set<String> getBadWords() { diff --git a/tool/src/org/antlr/v4/codegen/target/Python2Target.java b/tool/src/org/antlr/v4/codegen/target/Python2Target.java index 36249d5..efa5d2c 100644 --- a/tool/src/org/antlr/v4/codegen/target/Python2Target.java +++ b/tool/src/org/antlr/v4/codegen/target/Python2Target.java @@ -117,7 +117,7 @@ public class Python2Target extends Target { @Override public String getVersion() { - return "4.5.2"; + return "4.5.2.1"; } public Set<String> getBadWords() { diff --git a/tool/src/org/antlr/v4/codegen/target/Python3Target.java b/tool/src/org/antlr/v4/codegen/target/Python3Target.java index d07247f..68d7a16 100644 --- a/tool/src/org/antlr/v4/codegen/target/Python3Target.java +++ b/tool/src/org/antlr/v4/codegen/target/Python3Target.java @@ -119,7 +119,7 @@ public class Python3Target extends Target { @Override public String getVersion() { - return "4.5.2"; + return "4.5.2.1"; } /** Avoid grammar symbols in this set to prevent conflicts in gen'd code. */ diff --git a/tool/src/org/antlr/v4/gui/TestRig.java b/tool/src/org/antlr/v4/gui/TestRig.java index 4812e5c..e81a54c 100644 --- a/tool/src/org/antlr/v4/gui/TestRig.java +++ b/tool/src/org/antlr/v4/gui/TestRig.java @@ -80,7 +80,7 @@ public class TestRig { public TestRig(String[] args) throws Exception { if ( args.length < 2 ) { - System.err.println("java org.antlr.v4.runtime.misc.TestRig GrammarName startRuleName\n" + + System.err.println("java org.antlr.v4.gui.TestRig GrammarName startRuleName\n" + " [-tokens] [-tree] [-gui] [-ps file.ps] [-encoding encodingname]\n" + " [-trace] [-diagnostics] [-SLL]\n"+ " [input-filename(s)]"); @@ -172,9 +172,6 @@ public class TestRig { if ( !startRuleName.equals(LEXER_START_RULE_NAME) ) { String parserName = grammarName+"Parser"; parserClass = cl.loadClass(parserName).asSubclass(Parser.class); - if ( parserClass==null ) { - System.err.println("Can't load "+parserName); - } Constructor<? extends Parser> parserCtor = parserClass.getConstructor(TokenStream.class); parser = parserCtor.newInstance((TokenStream)null); } diff --git a/tool/src/org/antlr/v4/gui/TreeViewer.java b/tool/src/org/antlr/v4/gui/TreeViewer.java index 0ca15f3..3cfd5e5 100644 --- a/tool/src/org/antlr/v4/gui/TreeViewer.java +++ b/tool/src/org/antlr/v4/gui/TreeViewer.java @@ -372,10 +372,12 @@ public class TreeViewer extends JComponent { JTree selectedTree = (JTree) e.getSource(); TreePath path = selectedTree.getSelectionPath(); - TreeNodeWrapper treeNode = (TreeNodeWrapper) path.getLastPathComponent(); + if (path!=null) { + TreeNodeWrapper treeNode = (TreeNodeWrapper) path.getLastPathComponent(); - // Set the clicked AST. - viewer.setTree((Tree) treeNode.getUserObject()); + // Set the clicked AST. + viewer.setTree((Tree) treeNode.getUserObject()); + } } }); diff --git a/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java b/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java index a578a66..4853c37 100644 --- a/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java +++ b/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java @@ -349,7 +349,7 @@ public class BasicSemanticChecks extends GrammarTreeVisitor { GrammarAST root = (GrammarAST)rulesNode.getParent(); GrammarAST IDNode = (GrammarAST)root.getChild(0); g.tool.errMgr.grammarError(ErrorType.NO_RULES, g.fileName, - null, IDNode.getText(), g); + null, IDNode.getText(), g); } } @@ -491,6 +491,14 @@ public class BasicSemanticChecks extends GrammarTreeVisitor { label.getText()); } + @Override + protected void enterTerminal(GrammarAST tree) { + String text = tree.getText(); + if (text.equals("''")) { + g.tool.errMgr.grammarError(ErrorType.EMPTY_STRINGS_NOT_ALLOWED, g.fileName, tree.token); + } + } + /** Check option is appropriate for grammar, rule, subrule */ boolean checkOptions(GrammarAST parent, Token optionID, diff --git a/tool/src/org/antlr/v4/semantics/SemanticPipeline.java b/tool/src/org/antlr/v4/semantics/SemanticPipeline.java index 3561f91..ada4324 100644 --- a/tool/src/org/antlr/v4/semantics/SemanticPipeline.java +++ b/tool/src/org/antlr/v4/semantics/SemanticPipeline.java @@ -31,6 +31,7 @@ package org.antlr.v4.semantics; import org.antlr.v4.analysis.LeftRecursiveRuleTransformer; +import org.antlr.v4.automata.LexerATNFactory; import org.antlr.v4.parse.ANTLRParser; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.misc.Pair; @@ -128,6 +129,8 @@ public class SemanticPipeline { collector.tokenIDRefs, collector.terminals); } + symcheck.checkForModeConflicts(g); + assignChannelTypes(g, collector.channelDefs); // CHECK RULE REFS NOW (that we've defined rules in grammar) @@ -287,6 +290,10 @@ public class SemanticPipeline { g.tool.errMgr.grammarError(ErrorType.CHANNEL_CONFLICTS_WITH_TOKEN, g.fileName, channel.token, channelName); } + if (LexerATNFactory.COMMON_CONSTANTS.containsKey(channelName)) { + g.tool.errMgr.grammarError(ErrorType.CHANNEL_CONFLICTS_WITH_COMMON_CONSTANTS, g.fileName, channel.token, channelName); + } + if (outermost instanceof LexerGrammar) { LexerGrammar lexerGrammar = (LexerGrammar)outermost; if (lexerGrammar.modes.containsKey(channelName)) { diff --git a/tool/src/org/antlr/v4/semantics/SymbolChecks.java b/tool/src/org/antlr/v4/semantics/SymbolChecks.java index b280f40..999d9f0 100644 --- a/tool/src/org/antlr/v4/semantics/SymbolChecks.java +++ b/tool/src/org/antlr/v4/semantics/SymbolChecks.java @@ -30,7 +30,9 @@ package org.antlr.v4.semantics; +import org.antlr.v4.automata.LexerATNFactory; import org.antlr.v4.parse.ANTLRParser; +import org.antlr.v4.runtime.Token; import org.antlr.v4.tool.Alternative; import org.antlr.v4.tool.Attribute; import org.antlr.v4.tool.AttributeDict; @@ -38,6 +40,7 @@ import org.antlr.v4.tool.ErrorManager; import org.antlr.v4.tool.ErrorType; import org.antlr.v4.tool.Grammar; import org.antlr.v4.tool.LabelElementPair; +import org.antlr.v4.tool.LexerGrammar; import org.antlr.v4.tool.Rule; import org.antlr.v4.tool.ast.GrammarAST; @@ -67,7 +70,7 @@ public class SymbolChecks { protected final Set<String> reservedNames = new HashSet<String>(); { - reservedNames.add("EOF"); + reservedNames.addAll(LexerATNFactory.getCommonConstants()); } public SymbolChecks(Grammar g, SymbolCollector collector) { @@ -269,6 +272,23 @@ public class SymbolChecks { } } + public void checkForModeConflicts(Grammar g) { + if (g.isLexer()) { + LexerGrammar lexerGrammar = (LexerGrammar)g; + for (String modeName : lexerGrammar.modes.keySet()) { + if (!modeName.equals("DEFAULT_MODE") && reservedNames.contains(modeName)) { + Rule rule = lexerGrammar.modes.get(modeName).iterator().next(); + g.tool.errMgr.grammarError(ErrorType.MODE_CONFLICTS_WITH_COMMON_CONSTANTS, g.fileName, rule.ast.parent.getToken(), modeName); + } + + if (g.getTokenType(modeName) != Token.INVALID_TYPE) { + Rule rule = lexerGrammar.modes.get(modeName).iterator().next(); + g.tool.errMgr.grammarError(ErrorType.MODE_CONFLICTS_WITH_TOKEN, g.fileName, rule.ast.parent.getToken(), modeName); + } + } + } + } + // CAN ONLY CALL THE TWO NEXT METHODS AFTER GRAMMAR HAS RULE DEFS (see semanticpipeline) public void checkRuleArgs(Grammar g, List<GrammarAST> rulerefs) { diff --git a/tool/src/org/antlr/v4/tool/ErrorType.java b/tool/src/org/antlr/v4/tool/ErrorType.java index 4868931..0fedfc4 100644 --- a/tool/src/org/antlr/v4/tool/ErrorType.java +++ b/tool/src/org/antlr/v4/tool/ErrorType.java @@ -957,6 +957,60 @@ public enum ErrorType { CHANNELS_BLOCK_IN_COMBINED_GRAMMAR(164, "custom channels are not supported in combined grammars", ErrorSeverity.ERROR), NONCONFORMING_LR_RULE(169, "rule <arg> is left recursive but doesn't conform to a pattern ANTLR can handle", ErrorSeverity.ERROR), + /** + * Compiler Error 170. + * + * <pre> + * mode M1; + * A1: 'a'; // ok + * mode M2; + * A2: 'a'; // ok + * M1: 'b'; // error 170 + * </pre> + * + * <p>mode <em>name</em> conflicts with token with same name</p> + */ + MODE_CONFLICTS_WITH_TOKEN(170, "mode <arg> conflicts with token with same name", ErrorSeverity.ERROR), + /** + * Compiler Error 171. + * + * <p>can not use or declare token with reserved name</p> + * + * <p>Reserved names: HIDDEN, DEFAULT_TOKEN_CHANNEL, SKIP, MORE, MAX_CHAR_VALUE, MIN_CHAR_VALUE. + * + * <p>Can be used but cannot be declared: EOF</p> + */ + TOKEN_CONFLICTS_WITH_COMMON_CONSTANTS(171, "cannot use or declare token with reserved name <arg>", ErrorSeverity.ERROR), + /** + * Compiler Error 172. + * + * <p>can not use or declare channel with reserved name</p> + * + * <p>Reserved names: DEFAULT_MODE, SKIP, MORE, EOF, MAX_CHAR_VALUE, MIN_CHAR_VALUE. + * + * <p>Can be used but cannot be declared: HIDDEN, DEFAULT_TOKEN_CHANNEL</p> + */ + CHANNEL_CONFLICTS_WITH_COMMON_CONSTANTS(172, "cannot use or declare channel with reserved name <arg>", ErrorSeverity.ERROR), + /** + * Compiler Error 173. + * + * <p>can not use or declare mode with reserved name</p> + * + * <p>Reserved names: HIDDEN, DEFAULT_TOKEN_CHANNEL, SKIP, MORE, MAX_CHAR_VALUE, MIN_CHAR_VALUE. + * + * <p>Can be used and cannot declared: DEFAULT_MODE</p> + */ + MODE_CONFLICTS_WITH_COMMON_CONSTANTS(173, "cannot use or declare mode with reserved name <arg>", ErrorSeverity.ERROR), + /** + * Compiler Error 174. + * + * <p>empty strings not allowed</p> + * + * <pre>A: '''test''';</pre> + * <pre>B: '';</pre> + * <pre>C: 'test' '';</pre> + */ + EMPTY_STRINGS_NOT_ALLOWED(174, "string literals cannot be empty", ErrorSeverity.ERROR), /* * Backward incompatibility errors |