ANTLR4书,计算器练习

时间:2014-03-13 17:45:37

标签: antlr antlr4

我与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;
}

2 个答案:

答案 0 :(得分:4)

问题是你的词法分析器中CLEAR规则的位置。由于输入clear与规则IDCLEAR都匹配,因此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;
}