当前位置: 首页 > 知识库问答 >
问题:

Antlr4带模式的通用令牌

梁鸿风
2023-03-14

将标记移动到公共文件之前的语法

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
    ;

将标记移动到公共文件后的语法

通用lexer由其他3个lexer导入。它具有共享的标识符令牌。

lexer grammar CommonLexer;

..
..
IDENTIFIER
    : A_Z ((UNDERSCORE | A_Z | DIGIT | WS)*? (UNDERSCORE | A_Z | DIGIT))*
    ;

以下lexer导入通用lexer,并具有几种模式

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\u START now的将被识别为标识符。

结果屏幕截图

问题:我如何解决这个问题?标识符应保留在CommonLexer中。

如果您需要更多详细信息,请告诉我,谢谢。

共有1个答案

仉伟兆
2023-03-14

我不能确定(你只是在通用Lexer提取中有日蚀),但是在原始Lexer语法中,IDENTIFIER只有在你被推送VALUE_MODE时才会匹配。当你创建通用Lexer时,你似乎已经失去了这个特性。因为它在通用Lexer中是“公开的”,所以它会匹配你是否VALUE_MODE(长度会使它更强)。这解释了不同的行为。

您的IDENTIFIER lexer规则匹配的字符串比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])* 

在这里,我无法真正区分输入流中的命令和标识符。(在令牌中包含WS也是一种反模式)。

这是您可以控制语言设计的地方,还是您必须符合既定定义的地方?

如果你有控制权,我建议你读一读,重新考虑你的方法。

如果它已经建立,也许您可以分享建立的定义以及它如何区分IDENTIFIER和COMMAND。

从这里的行中可以看出,冒号之前的任何内容都是命令,冒号之后的任何内容都是需要标识符的地方。

我认为您试图在Lexer中投入太多工作。尝试将您的命令解析器规则重新思考为更像解析器规则的东西:

genericCommand:  +IDENTIFIER (COLON parameterArray)?;

(如果可以管理的话,我建议从命令和标识符标记中删除WS。这往往会产生各种各样的标记化歧义问题。)

 类似资料:
  • 如何实现这些模式?

  • 我有一个这样的可重装武器类: 具有以下: 并像这样使用它: 客户: 我想知道,对于命令,对于我看到的示例,除了命令正在操作的对象之外,没有其他。 此示例更改执行方法以允许使用参数。 另一个示例,更接近我在这里拥有的,在构造函数中使用参数。 在命令中包含参数是不是不好的做法/代码气味,在这种情况下是带有项目符号数的?

  • 是否有方法为模式中捕获的所有字符返回一个字符串类型的标记,包括导致进入模式的字符? 模式何时结束? 我知道我也可以像这样编写字符串标记:

  • 如果我对“令牌”不感兴趣,因为规则已经建立了我要匹配的对象,而且我无论如何都要跳过它,那么用和令牌声明替换它有意义吗?(然后,代币的数量将会增加。)为什么在ANTLRWorks中这是一个警告?

  • 我是一个Antlr4新手,有一个相对简单的语法问题。语法在末尾的底部给出。(这是一个语法片段,用于分析生物序列变体的描述)。 在下面的单元测试中,我试图解析字符串。 这里出了什么问题?我在哪里可以学习如何解决这个问题?

  • 我有不同实现的< code>ProductHandler类,例如< code>ABCProductHandler、< code>DEFProductHandler等..它们是使用如下所示的命令模式从< code>ProductServiceImpl类调用的。 产品ServiceImpl类: 但是,我对上面的 类不满意,因为有很多带有样板代码的产品 调用。 现在,我的问题是,有什么方法可以轻松加载?