如何解决Antlr4 具有模式的常见令牌
lexer grammar ALexer;
COMMAND_START
: [a-zA-Z] -> pushMode(COMMAND_MODE)
;
EQUALS
: '=' -> pushMode(VALUE_MODE)
;
mode COMMAND_MODE;
COMMAND_NAME_REMAINDER
: ([a-zA-Z0-9_ ]? [a-zA-Z0-9])* -> popMode
;
mode VALUE_MODE;
IDENTIFIER
: A_Z ((UNDERscore | A_Z | DIGIT | WS)*? (UNDERscore | A_Z | DIGIT))* -> popMode
;
通用词法分析器由其他 3 个词法分析器导入。它具有共享的 IDENTIFIER 令牌。
lexer grammar CommonLexer;
..
..
IDENTIFIER
: A_Z ((UNDERscore | A_Z | DIGIT | WS)*? (UNDERscore | A_Z | DIGIT))*
;
下面的词法分析器导入了 Common 词法分析器并有几个模式
lexer grammar ALexer;
import CommonLexer;
COMMAND_START
: [a-zA-Z] -> pushMode(COMMAND_MODE)
;
EQUALS
: '=' -> pushMode(VALUE_MODE)
;
mode COMMAND_MODE;
COMMAND_NAME_REMAINDER
: ([a-zA-Z0-9_ ]? [a-zA-Z0-9])* -> popMode
;
mode VALUE_MODE;
IDENTIFIER_VALUE_MODE
: IDENTIFIER -> type(IDENTIFIER),popMode
;
解析器语法:
parser grammar AParser;
options { tokenVocab=ALexer; }
genericCommand
: COMMAND_START COMMAND_NAME_REMAINDER? (COLON parameterarray)?
;
结果: 诸如“删除资源:a;”之类的命令之前被识别为 COMMAND_START 现在被识别为 IDENTIFIER。
问题:我该如何解决这个问题? IDENTIFIER 应保留在 CommonLexer 中。
如果您需要更多详细信息,请告诉我,谢谢。
解决方法
我不能肯定(您只是在 Common Lexer 摘录中有日食),但在原始 Lexer 语法中,IDENTIFIER 只会在您被推送 VALUE_MODE 时匹配。当您创建 Common Lexer 时,您似乎已经失去了该特性。由于它在公共词法分析器中“处于开放状态”,因此无论您是否处于 VALUE_MODE 中,它都会匹配(并且长度将使其成为更强的匹配)。这解释了不同的行为。
您的 IDENTIFIER 词法分析器规则匹配比 COMMAND_START 更长的字符串,因此它将优先。您不会在 COMMAND_START 规则上获得“命中”以将您推入 COMMAND_MODE。这是您问题的核心。您的 IDENTIFIER 规则与 COMMAND_START 规则重叠,并且始终至少与 COMMAND_START 规则匹配项一样长(1 个字符)或更长,因此 ANTLR 将始终支持它。
如果没有 A_Z、UNDERSCORE、DIGIT 和 WS 的片段定义(您像片段一样使用它们,所以我假设它们是),则很难确定您打算成为 COMMAND 和 IDENTIFIER 之间的区别.
您让 COMMAND_START 触发模式仅立即弹出它的方式是“不寻常的”。我希望看到包含整个模式的 COMMAND Lexer 规则:
COMMAND: [a-zA-Z]([a-zA-Z0-9_ ]? [a-zA-Z0-9])*
在这里,我真的无法分辨输入流中 COMMAND 和 IDENTIFIER 的区别。 (在令牌中包含 WS 也是一种反模式)。
这是您可以控制语言设计的地方,还是您必须匹配既定定义的地方?
如果你有控制权,我建议你应该多读一点并重新考虑你的方法。
如果它已经建立,也许您可以分享建立的定义以及它如何区分 IDENTIFIER 和 COMMAND。
阅读此处的两行,似乎冒号之前的内容是命令,冒号之后的内容是您期望标识符的位置。
我认为您试图将过多的工作投入到 Lexer 中。尝试将您的命令解析器规则重新考虑为更像解析器规则的东西:
genericCommand: +IDENTIFIER (COLON parameterArray)?;
(如果可以管理的话,我建议从 COMMAND 和 IDENTIFIER 令牌中删除 WS。这往往会产生各种令牌化歧义问题。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。