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

Antlr4 具有模式的常见令牌

如何解决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。

result screenshot

问题:我该如何解决这个问题? 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 举报,一经查实,本站将立刻删除。