如何解决Antlr 解析器表现得很奇怪
我的 anltr 配置的解析器有这种奇怪的行为。 到目前为止,这是按预期工作的,但现在我们发现了 antlr 崩溃时的一些其他情况。
这是词法分析器:
lexer grammar RuleLexer;
WORD: (DIGIT | LOWERCASE | UPPERCASE)+;
ANY_SPACE: (SINGLE_SPACE | NEW_LINE)+;
WS: [\r\t]+ -> skip;
CONDITION_OPEN: '<';
CONDITION_CLOSE: '>';
AND: '&';
OR: '/';
fragment LOWERCASE: [a-z];
fragment UPPERCASE: [A-Z];
fragment DIGIT: [0-9];
fragment SINGLE_SPACE: ' ';
fragment NEW_LINE: [\n];
这里是解析器:
parser grammar RuleParser;
options {
tokenVocab = RuleLexer;
language = Java;
}
rules: term+ EOF;
term:
constraint EOF # statement
| fi = constraint CONDITION_OPEN then = constraint CONDITION_CLOSE # conditional;
constraint:
ANY_SPACE? (element) ANY_SPACE? (
operation constraint
)?;
operation: AND | OR;
element: WORD;
以下是结果的一些输入和图片: 001/002/003 -> 工作正常: 001/002/003
但现在奇怪的部分来了。如果我在输入的末尾添加另一个运算符 / 或 & 001/002/003/ -> 不起作用。 001/002/003/
如果我有一个条件作为输入,解析器会按需要工作。它验证输入并识别额外的操作: 001/ -> 正在工作 001<002/003>/ 我希望第二个输入像第三个一样被解释。
我发现的最后一个问题是我错过了约束之间的操作。 001/002 003/004 001/002 003/004
我想知道为什么在不工作的情况下我会得到带有 EOF 和 null 的结果。 我希望图片分辨率足够好。
解决方法
使用 constraint EOF # statement
替代方案,您只匹配一个约束IF,它是整个输入流中的唯一内容。
您同等对待 Spaces 和 newLines,那么您是否打算在输入流中允许多个约束条件?如果是这样,您需要删除该规则替代项上的 EOF
。
由于您已将 /
定义为 OR 运算符,该运算符仅在后跟另一个约束时可用,因此它在输入的末尾无效。因此,您会收到 no viable alternative
错误消息。您似乎更愿意得到 extraneous input '/' expecting ...
错误。
您通过 EOF
替代项上的 statement
获得该消息(对于 some 输入),因为 ANTLR 能够使用它的一些错误恢复策略。 extraneous input
错误是 ANTLR 试图为更优雅的错误恢复而做的事情(有点像“嗯...我可以理解 如果我忽略了这个标记)。但是,ANTLR并不总是能够尝试这些错误恢复。(我认为我知道他们什么时候会触发什么时候不会触发,但是不能修改这个语法来利用我 >认为它奏效了。我敢肯定,某些错误恢复策略是否适用涉及到相当复杂的内部结构。
通过对术语规则的修改:
term:
fi = constraint (
CONDITION_OPEN then = constraint CONDITION_CLOSE
)?;
我收到 line 1:12 mismatched input '<EOF>' expecting {WORD,ANY_SPACE}
而不是 no viable alternative
错误消息。这似乎是更具体的错误消息。
也就是说,这似乎是一个相当精简的语法,这种避免替代的更改在更大范围内可能不切实际。
最后,很可能会出现 no viable alternative
错误消息。
您也可以考虑实施您自己的错误恢复策略,但这更常用于跳过某些策略以避免开销。添加更多逻辑可能是“专家”级别的努力。
注意:我刚刚在 ANTLR 书中注意到的一个相当聪明的替代方案是,如果您有某些常见错误(例如,说一个尾随的“/”),您可以添加一个规则来专门检测错误。
constraint:
ANY_SPACE? (element) ANY_SPACE? (operation constraint)?
| ANY_SPACE? (element) ANY_SPACE? operation {notifyErrorListeners("operation without following constraint");
};
给出:line 1:12 operation without following constraint
用于输入 001/002/003/
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。