我与antlr陷入了一个非常基本的层面。通过' The Definitive ANTLR 4 Reference'帕尔博士。在第4.2节中,“使用访问者构建计算器”#39;列出了以下语法:
grammar LabeledExpr; // rename to distinguish from Expr.g4
prog: stat+ ;
stat: expr NEWLINE # printExpr
| ID '=' expr NEWLINE # assign
| NEWLINE # blank
;
expr: expr op=('*'|'/') expr # MulDiv
| expr op=('+'|'-') expr # AddSub
| INT # int
| ID # id
| '(' expr ')' # parens
;
MUL : '*' ; // assigns token name to '*' used above in grammar
DIV : '/' ;
ADD : '+' ;
SUB : '-' ;
ID : [a-zA-Z]+ ; // match identifiers
INT : [0-9]+ ; // match integers
NEWLINE:'\r'? '\n' ; // return newlines to parser (is end-statement signal)
WS : [ \t]+ -> skip ; // toss out whitespace
我试图从上面的书中添加clear
语句:
在继续之前,您可能需要花一点时间尝试通过添加clear
语句来扩展此表达式语言。 clear
命令应清除memory
地图,您需要在规则stat
中使用新的替代方案来识别它。使用# clear
标记替代方案,然后在语法上运行ANTLR
以获取扩充的访问者界面。
这是我的尝试:
grammar LabeledExpr;
prog: stat+ ;
stat: expr NEWLINE # printExpr
| ID '=' expr NEWLINE # assign
| clear NEWLINE # clearMem
| NEWLINE # blank
;
expr: expr op=('*'|'/') expr # MulDiv
| expr op=('+'|'-') expr # AddSub
| INT # int
| ID # id
| '(' expr ')' # parens
;
clear: CLEAR
;
MUL: '*' ; // assigns token name to '*' used above in grammar
DIV: '/' ;
ADD: '+' ;
SUB: '-' ;
ID : [a-zA-Z]+ ;
INT : [0-9]+ ;
NEWLINE: '\r'?'\n' ;
WS : [ \t]+ -> skip ;
CLEAR: 'clear';
但是,visitClearMem
永远不会被调用:
@Override
public Integer visitClearMem(LabeledExprParser.ClearMemContext ctx) {
String text = ctx.getText();
if (text.equalsIgnoreCase("clear")) {
memory.clear();
}
return 0;
}
答案 0 :(得分:4)
问题是你的词法分析器中CLEAR
规则的位置。由于输入clear
与规则ID
和CLEAR
都匹配,因此ANTLR会选择在语法中首先出现的那个。在这种情况下,输入clear
变为ID
。
通常,您希望在其他标识符的规则之前放置您的语言的所有关键字,以确保它们正确匹配。
答案 1 :(得分:0)
正如Sam Harwell解释的那样,只需向上移动规则CLEAR:' clear&#39 ;;在ID规则之前,它可以工作,并对代码进行微小的修改
@Override
public Integer visitClearMem(LabeledExprParser.ClearMemContext ctx) {
String text = ctx.getText();
if (text.contains("clear")) {
memory.clear();
}
return 0;
}