did REWRITE_ELEMENT_NOT_PRESENT_ON_LHS
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6678]
This commit is contained in:
parent
974c9556fd
commit
1cea245655
|
@ -166,12 +166,12 @@ ILLEGAL_OPTION(arg) ::=
|
|||
"illegal option <arg>"
|
||||
LIST_LABEL_INVALID_UNLESS_RETVAL_STRUCT(arg) ::=
|
||||
"rule '+=' list labels are not allowed w/o output option: <arg>"
|
||||
UNDEFINED_TOKEN_REF_IN_REWRITE(arg) ::=
|
||||
"reference to undefined token in rewrite rule: <arg>"
|
||||
REWRITE_ELEMENT_NOT_PRESENT_ON_LHS(arg) ::=
|
||||
"reference to rewrite element <arg> without reference on left of ->"
|
||||
UNDEFINED_LABEL_REF_IN_REWRITE(arg) ::=
|
||||
"reference to undefined label in rewrite rule: $<arg>"
|
||||
"reference to rewrite element <arg> not found to left of ->"
|
||||
//UNDEFINED_TOKEN_REF_IN_REWRITE(arg) ::=
|
||||
// "reference to undefined token in rewrite rule: <arg>"
|
||||
//UNDEFINED_LABEL_REF_IN_REWRITE(arg) ::=
|
||||
// "reference to undefined label in rewrite rule: $<arg>"
|
||||
NO_GRAMMAR_START_RULE (arg) ::=
|
||||
"grammar <arg>: no start rule (no rule can obviously be followed by EOF)"
|
||||
EMPTY_COMPLEMENT(arg) ::= <<
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ANTLRLexer.g 2010-02-07 13:10:26
|
||||
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ANTLRLexer.g 2010-02-07 17:00:03
|
||||
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
|
|
|
@ -819,7 +819,7 @@ options {backtrack=true;}
|
|||
// have output=AST; options. If that is the case, we will issue
|
||||
// errors/warnings in the next phase, so we just eat them here
|
||||
rewriteTreeAlt
|
||||
|
||||
|
||||
| ETC
|
||||
|
||||
| /* empty rewrite */ -> EPSILON
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ANTLRParser.g 2010-02-07 13:10:28
|
||||
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ANTLRParser.g 2010-02-07 17:00:06
|
||||
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
|
@ -284,7 +284,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: prequelConstruct, id, rules, grammarType, DOC_COMMENT
|
||||
// elements: prequelConstruct, DOC_COMMENT, id, grammarType, rules
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -1404,7 +1404,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: tokenSpec, TOKENS
|
||||
// elements: TOKENS, tokenSpec
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -1699,7 +1699,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: ACTION, SCOPE, id
|
||||
// elements: ACTION, id, SCOPE
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -1853,7 +1853,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: actionScopeName, id, AT, ACTION
|
||||
// elements: ACTION, actionScopeName, id, AT
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -2353,7 +2353,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: altListAsBlock, ruleReturns, exceptionGroup, id, rulePrequel, DOC_COMMENT, ARG_ACTION, ruleModifiers
|
||||
// elements: exceptionGroup, id, ruleReturns, ruleModifiers, altListAsBlock, rulePrequel, ARG_ACTION, DOC_COMMENT
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -3284,7 +3284,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: AT, id, ACTION
|
||||
// elements: ACTION, id, AT
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -3800,7 +3800,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: elements, rewrite
|
||||
// elements: rewrite, elements
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -4504,7 +4504,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: treeSpec, ebnfSuffix
|
||||
// elements: ebnfSuffix, treeSpec
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -5450,7 +5450,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: DOT, ruleref, id
|
||||
// elements: ruleref, DOT, id
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -5508,7 +5508,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: DOT, terminal, id
|
||||
// elements: terminal, DOT, id
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -5750,7 +5750,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: block, NOT
|
||||
// elements: NOT, block
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -6014,7 +6014,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: altList, ACTION, ra, optionsSpec
|
||||
// elements: ra, optionsSpec, ACTION, altList
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -6195,7 +6195,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: ARG_ACTION, RULE_REF, op
|
||||
// elements: RULE_REF, op, ARG_ACTION
|
||||
// token labels: op
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -6242,7 +6242,7 @@ public class ANTLRParser extends Parser {
|
|||
{
|
||||
|
||||
// AST REWRITE
|
||||
// elements: ARG_ACTION, RULE_REF
|
||||
// elements: RULE_REF, ARG_ACTION
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -6548,7 +6548,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: elementOptions, ARG_ACTION, TOKEN_REF
|
||||
// elements: ARG_ACTION, elementOptions, TOKEN_REF
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -6777,7 +6777,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: terminal, BANG
|
||||
// elements: BANG, terminal
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -7317,7 +7317,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: SEMPRED, SEMPRED, rewriteAlt, rewriteAlt
|
||||
// elements: SEMPRED, rewriteAlt, SEMPRED, rewriteAlt
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -8098,7 +8098,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: elementOptions, TOKEN_REF, ARG_ACTION
|
||||
// elements: elementOptions, ARG_ACTION, TOKEN_REF
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -8182,7 +8182,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: elementOptions, STRING_LITERAL
|
||||
// elements: STRING_LITERAL, elementOptions
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -8476,7 +8476,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: TREE_BEGIN, rewriteTreeElement, rewriteTreeAtom
|
||||
// elements: TREE_BEGIN, rewriteTreeAtom, rewriteTreeElement
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -8780,7 +8780,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: id, rewriteTemplateArgs
|
||||
// elements: rewriteTemplateArgs, id
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
@ -8892,7 +8892,7 @@ public class ANTLRParser extends Parser {
|
|||
|
||||
|
||||
// AST REWRITE
|
||||
// elements: ACTION, rewriteTemplateArgs
|
||||
// elements: rewriteTemplateArgs, ACTION
|
||||
// token labels:
|
||||
// rule labels: retval
|
||||
// token list labels:
|
||||
|
|
|
@ -126,7 +126,7 @@ prequelConstruct
|
|||
;
|
||||
|
||||
optionsSpec
|
||||
: ^(OPTIONS option+)
|
||||
: ^(OPTIONS option*)
|
||||
;
|
||||
|
||||
option
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ASTVerifier.g 2010-02-07 13:10:29
|
||||
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ASTVerifier.g 2010-02-07 17:00:06
|
||||
|
||||
/*
|
||||
[The "BSD license"]
|
||||
|
@ -391,51 +391,48 @@ public class ASTVerifier extends TreeParser {
|
|||
|
||||
|
||||
// $ANTLR start "optionsSpec"
|
||||
// ASTVerifier.g:128:1: optionsSpec : ^( OPTIONS ( option )+ ) ;
|
||||
// ASTVerifier.g:128:1: optionsSpec : ^( OPTIONS ( option )* ) ;
|
||||
public final void optionsSpec() throws RecognitionException {
|
||||
try {
|
||||
// ASTVerifier.g:129:2: ( ^( OPTIONS ( option )+ ) )
|
||||
// ASTVerifier.g:129:4: ^( OPTIONS ( option )+ )
|
||||
// ASTVerifier.g:129:2: ( ^( OPTIONS ( option )* ) )
|
||||
// ASTVerifier.g:129:4: ^( OPTIONS ( option )* )
|
||||
{
|
||||
match(input,OPTIONS,FOLLOW_OPTIONS_in_optionsSpec157);
|
||||
|
||||
match(input, Token.DOWN, null);
|
||||
// ASTVerifier.g:129:14: ( option )+
|
||||
int cnt4=0;
|
||||
loop4:
|
||||
do {
|
||||
int alt4=2;
|
||||
int LA4_0 = input.LA(1);
|
||||
if ( input.LA(1)==Token.DOWN ) {
|
||||
match(input, Token.DOWN, null);
|
||||
// ASTVerifier.g:129:14: ( option )*
|
||||
loop4:
|
||||
do {
|
||||
int alt4=2;
|
||||
int LA4_0 = input.LA(1);
|
||||
|
||||
if ( (LA4_0==ASSIGN) ) {
|
||||
alt4=1;
|
||||
}
|
||||
if ( (LA4_0==ASSIGN) ) {
|
||||
alt4=1;
|
||||
}
|
||||
|
||||
|
||||
switch (alt4) {
|
||||
case 1 :
|
||||
// ASTVerifier.g:129:14: option
|
||||
{
|
||||
pushFollow(FOLLOW_option_in_optionsSpec159);
|
||||
option();
|
||||
switch (alt4) {
|
||||
case 1 :
|
||||
// ASTVerifier.g:129:14: option
|
||||
{
|
||||
pushFollow(FOLLOW_option_in_optionsSpec159);
|
||||
option();
|
||||
|
||||
state._fsp--;
|
||||
state._fsp--;
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
if ( cnt4 >= 1 ) break loop4;
|
||||
EarlyExitException eee =
|
||||
new EarlyExitException(4, input);
|
||||
throw eee;
|
||||
}
|
||||
cnt4++;
|
||||
} while (true);
|
||||
default :
|
||||
break loop4;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
|
||||
match(input, Token.UP, null);
|
||||
match(input, Token.UP, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -4268,7 +4265,7 @@ public class ASTVerifier extends TreeParser {
|
|||
"\1\141\2\2\1\uffff\1\2\2\uffff\2\141\1\127\4\uffff\1\141\2\2\2\uffff"+
|
||||
"\2\141";
|
||||
static final String DFA31_acceptS =
|
||||
"\3\uffff\1\5\1\uffff\1\10\1\11\3\uffff\1\3\1\1\1\4\1\2\3\uffff\1"+
|
||||
"\3\uffff\1\5\1\uffff\1\10\1\11\3\uffff\1\1\1\3\1\4\1\2\3\uffff\1"+
|
||||
"\7\1\6\2\uffff";
|
||||
static final String DFA31_specialS =
|
||||
"\25\uffff}>";
|
||||
|
@ -4281,7 +4278,7 @@ public class ASTVerifier extends TreeParser {
|
|||
"\1\11",
|
||||
"",
|
||||
"",
|
||||
"\1\5\4\uffff\1\5\2\uffff\1\13\4\uffff\1\12\1\uffff\1\5\1\6"+
|
||||
"\1\5\4\uffff\1\5\2\uffff\1\12\4\uffff\1\13\1\uffff\1\5\1\6"+
|
||||
"\3\uffff\1\5\35\uffff\1\5",
|
||||
"\1\5\4\uffff\1\5\2\uffff\1\15\4\uffff\1\14\1\uffff\1\5\1\6"+
|
||||
"\3\uffff\1\5\35\uffff\1\5",
|
||||
|
|
|
@ -242,7 +242,7 @@ public class BasicSemanticChecks {
|
|||
ok = false;
|
||||
}
|
||||
}
|
||||
else if ( parent.getType()==ANTLRParser.COMBINED &&
|
||||
else if ( parent.getType()==ANTLRParser.GRAMMAR &&
|
||||
!legalGrammarOption(g.getType(), optionID.getText()) ) { // grammar
|
||||
ErrorManager.grammarError(ErrorType.ILLEGAL_OPTION,
|
||||
g.fileName,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 BasicSemanticTriggers.g 2010-02-07 16:55:18
|
||||
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 BasicSemanticTriggers.g 2010-02-08 17:03:10
|
||||
|
||||
/*
|
||||
[The "BSD license"]
|
||||
|
|
|
@ -72,17 +72,15 @@ import org.stringtemplate.v4.misc.MultiMap;
|
|||
|
||||
@members {
|
||||
Rule currentRule = null;
|
||||
int currentAlt = 1; // 1..n
|
||||
public List<Rule> rules = new ArrayList<Rule>();
|
||||
public List<GrammarAST> rulerefs = new ArrayList<GrammarAST>();
|
||||
public List<GrammarAST> terminals = new ArrayList<GrammarAST>();
|
||||
public List<GrammarAST> tokenIDRefs = new ArrayList<GrammarAST>();
|
||||
public List<GrammarAST> tokenNameRefsInRewrite = new ArrayList<GrammarAST>();
|
||||
public List<GrammarAST> strings = new ArrayList<GrammarAST>();
|
||||
public List<GrammarAST> tokensDefs = new ArrayList<GrammarAST>();
|
||||
public List<GrammarAST> scopes = new ArrayList<GrammarAST>();
|
||||
public List<GrammarAST> actions = new ArrayList<GrammarAST>();
|
||||
public MultiMap<String, LabelElementPair> ruleToLabelSpace =
|
||||
new MultiMap<String, LabelElementPair>();
|
||||
Grammar g; // which grammar are we checking
|
||||
public CollectSymbols(TreeNodeStream input, Grammar g) {
|
||||
this(input);
|
||||
|
@ -91,6 +89,7 @@ public CollectSymbols(TreeNodeStream input, Grammar g) {
|
|||
}
|
||||
|
||||
topdown
|
||||
//@init {System.out.println("topdown: "+((Tree)input.LT(1)).getText());}
|
||||
: globalScope
|
||||
| action
|
||||
| tokensSection
|
||||
|
@ -99,9 +98,11 @@ topdown
|
|||
| ruleReturns
|
||||
| ruleScopeSpec
|
||||
| ruleref
|
||||
| rewriteElement // make sure we check this before terminal etc...
|
||||
// want to match rewrite stuff all here
|
||||
| terminal
|
||||
| labeledElement
|
||||
| tokenRefInRewrite
|
||||
| setAlt
|
||||
;
|
||||
|
||||
bottomup
|
||||
|
@ -129,12 +130,19 @@ tokensSection
|
|||
|
||||
rule: ^( RULE name=ID .+)
|
||||
{
|
||||
Rule r = new Rule($name.text, (GrammarASTWithOptions)$RULE);
|
||||
int numAlts = $RULE.getFirstChildWithType(BLOCK).getChildCount();
|
||||
Rule r = new Rule($name.text, (GrammarASTWithOptions)$RULE, numAlts);
|
||||
rules.add(r);
|
||||
currentRule = r;
|
||||
currentAlt = 1;
|
||||
}
|
||||
;
|
||||
|
||||
setAlt
|
||||
: {inContext("RULE BLOCK")}? ( ALT | ALT_REWRITE )
|
||||
{currentAlt = $start.getChildIndex()+1;}
|
||||
;
|
||||
|
||||
finishRule
|
||||
: RULE {currentRule = null;}
|
||||
;
|
||||
|
@ -154,14 +162,18 @@ ruleScopeSpec
|
|||
)
|
||||
;
|
||||
|
||||
tokenRefInRewrite
|
||||
: {inContext("RESULT ...")}? TOKEN_REF {tokenNameRefsInRewrite.add($TOKEN_REF);}
|
||||
rewriteElement
|
||||
//@init {System.out.println("rewriteElement: "+((Tree)input.LT(1)).getText());}
|
||||
:
|
||||
{inContext("RESULT ...")}? (TOKEN_REF|RULE_REF|STRING_LITERAL|LABEL)
|
||||
{currentRule.alt[currentAlt].rewriteElements.add($start);}
|
||||
;
|
||||
|
||||
labeledElement
|
||||
@after {
|
||||
LabelElementPair lp = new LabelElementPair(g, $id, $e, $start.getType());
|
||||
ruleToLabelSpace.map(currentRule.name, lp);
|
||||
currentRule.labelDefs.map($id.text, lp);
|
||||
currentRule.alt[currentAlt].labelRefs.map($id.text, $id);
|
||||
}
|
||||
: {inContext("RULE ...")}?
|
||||
( ^(ASSIGN id=ID e=.)
|
||||
|
@ -170,11 +182,31 @@ ruleToLabelSpace.map(currentRule.name, lp);
|
|||
;
|
||||
|
||||
terminal
|
||||
: {!inContext("TOKENS ASSIGN")}? STRING_LITERAL {terminals.add($start);
|
||||
strings.add($STRING_LITERAL);}
|
||||
| TOKEN_REF {terminals.add($start); tokenIDRefs.add($TOKEN_REF);}
|
||||
: {!inContext("TOKENS ASSIGN")}? STRING_LITERAL
|
||||
{
|
||||
terminals.add($start);
|
||||
strings.add($STRING_LITERAL);
|
||||
if ( currentRule!=null ) {
|
||||
currentRule.alt[currentAlt].tokenRefs.map($STRING_LITERAL.text, $STRING_LITERAL);
|
||||
}
|
||||
}
|
||||
| TOKEN_REF
|
||||
{
|
||||
terminals.add($TOKEN_REF);
|
||||
tokenIDRefs.add($TOKEN_REF);
|
||||
if ( currentRule!=null ) {
|
||||
currentRule.alt[currentAlt].tokenRefs.map($TOKEN_REF.text, $TOKEN_REF);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
ruleref
|
||||
: ^(RULE_REF ARG_ACTION?) {rulerefs.add($RULE_REF);}
|
||||
//@init {System.out.println("ruleref: "+((Tree)input.LT(1)).getText());}
|
||||
: RULE_REF
|
||||
{
|
||||
rulerefs.add($RULE_REF);
|
||||
if ( currentRule!=null ) {
|
||||
currentRule.alt[currentAlt].ruleRefs.map($RULE_REF.text, $RULE_REF);
|
||||
}
|
||||
}
|
||||
;
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,6 @@ package org.antlr.v4.semantics;
|
|||
import org.antlr.runtime.Token;
|
||||
import org.antlr.v4.parse.ANTLRParser;
|
||||
import org.antlr.v4.tool.*;
|
||||
import org.stringtemplate.v4.misc.MultiMap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -43,8 +42,8 @@ public class SymbolChecks {
|
|||
checkTokenAliasRedefinitions(collector.tokensDefs);
|
||||
checkRuleArgs(collector.rulerefs);
|
||||
checkForTokenConflicts(collector.tokenIDRefs); // sets tokenIDs
|
||||
checkForLabelConflicts(collector.ruleToLabelSpace, collector.rules);
|
||||
checkTokenNameRefsInRewrite(collector.tokenNameRefsInRewrite);
|
||||
checkForLabelConflicts(collector.rules);
|
||||
checkRewriteElementsPresentOnLeftSide(collector.rules);
|
||||
}
|
||||
|
||||
public void checkForRuleConflicts(List<Rule> rules) {
|
||||
|
@ -170,41 +169,40 @@ public class SymbolChecks {
|
|||
/** Make sure a label doesn't conflict with another symbol.
|
||||
* Labels must not conflict with: rules, tokens, scope names,
|
||||
* return values, parameters, and rule-scope dynamic attributes
|
||||
* defined in surrounding rule.
|
||||
* defined in surrounding rule. Also they must have same type
|
||||
* for repeated defs.
|
||||
*/
|
||||
public void checkForLabelConflicts(MultiMap<String, LabelElementPair> ruleToLabelSpace,
|
||||
List<Rule> rules) {
|
||||
public void checkForLabelConflicts(List<Rule> rules) {
|
||||
for (Rule r : rules) {
|
||||
Map<String, LabelElementPair> labelNameSpace =
|
||||
new HashMap<String, LabelElementPair>();
|
||||
|
||||
List<LabelElementPair> pairs = ruleToLabelSpace.get(r.name);
|
||||
if ( pairs==null ) continue;
|
||||
|
||||
for (LabelElementPair labelPair : pairs) {
|
||||
checkForLabelConflict(r, labelPair.label);
|
||||
|
||||
String name = labelPair.label.getText();
|
||||
LabelElementPair prevLabelPair = labelNameSpace.get(name);
|
||||
if ( prevLabelPair==null ) {
|
||||
labelNameSpace.put(name, labelPair);
|
||||
}
|
||||
else {
|
||||
// label already defined; if same type, no problem
|
||||
if ( prevLabelPair.type != labelPair.type ) {
|
||||
String typeMismatchExpr = labelPair.type+"!="+prevLabelPair.type;
|
||||
ErrorManager.grammarError(
|
||||
ErrorType.LABEL_TYPE_CONFLICT,
|
||||
g.fileName,
|
||||
labelPair.label.token,
|
||||
name,
|
||||
typeMismatchExpr);
|
||||
}
|
||||
for (List<LabelElementPair> pairs : r.labelDefs.values() ) {
|
||||
for (LabelElementPair p : pairs) {
|
||||
checkForLabelConflict(r, p.label);
|
||||
String name = p.label.getText();
|
||||
LabelElementPair prev = labelNameSpace.get(name);
|
||||
if ( prev==null ) labelNameSpace.put(name, p);
|
||||
else checkForTypeMismatch(prev, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkForTypeMismatch(LabelElementPair prevLabelPair,
|
||||
LabelElementPair labelPair)
|
||||
{
|
||||
// label already defined; if same type, no problem
|
||||
if ( prevLabelPair.type != labelPair.type ) {
|
||||
String typeMismatchExpr = labelPair.type+"!="+prevLabelPair.type;
|
||||
ErrorManager.grammarError(
|
||||
ErrorType.LABEL_TYPE_CONFLICT,
|
||||
g.fileName,
|
||||
labelPair.label.token,
|
||||
labelPair.label.getText(),
|
||||
typeMismatchExpr);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkForLabelConflict(Rule r, GrammarAST labelID) {
|
||||
ErrorType etype = ErrorType.INVALID;
|
||||
Object arg2 = null;
|
||||
|
@ -234,10 +232,19 @@ public class SymbolChecks {
|
|||
}
|
||||
}
|
||||
|
||||
public void checkTokenNameRefsInRewrite(List<GrammarAST> tokenNameRefsInRewrite) {
|
||||
for (GrammarAST t : tokenNameRefsInRewrite) {
|
||||
ErrorManager.grammarError(ErrorType.UNDEFINED_TOKEN_REF_IN_REWRITE,
|
||||
g.fileName, t.token, t.getText());
|
||||
public void checkRewriteElementsPresentOnLeftSide(List<Rule> rules) {
|
||||
for (Rule r : rules) {
|
||||
for (int a=1; a<=r.numberOfAlts; a++) {
|
||||
Alternative alt = r.alt[a];
|
||||
for (GrammarAST e : alt.rewriteElements) {
|
||||
if ( !(alt.ruleRefs.containsKey(e.getText()) ||
|
||||
alt.tokenRefs.containsKey(e.getText()) ||
|
||||
alt.labelRefs.containsKey(e.getText())) ) {
|
||||
ErrorManager.grammarError(ErrorType.REWRITE_ELEMENT_NOT_PRESENT_ON_LHS,
|
||||
g.fileName, e.token, e.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package org.antlr.v4.tool;
|
||||
|
||||
|
||||
import org.stringtemplate.v4.misc.MultiMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Record use/def information about an outermost alternative in a subrule
|
||||
* or rule of a grammar.
|
||||
*/
|
||||
public class Alternative {
|
||||
// token IDs, string literals in this alt
|
||||
public MultiMap<String, GrammarAST> tokenRefs = new MultiMap<String, GrammarAST>();
|
||||
|
||||
// token IDs, string literals in this alt
|
||||
public MultiMap<String, GrammarAST> labelRefs = new MultiMap<String, GrammarAST>();
|
||||
|
||||
// all rule refs in this alt
|
||||
public MultiMap<String, GrammarAST> ruleRefs = new MultiMap<String, GrammarAST>();
|
||||
|
||||
// track all token, rule, label refs in rewrite (right of ->)
|
||||
public List<GrammarAST> rewriteElements = new ArrayList<GrammarAST>();
|
||||
|
||||
public Alternative() {
|
||||
}
|
||||
}
|
|
@ -98,9 +98,9 @@ public enum ErrorType {
|
|||
RULE_REF_AMBIG_WITH_RULE_IN_ALT(ErrorSeverity.ERROR, true, true),
|
||||
ILLEGAL_OPTION(ErrorSeverity.ERROR, true, true),
|
||||
LIST_LABEL_INVALID_UNLESS_RETVAL_STRUCT(ErrorSeverity.ERROR, true, true),
|
||||
UNDEFINED_TOKEN_REF_IN_REWRITE(ErrorSeverity.ERROR, true, true),
|
||||
REWRITE_ELEMENT_NOT_PRESENT_ON_LHS(ErrorSeverity.ERROR, true, true),
|
||||
UNDEFINED_LABEL_REF_IN_REWRITE(ErrorSeverity.ERROR, true, true),
|
||||
//UNDEFINED_TOKEN_REF_IN_REWRITE(ErrorSeverity.ERROR, true, true),
|
||||
///UNDEFINED_LABEL_REF_IN_REWRITE(ErrorSeverity.ERROR, true, true), use previous
|
||||
NO_GRAMMAR_START_RULE(ErrorSeverity.ERROR, true, true),
|
||||
EMPTY_COMPLEMENT(ErrorSeverity.ERROR, true, true),
|
||||
UNKNOWN_DYNAMIC_SCOPE(ErrorSeverity.ERROR, true, true),
|
||||
|
|
|
@ -1,22 +1,29 @@
|
|||
package org.antlr.v4.tool;
|
||||
|
||||
import java.util.Map;
|
||||
import org.stringtemplate.v4.misc.MultiMap;
|
||||
|
||||
public class Rule {
|
||||
public String name;
|
||||
public GrammarASTWithOptions ast;
|
||||
public GrammarAST arg;
|
||||
public GrammarAST ret;
|
||||
public int numberOfAlts;
|
||||
|
||||
/** All labels go in here (TODO: plus being split per the above lists) to
|
||||
* catch dup label and label type mismatches.
|
||||
/** Labels are visible to all alts in a rule. Record all defs here.
|
||||
* We need to ensure labels are used to track same kind of symbols.
|
||||
* Tracks all label defs for a label.
|
||||
*/
|
||||
public Map<String, LabelElementPair> labelNameSpace;
|
||||
//= new HashMap<String, LabelElementPair>();
|
||||
public MultiMap<String, LabelElementPair> labelDefs =
|
||||
new MultiMap<String, LabelElementPair>();
|
||||
|
||||
public Rule(String name, GrammarASTWithOptions ast) {
|
||||
public Alternative[] alt;
|
||||
|
||||
public Rule(String name, GrammarASTWithOptions ast, int numberOfAlts) {
|
||||
this.name = name;
|
||||
this.ast = ast;
|
||||
this.numberOfAlts = numberOfAlts;
|
||||
alt = new Alternative[numberOfAlts+1]; // 1..n
|
||||
for (int i=1; i<=numberOfAlts; i++) alt[i] = new Alternative();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -25,7 +32,7 @@ public class Rule {
|
|||
"name='" + name + '\'' +
|
||||
", arg=" + arg +
|
||||
", ret=" + ret +
|
||||
", labels=" + labelNameSpace +
|
||||
", labels=" + labelDefs +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,8 +48,6 @@ import java.util.*;
|
|||
|
||||
|
||||
public abstract class BaseTest {
|
||||
public static class InOutPair { String in, out; }
|
||||
|
||||
public static final String jikes = null;//"/usr/bin/jikes";
|
||||
public static final String pathSep = System.getProperty("path.separator");
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package org.antlr.v4.test;
|
|||
import org.junit.Test;
|
||||
|
||||
public class TestBasicSemanticErrors extends BaseTest {
|
||||
static String[] pairs = {
|
||||
static String[] A = {
|
||||
// INPUT
|
||||
"grammar A;\n" +
|
||||
"\n" +
|
||||
|
@ -13,7 +13,7 @@ public class TestBasicSemanticErrors extends BaseTest {
|
|||
"\n" +
|
||||
"a : ID<Foo> -> ID ;\n" +
|
||||
"\n" +
|
||||
"b : A^ | ((B!|C)) -> ICK;",
|
||||
"b : A^ | ((B!|C)) -> C;",
|
||||
// YIELDS
|
||||
"error(68): A.g:7:7: alts with rewrites can't use heterogeneous types left of ->\n" +
|
||||
"error(77): A.g:9:4: AST operator with non-AST output option: ^\n" +
|
||||
|
@ -34,8 +34,10 @@ public class TestBasicSemanticErrors extends BaseTest {
|
|||
// YIELDS
|
||||
"error(79): B.g:10:6: Wildcard invalid as root; wildcard can itself be a tree\n" +
|
||||
"error(80): B.g:1:5: option backtrack=false conflicts with tree grammar filter mode\n" +
|
||||
"error(80): B.g:1:5: option output=template conflicts with tree grammar filter mode",
|
||||
"error(80): B.g:1:5: option output=template conflicts with tree grammar filter mode"
|
||||
};
|
||||
|
||||
static String[] U = {
|
||||
// INPUT
|
||||
"parser grammar U;\n" +
|
||||
"options { foo=bar; k=*; backtrack=true;}\n" +
|
||||
|
@ -53,14 +55,14 @@ public class TestBasicSemanticErrors extends BaseTest {
|
|||
"b : ( options { ick=bar; greedy=true; } : ID )+ ;\n" +
|
||||
"c : ID<blue> ID<x=y> ;",
|
||||
// YIELDS
|
||||
"error(20): U.g:8:0: repeated grammar prequel spec (option, token, or import); please merge\n" +
|
||||
"error(20): U.g:7:0: repeated grammar prequel spec (option, token, or import); please merge\n" +
|
||||
"error(48): U.g:2:10: illegal option foo\n" +
|
||||
"error(26): U.g:4:8: token names must start with an uppercase letter: f\n" +
|
||||
"error(48): U.g:8:10: illegal option x\n" +
|
||||
"error(48): U.g:11:10: illegal option blech\n" +
|
||||
"error(48): U.g:14:16: illegal option ick\n" +
|
||||
"error(48): U.g:15:16: illegal option x",
|
||||
"error(21): U.g:8:0: repeated grammar prequel spec (option, token, or import); please merge\n" +
|
||||
"error(21): U.g:7:0: repeated grammar prequel spec (option, token, or import); please merge\n" +
|
||||
"error(49): U.g:2:10: illegal option foo\n" +
|
||||
"error(27): U.g:4:8: token names must start with an uppercase letter: f\n" +
|
||||
"error(49): U.g:8:10: illegal option x\n" +
|
||||
"error(49): U.g:11:10: illegal option blech\n" +
|
||||
"error(49): U.g:14:16: illegal option ick\n" +
|
||||
"error(49): U.g:15:16: illegal option x",
|
||||
|
||||
// INPUT
|
||||
"tree grammar V;\n" +
|
||||
|
@ -75,5 +77,6 @@ public class TestBasicSemanticErrors extends BaseTest {
|
|||
"error(66): V.g:7:4: with rewrite=true, alt 2 not simple node or obvious tree element; text attribute for rule not guaranteed to be correct",
|
||||
};
|
||||
|
||||
@Test public void testErrors() { super.testErrors(pairs); }
|
||||
@Test public void testA() { super.testErrors(A); }
|
||||
@Test public void testB() { super.testErrors(U); }
|
||||
}
|
|
@ -4,7 +4,7 @@ import org.junit.Test;
|
|||
|
||||
/** */
|
||||
public class TestSymbolIssues extends BaseTest {
|
||||
static String[] pairs = {
|
||||
static String[] A = {
|
||||
// INPUT
|
||||
"grammar A;\n" +
|
||||
"options { opt='sss'; k=3; }\n" +
|
||||
|
@ -24,17 +24,20 @@ public class TestSymbolIssues extends BaseTest {
|
|||
"\n" +
|
||||
"ID : 'a'..'z'+ ID ;",
|
||||
// YIELDS
|
||||
"error(61): A.g:11:6: scope Blort redefinition\n" +
|
||||
"error(49): A.g:2:10: illegal option opt\n" +
|
||||
"error(59): A.g:11:6: scope Blort redefinition\n" +
|
||||
"error(18): A.g:15:0: rule a redefinition\n" +
|
||||
"error(60): A.g:7:1: redefinition of members action\n" +
|
||||
"error(60): A.g:9:1: redefinition of header action\n" +
|
||||
"error(74): A.g:3:19: cannot alias X; token name already defined\n" +
|
||||
"error(74): A.g:3:26: cannot alias Y; token name already assigned to 'y'\n" +
|
||||
"error(74): A.g:3:36: cannot alias Z; token name already defined\n" +
|
||||
"error(58): A.g:7:1: redefinition of members action\n" +
|
||||
"error(58): A.g:9:1: redefinition of header action\n" +
|
||||
"error(72): A.g:3:19: cannot alias X; token name already defined\n" +
|
||||
"error(72): A.g:3:26: cannot alias Y; token name already assigned to 'y'\n" +
|
||||
"error(72): A.g:3:36: cannot alias Z; token name already defined\n" +
|
||||
"error(46): A.g:13:37: rule b has no defined parameters\n" +
|
||||
"error(24): A.g:13:43: reference to undefined rule: q\n" +
|
||||
"error(45): A.g:14:31: missing parameter(s) on rule reference: a",
|
||||
"error(45): A.g:14:31: missing parameter(s) on rule reference: a"
|
||||
};
|
||||
|
||||
static String[] B = {
|
||||
// INPUT
|
||||
"parser grammar B;\n" +
|
||||
"tokens { X='x'; Y; }\n" +
|
||||
|
@ -47,11 +50,30 @@ public class TestSymbolIssues extends BaseTest {
|
|||
"s : FOO ;",
|
||||
// YIELDS
|
||||
"error(34): B.g:9:0: symbol s conflicts with global dynamic scope with same name\n" +
|
||||
"error(34): B.g:5:4: symbol s conflicts with global dynamic scope with same name\n" +
|
||||
"error(35): B.g:5:9: label b conflicts with rule with same name\n" +
|
||||
"error(34): B.g:5:4: symbol s conflicts with global dynamic scope with same name\n" +
|
||||
"error(36): B.g:5:15: label X conflicts with token with same name\n" +
|
||||
"error(41): B.g:7:9: label x type mismatch with previous definition: TOKEN_LIST_LABEL!=TOKEN_LABEL"
|
||||
};
|
||||
|
||||
@Test public void testErrors() { super.testErrors(pairs); }
|
||||
static String[] C = {
|
||||
// INPUT
|
||||
"grammar C;\n"+
|
||||
"options {output=AST;}\n"+
|
||||
"a : A x=b y+=Z 'hi' -> ID A r $foo $x b $y+ 'hi' 'eh?'\n"+
|
||||
" | ID -> $x A ID // shouldn't see these refs from other alt ('cept ID)\n"+
|
||||
" ;\n"+
|
||||
"b : B ;\n"+
|
||||
"A : 'a';",
|
||||
// YIELDS
|
||||
"error(51): C.g:3:23: reference to rewrite element ID not found to left of ->\n" +
|
||||
"error(51): C.g:3:28: reference to rewrite element r not found to left of ->\n" +
|
||||
"error(51): C.g:3:30: reference to rewrite element foo not found to left of ->\n" +
|
||||
"error(51): C.g:3:49: reference to rewrite element 'eh?' not found to left of ->\n" +
|
||||
"error(51): C.g:4:10: reference to rewrite element x not found to left of ->\n" +
|
||||
"error(51): C.g:4:13: reference to rewrite element A not found to left of ->"
|
||||
};
|
||||
@Test public void testA() { super.testErrors(A); }
|
||||
@Test public void testB() { super.testErrors(B); }
|
||||
@Test public void testC() { super.testErrors(C); }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue