forked from jasder/antlr
added check: action in lexer rules must be last element of outermost alt
This commit is contained in:
parent
5e519d0063
commit
e86f89724f
|
@ -3,6 +3,7 @@ ANTLR v4 Honey Badger
|
||||||
November 17, 2012
|
November 17, 2012
|
||||||
|
|
||||||
* .tokens files goes in output dir like parser file.
|
* .tokens files goes in output dir like parser file.
|
||||||
|
* added check: action in lexer rules must be last element of outermost alt
|
||||||
|
|
||||||
November 11, 2012
|
November 11, 2012
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
grammar T;
|
grammar T;
|
||||||
s : ~(ID|X)* X ;
|
s : A ;
|
||||||
b : ~(ID|X)*? X ;
|
|
||||||
A : 'a' ;
|
A : {} 'a' ;
|
||||||
B : 'b' ;
|
|
||||||
X : 'x' ;
|
B : ('x' {}|{}'y') {} ;
|
||||||
ID : 'id' ;
|
|
||||||
WS : [ \t\r\n]+ -> skip ;
|
WS : [ \t\r\n]+ -> skip ;
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
package org.antlr.v4.semantics;
|
package org.antlr.v4.semantics;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
import org.antlr.runtime.tree.CommonTree;
|
||||||
|
import org.antlr.runtime.tree.Tree;
|
||||||
import org.antlr.v4.misc.Utils;
|
import org.antlr.v4.misc.Utils;
|
||||||
import org.antlr.v4.parse.ANTLRParser;
|
import org.antlr.v4.parse.ANTLRParser;
|
||||||
import org.antlr.v4.parse.GrammarTreeVisitor;
|
import org.antlr.v4.parse.GrammarTreeVisitor;
|
||||||
|
@ -322,6 +324,28 @@ public class BasicSemanticChecks extends GrammarTreeVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enterLexerElement(GrammarAST tree) {
|
||||||
|
if ( tree.getType() == ACTION ) {
|
||||||
|
// Make sure that action is last element in outer alt; here action
|
||||||
|
// and a2 are bad, but a3 is ok.
|
||||||
|
// (RULE A (BLOCK (ALT {action} 'a')))
|
||||||
|
// (RULE B (BLOCK (ALT (BLOCK (ALT {a2} 'x') (ALT 'y')) {a3})))
|
||||||
|
CommonTree alt = tree.parent;
|
||||||
|
CommonTree blk = alt.parent;
|
||||||
|
boolean outerMostAlt = blk.parent.getType() != RULE;
|
||||||
|
Tree rule = tree.getAncestor(RULE);
|
||||||
|
String fileName = tree.getToken().getInputStream().getSourceName();
|
||||||
|
if ( !outerMostAlt || tree.getChildIndex() != alt.getChildCount()-1 ) {
|
||||||
|
g.tool.errMgr.grammarError(ErrorType.LEXER_ACTION_PLACEMENT_ISSUE,
|
||||||
|
fileName,
|
||||||
|
tree.getToken(),
|
||||||
|
rule.getChild(0).getText());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void label(GrammarAST op, GrammarAST ID, GrammarAST element) {
|
public void label(GrammarAST op, GrammarAST ID, GrammarAST element) {
|
||||||
switch (element.getType()) {
|
switch (element.getType()) {
|
||||||
|
|
|
@ -153,6 +153,7 @@ public enum ErrorType {
|
||||||
// WILDCARD_IN_PARSER(129, "wildcard '.' not allowed in parsers", ErrorSeverity.ERROR),
|
// WILDCARD_IN_PARSER(129, "wildcard '.' not allowed in parsers", ErrorSeverity.ERROR),
|
||||||
LABEL_BLOCK_NOT_A_SET(130, "label <arg> assigned to a block which is not a set", ErrorSeverity.ERROR),
|
LABEL_BLOCK_NOT_A_SET(130, "label <arg> assigned to a block which is not a set", ErrorSeverity.ERROR),
|
||||||
EXPECTED_NON_GREEDY_WILDCARD_BLOCK(131, "greedy block ()<arg> contains wildcard; the non-greedy syntax ()<arg>? may be preferred", ErrorSeverity.WARNING),
|
EXPECTED_NON_GREEDY_WILDCARD_BLOCK(131, "greedy block ()<arg> contains wildcard; the non-greedy syntax ()<arg>? may be preferred", ErrorSeverity.WARNING),
|
||||||
|
LEXER_ACTION_PLACEMENT_ISSUE(132, "action in lexer rule <arg> must be last element of outermost alt", ErrorSeverity.ERROR),
|
||||||
|
|
||||||
/** Documentation comment is unterminated */
|
/** Documentation comment is unterminated */
|
||||||
//UNTERMINATED_DOC_COMMENT(, "", ErrorSeverity.ERROR),
|
//UNTERMINATED_DOC_COMMENT(, "", ErrorSeverity.ERROR),
|
||||||
|
|
Loading…
Reference in New Issue