diff --git a/tool/src/org/antlr/v4/Tool.java b/tool/src/org/antlr/v4/Tool.java index e39b22d1c..52f7d7b19 100644 --- a/tool/src/org/antlr/v4/Tool.java +++ b/tool/src/org/antlr/v4/Tool.java @@ -433,10 +433,16 @@ public class Tool { public boolean checkForRuleIssues(final Grammar g) { // check for redefined rules GrammarAST RULES = (GrammarAST)g.ast.getFirstChildWithType(ANTLRParser.RULES); - List rules = (List)RULES.getChildren(); + + List rules = (List)RULES.getChildren(); + if (rules == null) { + rules = Collections.emptyList(); + } + final Map ruleToAST = new HashMap(); - for (RuleAST r : rules) { - GrammarAST ID = (GrammarAST)r.getChild(0); + for (Object r : rules) { + RuleAST ruleAST = (RuleAST)r; + GrammarAST ID = (GrammarAST)ruleAST.getChild(0); String ruleName = ID.getText(); RuleAST prev = ruleToAST.get(ruleName); if ( prev !=null ) { @@ -446,10 +452,10 @@ public class Tool { ID.getToken(), ruleName, prevChild.getToken().getLine()); - r.dead = true; + ruleAST.dead = true; continue; } - ruleToAST.put(ruleName, r); + ruleToAST.put(ruleName, ruleAST); } // check for undefined rules @@ -457,6 +463,11 @@ public class Tool { public boolean undefined = false; @Override public void tokenRef(TerminalAST ref) { + if ("EOF".equals(ref.getText())) { + // this is a special predefined reference + return; + } + if ( g.isLexer() ) ruleRef(ref, null); } diff --git a/tool/src/org/antlr/v4/parse/ANTLRLexer.g b/tool/src/org/antlr/v4/parse/ANTLRLexer.g index 6e01ae71f..446d5aac6 100644 --- a/tool/src/org/antlr/v4/parse/ANTLRLexer.g +++ b/tool/src/org/antlr/v4/parse/ANTLRLexer.g @@ -298,15 +298,16 @@ ARG_ACTION // ACTION : NESTED_ACTION - ('?' {$type = SEMPRED;} )? - ( '=>' // v3 gated sempred - { - Token t = new CommonToken(input, state.type, state.channel, state.tokenStartCharIndex, getCharIndex()-1); - t.setLine(state.tokenStartLine); - t.setText(state.text); - t.setCharPositionInLine(state.tokenStartCharPositionInLine); - grammarError(ErrorType.V3_GATED_SEMPRED, t); - } + ( '?' {$type = SEMPRED;} + ( (WSNLCHARS* '=>') => WSNLCHARS* '=>' // v3 gated sempred + { + Token t = new CommonToken(input, state.type, state.channel, state.tokenStartCharIndex, getCharIndex()-1); + t.setLine(state.tokenStartLine); + t.setText(state.text); + t.setCharPositionInLine(state.tokenStartCharPositionInLine); + grammarError(ErrorType.V3_GATED_SEMPRED, t); + } + )? )? ; diff --git a/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java b/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java index f4793a63b..0ef42fcd8 100644 --- a/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java +++ b/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java @@ -347,8 +347,7 @@ public class BasicSemanticChecks extends GrammarTreeVisitor { boolean outerMostAlt = blk.parent.getType() == RULE; Tree rule = tree.getAncestor(RULE); String fileName = tree.getToken().getInputStream().getSourceName(); - if ( !outerMostAlt || tree.getChildIndex() != alt.getChildCount()-1 || - blk.getChildCount()>1 ) + if ( !outerMostAlt || blk.getChildCount()>1 ) { ErrorType e = ErrorType.LEXER_COMMAND_PLACEMENT_ISSUE; if ( tree.getType() == ACTION ) e = ErrorType.LEXER_ACTION_PLACEMENT_ISSUE; diff --git a/tool/src/org/antlr/v4/semantics/SemanticPipeline.java b/tool/src/org/antlr/v4/semantics/SemanticPipeline.java index da87b3b64..550b33a4c 100644 --- a/tool/src/org/antlr/v4/semantics/SemanticPipeline.java +++ b/tool/src/org/antlr/v4/semantics/SemanticPipeline.java @@ -151,7 +151,7 @@ public class SemanticPipeline { void assignLexerTokenTypes(Grammar g, List tokensDefs) { Grammar G = g.getOutermostGrammar(); // put in root, even if imported for (GrammarAST def : tokensDefs) { - if ( def.getType()== ANTLRParser.ID ) G.defineTokenName(def.getText()); + if ( def.getType()== ANTLRParser.TOKEN_REF ) G.defineTokenName(def.getText()); } /* Define token types for nonfragment rules which do not include a 'type(...)'