add check for command placement in lexer rules

This commit is contained in:
Terence Parr 2012-11-17 17:03:29 -08:00
parent 9d34d4d3c9
commit 8631c143da
3 changed files with 31 additions and 22 deletions

View File

@ -3,8 +3,6 @@ s : A ;
A : 'a' ;
B : ('x' -> skip |'y') ;
C : 'd' {} | 'e' {} ;
B : 'x' -> skip |'y' ;
WS : [ \t\r\n]+ -> skip ;

View File

@ -327,25 +327,36 @@ 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,
// a2, z, and zz are bad, but a3 is ok:
// (RULE A (BLOCK (ALT {action} 'a')))
// (RULE B (BLOCK (ALT (BLOCK (ALT {a2} 'x') (ALT 'y')) {a3})))
// (RULE C (BLOCK (ALT 'd' {z}) (ALT 'e' {zz})))
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 ||
blk.getChildCount()>1 )
{
g.tool.errMgr.grammarError(ErrorType.LEXER_ACTION_PLACEMENT_ISSUE,
fileName,
tree.getToken(),
rule.getChild(0).getText());
checkElementIsOuterMostInSingleAlt(tree);
}
}
@Override
protected void enterLexerCommand(GrammarAST tree) {
checkElementIsOuterMostInSingleAlt(tree);
}
/**
Make sure that action is last element in outer alt; here action,
a2, z, and zz are bad, but a3 is ok:
(RULE A (BLOCK (ALT {action} 'a')))
(RULE B (BLOCK (ALT (BLOCK (ALT {a2} 'x') (ALT 'y')) {a3})))
(RULE C (BLOCK (ALT 'd' {z}) (ALT 'e' {zz})))
*/
protected void checkElementIsOuterMostInSingleAlt(GrammarAST tree) {
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 ||
blk.getChildCount()>1 )
{
g.tool.errMgr.grammarError(ErrorType.LEXER_ACTION_PLACEMENT_ISSUE,
fileName,
tree.getToken(),
rule.getChild(0).getText());
}
}
}

View File

@ -153,7 +153,7 @@ public enum ErrorType {
// 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),
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 single outermost alt", ErrorSeverity.ERROR),
LEXER_ACTION_PLACEMENT_ISSUE(132, "action or ->command in lexer rule <arg> must be last element of single outermost alt", ErrorSeverity.ERROR),
/** Documentation comment is unterminated */
//UNTERMINATED_DOC_COMMENT(, "", ErrorSeverity.ERROR),