forked from jasder/antlr
report errors with too few alt labels or redef of alt label
This commit is contained in:
parent
646b22b9ec
commit
100b530201
|
@ -8,5 +8,11 @@ e : e '*' e -> Mult
|
|||
| '(' e ')' -> Parens
|
||||
;
|
||||
|
||||
x : A -> Foo
|
||||
| B
|
||||
;
|
||||
|
||||
y : Y -> Mult ;
|
||||
|
||||
INT : [0-9]+ ;
|
||||
WS : [ \t\n]+ -> skip ;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import org.antlr.v4.runtime.tree.*;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
|
||||
|
||||
public class ABaseVisitor<T> extends ParseTreeVisitor<T> implements AVisitor<T> {
|
||||
public T visit(AParser.MultContext ctx) { visitChildren(ctx); return null; }
|
||||
public T visit(AParser.ParensContext ctx) { visitChildren(ctx); return null; }
|
||||
public T visit(AParser.sContext ctx) { visitChildren(ctx); return null; }
|
||||
public T visit(AParser.FooContext ctx) { visitChildren(ctx); return null; }
|
||||
public T visit(AParser.AddContext ctx) { visitChildren(ctx); return null; }
|
||||
public T visit(AParser.IntContext ctx) { visitChildren(ctx); return null; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import org.antlr.v4.runtime.tree.*;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
public interface AVisitor<T> {
|
||||
T visit(AParser.MultContext ctx);
|
||||
T visit(AParser.ParensContext ctx);
|
||||
T visit(AParser.sContext ctx);
|
||||
T visit(AParser.FooContext ctx);
|
||||
T visit(AParser.AddContext ctx);
|
||||
T visit(AParser.IntContext ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,10 +40,7 @@ import org.antlr.v4.tool.ast.*;
|
|||
import org.stringtemplate.v4.misc.MultiMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/** No side-effects except for setting options into the appropriate node.
|
||||
* TODO: make the side effects into a separate pass this
|
||||
|
@ -242,6 +239,44 @@ public class BasicSemanticChecks extends GrammarTreeVisitor {
|
|||
// }
|
||||
}
|
||||
|
||||
Map<String,String> altLabelToRuleName = new HashMap<String, String>();
|
||||
|
||||
@Override
|
||||
public void finishRule(RuleAST rule, GrammarAST ID, GrammarAST block) {
|
||||
MultiMap<String,GrammarAST> ruleToAltLabels = new MultiMap<String, GrammarAST>();
|
||||
if ( rule.isLexerRule() ) return;
|
||||
BlockAST blk = (BlockAST)rule.getFirstChildWithType(BLOCK);
|
||||
int nalts = blk.getChildCount();
|
||||
for (int i=0; i< nalts; i++) {
|
||||
AltAST altAST = (AltAST)blk.getChild(i);
|
||||
if ( altAST.altLabel!=null ) {
|
||||
System.out.println("alt label "+altAST.altLabel);
|
||||
ruleToAltLabels.map(rule.getRuleName(), altAST.altLabel);
|
||||
String altLabel = altAST.altLabel.getText();
|
||||
String prevRuleForLabel = altLabelToRuleName.get(altLabel);
|
||||
if ( prevRuleForLabel!=null ) {
|
||||
g.tool.errMgr.grammarError(ErrorType.ALT_LABEL_REDEF,
|
||||
g.fileName, rule.getToken(),
|
||||
altLabel,
|
||||
rule.getRuleName(),
|
||||
prevRuleForLabel);
|
||||
}
|
||||
else {
|
||||
altLabelToRuleName.put(altLabel, rule.getRuleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println(rule.getRuleName()+" has "+ nalts +" alts");
|
||||
List<GrammarAST> altLabels = ruleToAltLabels.get(rule.getRuleName());
|
||||
int numAltLabels = 0;
|
||||
if ( altLabels!=null ) numAltLabels = altLabels.size();
|
||||
System.out.println("labels="+altLabels);
|
||||
if ( numAltLabels>0 && nalts != numAltLabels ) {
|
||||
g.tool.errMgr.grammarError(ErrorType.RULE_WITH_TOO_FEW_ALT_LABELS,
|
||||
g.fileName, rule.getToken(), rule.getRuleName());
|
||||
}
|
||||
}
|
||||
|
||||
// Routines to do the actual work of checking issues with a grammar.
|
||||
// They are triggered by the visitor methods above.
|
||||
|
||||
|
|
|
@ -139,7 +139,9 @@ public enum ErrorType {
|
|||
ALL_OPS_NEED_SAME_ASSOC(118, "all operators of alt <arg> of left-recursive rule must have same associativity", ErrorSeverity.WARNING),
|
||||
LEFT_RECURSION_CYCLES(119, "The following sets of rules are mutually left-recursive <arg:{c| [<c:{r|<r.name>}; separator=\", \">]}; separator=\" and \">", ErrorSeverity.ERROR),
|
||||
MODE_NOT_IN_LEXER(120, "lexical modes are only allowed in lexer grammars", ErrorSeverity.ERROR),
|
||||
CANNOT_FIND_ATTRIBUTE_NAME_IN_DECL(121, "cannot find an attribute name in attribute declaration", ErrorSeverity.ERROR),
|
||||
CANNOT_FIND_ATTRIBUTE_NAME_IN_DECL(121, "cannot find an attribute name in attribute declaration", ErrorSeverity.ERROR),
|
||||
RULE_WITH_TOO_FEW_ALT_LABELS(122, "rule <arg>: must label all alternatives or none", ErrorSeverity.ERROR),
|
||||
ALT_LABEL_REDEF(123, "rule alt label <arg> redefined in rule <arg2>, originally in <arg3>", ErrorSeverity.ERROR),
|
||||
/** Documentation comment is unterminated */
|
||||
//UNTERMINATED_DOC_COMMENT(, "", ErrorSeverity.ERROR),
|
||||
|
||||
|
|
|
@ -34,8 +34,6 @@ import org.antlr.runtime.tree.Tree;
|
|||
import org.antlr.v4.parse.ANTLRParser;
|
||||
|
||||
public class RuleAST extends GrammarASTWithOptions {
|
||||
|
||||
|
||||
public RuleAST(GrammarAST node) {
|
||||
super(node);
|
||||
}
|
||||
|
@ -43,6 +41,17 @@ public class RuleAST extends GrammarASTWithOptions {
|
|||
public RuleAST(Token t) { super(t); }
|
||||
public RuleAST(int type) { super(type); }
|
||||
|
||||
public boolean isLexerRule() {
|
||||
String name = getRuleName();
|
||||
return name!=null && Character.isUpperCase(name.charAt(0));
|
||||
}
|
||||
|
||||
public String getRuleName() {
|
||||
GrammarAST nameNode = (GrammarAST)getChild(0);
|
||||
if ( nameNode!=null ) return nameNode.getText();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tree dupNode() { return new RuleAST(this); }
|
||||
|
||||
|
|
Loading…
Reference in New Issue