javascript : 如何在antlr生成的词法分析器中进行错误处理?

javascript : How to do Error Handling in Lexer generated by antlr?

我正在使用 antlr 编写 java 脚本语法分析器。 Antlr 为 lexer 中的每个标记创建一个方法。但它不包含 catch 块。我想将自定义 catch 块添加到词法分析器方法中。我已经为解析器方法添加了自定义的 catch 块,但无法通过语法文件为词法分析器方法添加它。

这是语法文件 -

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

词法分析器不同于解析器 -

  • 当解析器发现意外输入时,它符合某些规则并且知道下一个应该在输入上
  • 当词法分析器发现意外输入时,这意味着定义的词法分析器规则 none 匹配输入(即词法分析器对“意外”的定义 - 请记住那个词法分析器只关心匹配输入的下一个“单词”而不关心之前匹配的内容) - 因为问题是“none 的规则匹配这个”,它没有意义问“问题发生在哪个词法分析器规则中?”

并且因为您无法判断在哪个词法分析器规则中发生了意外输入,所以向它们添加 catch 块没有意义。


详细解释

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

  • org.antlr.runtime.Lexer.nextToken() 被调用 - 此方法将 运行 词法分析器使用 mTokens() 然后收集结果
  • mTokens() 词法分析器中的方法决定哪个标记规则是合适的,运行
    • 决定是在 mTokens() 中完成的(通常是通过 DFA - 有限自动化),而不是在词法分析器规则方法中
      • 如果没有词法分析器规则匹配当前输入,这将抛出 NoViableAlt 异常
  • 适当的词法分析器规则方法使用输入并为 nextToken() 设置适当的标志以用作词法分析器结果
    • 虽然此方法也可能抛出异常,但这通常不会发生,因为 mTokens() 中的决定应该已经选择了匹配规则

我的理解是,除非您在词法分析器规则中使用句法或语义谓词或自定义代码,否则词法分析器规则方法实际上永远不会抛出 RecognitionException - 发出这些的地方应该是决策块在 mTokens()。因此,向词法分析器规则方法添加一个 catch 块是没有意义的。


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