首页 > 解决方案 > 如何识别 ANTLR 中的额外输入错误?

问题描述

这是ANTLR中简单算术表达式的语法。我想获得一个简单算术表达式的解析树。

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

现在我输入(3+5)*4,ANTLR 正确生成了表达式的解析树。但是,如果我 input (3+5)4,这不是一个有效的输入,我也不会得到任何错误和解析树。从输出来看,似乎只有(3+5)被接受。

<code>(3+5)*4</code> 的解析树 <code>(3+5)4</code> 的解析树

我还注意到一些类似的情况,如果在输入中找到了一些匹配项,那么剩余的输入将被忽略。例如,我定义了一个语法:

relation_op : LESS_THAN | LEQ | GREATER_THAN | GEQ | EQUAL |
              DOUBLE_EQUAL | NEQ; 
              //Capital letters are predefined symbols(<,>,=...)

然后我输入<dskjkdsd,解析树<将正确显示,dskjkdsd忽略额外的错误输入。

在此处输入图像描述

那么这出了什么问题呢?

标签: expressionantlrgrammarantlr4

解决方案


默认情况下,规则会尽可能多地匹配输入,然后将其余部分留在令牌流中。因此,当您将输入(3+5)4提供给prog规则时,您会注意到4之后令牌仍将位于令牌流中。所以理论上你可以调用另一个规则然后使用它。

当您不想要这种行为时(您通常不希望从主代码调用的规则),您可以添加EOF到规则的末尾以表示它必须始终匹配到文件末尾并生成如果不能,则错误。

因此,当您将prog规则更改为:

prog: stat+ EOF ;

推荐阅读