微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Antlr 解析器表现得很奇怪

如何解决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 举报,一经查实,本站将立刻删除。