为什么 ANTLR C# 自动生成的解析器不匹配 EOF?

Why is ANTLR C# autogenerated parser not matching EOF?

我有一个非常简单的语法,(我认为)应该只允许添加两个元素,例如 1+12+3

grammar dumbCalculator;
expression: simple_add EOF;
simple_add: INT ADD INT;

INT:('0'..'9');
ADD : '+';

我使用官方 ANTLR jar 文件生成我的 C# 类

java -jar "antlr-4.9-complete.jar" C:\Users\Me\source\repos\ConsoleApp2\ConsoleApp2\dumbCalculator.g4 -o C:\Users\Me\source\repos\ConsoleApp2\ConsoleApp2\Dumb -Dlanguage=CSharp -no-listener -visitor

无论我尝试什么,解析器都会继续添加尾随元素,尽管它们不应该被允许。

例如 "1+1+1" 被正确解析为 AST :

expression
    simple_add
        1
        +
        1
    +
    1

虽然我特意写了expression必须是simple_add然后EOFsimple_add就是INT ADD INT。我不知道为什么其余的被接受,我希望 ANTLR 对此抛出异常。

这就是我测试解析器的方式:

var inputStream = new AntlrInputStream("1+1+1");
var lexer = new dumbCalculatorLexer(inputStream);
lexer.RemoveErrorListeners();
lexer.AddErrorListener(new ThrowExceptionErrorListener());
var commonTokenStream = new CommonTokenStream(lexer);
var parser = new dumbCalculatorParser(commonTokenStream);
parser.RemoveErrorListeners();
parser.AddErrorListener(new ThrowExceptionErrorListener());
var ex = parser.expression();
ExploreAST(ex);

为什么其余的输出被接受?

经典场景,我在 Stack Overflow 上发帖 5 分钟后发现错误。

对于遇到类似情况的任何人,发生这种情况是因为我没有在我的解析器上明确设置 ErrorHandler

天真地,我希望所有 AddErrorListener 都能处理错误,但不知何故,如果您需要在访问树之前处理错误,则需要做一些特定的事情。

我需要添加

parser.ErrorHandler = new BailErrorStrategy();

在这之后,我确实得到了错误输入字符串的异常。

这可能不是正确的做法,我会让更了解 ANTLR 的人对此发表评论。