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 块,而不能为一个特定规则提供。
我正在使用 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 块,而不能为一个特定规则提供。