如何识别 ANTLR 中的额外输入错误?

How to recognize extra input error in 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 正确地生成了表达式的解析树。但是,如果我输入 (3+5)4,这不是有效输入,我也不会收到任何错误和解析树。从输出来看,似乎只接受了 (3+5)

我也注意到一些类似的情况,如果在输入中找到了一些匹配项,则剩余的输入将被忽略。比如我定义了一个文法:

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

然后我输入<dskjkdsd<的解析树会正确显示,多余的错误输入dskjkdsd会被忽略。

那么这里出了什么问题?

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

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

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

时,您会得到预期的错误
prog: stat+ EOF ;