我正在使用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块。