我正在使用antlr编写Java脚本语法解析器。 Antlr为lexer中的每个令牌创建一个方法。但是它不包含catch块。我想向lexer方法添加自定义catch块。我为解析器方法添加了自定义的catch块,但无法通过语法文件为lexer方法添加它。

这是语法文件-

grammar test;

options {
 language=JavaScript;
 output=AST;
}
@lexer::members {
  function reportError(e) {
    throw e;
  }
}
SALUTATION:'Hello world';
ENDSYMBOL:'!';
expression : SALUTATION ENDSYMBOL;
catch [e] {
  throw e;
}


并在此处完成演示-Plunker

最佳答案

TL; DR

Lexer与解析器不同-


当解析器发现意外的输入时,这是某种规则,并且知道下一个应该在输入中
当词法分析器发现意外的输入时,这意味着没有一个已定义的词法分析器规则与输入匹配(即词法分析器对“意外”的定义-请记住,词法分析器仅关心匹配输入中的下一个“单词”,而不关心-既然问题是“没有一个规则与此匹配”,那么问“问题是在哪个词法分析器规则中发生的?”是没有意义的。


而且,由于您无法确定在哪个lexer规则中发生了意外输入,因此没有必要向其添加catch块。



详细说明

在lexer规则的方法中添加catch块没有多大意义。原因是词法分析器方法与解析器方法的使用方式不同-这是当解析器查询下一个标记时发生的情况:


调用org.antlr.runtime.Lexer.nextToken()-此方法将使用mTokens()运行词法分析器,然后收集结果
词法分析器中的mTokens()方法决定哪种令牌规则合适并运行


该决定是在mTokens()中完成的(通常是通过DFA-有限自动执行),而不是在词法分析器规则方法中


如果没有词法分析器规则与当前输入匹配,将抛出NoViableAlt异常


适当的词法分析器规则方法使用输入并为nextToken()设置适当的标志以用作词法分析器结果


尽管此方法也可能引发异常,但是通常不会发生这种情况,因为mTokens()中的决定应该已经选择了匹配的规则



我的理解是,除非在词法分析器规则中使用句法或语义谓词或自定义代码,否则词法分析器规则方法切勿实际抛出RecognitionException-发出这些词的位置应为mTokens()中的决策块。因此,向lexer规则方法添加catch块没有任何意义。



mTokens()在决策部分周围没有try块,因此除非修改代码生成模板,否则无法使用自定义catch块。您可以尝试使用具有自定义异常处理功能的自己的方法来覆盖org.antlr.runtime.Lexer.nextToken(),但是在那里您将只能为所有词法分析器规则提供一个catch块,而不能为一个特定规则提供一个catch块。

10-07 14:23
查看更多