Antlr4 Lexer,重叠规则,但需要较短的匹配

Antlr4 Lexer,重叠规则,但需要较短的匹配,antlr4,Antlr4,我想读取一个输入流,并将输入分为两种类型:模式和单词权重,定义如下 问题产生于这样一个事实,即为单词_WEIGHT定义的所有字符对模式也是有效的。当我们有多个单词权重,且两个单词之间没有空格时,lexer将匹配模式,而不是提供多个单词权重 我需要能够处理以下情况并获得指示结果: [20] =>字的重量 cat=>模式 [狗]=>图案 这个案子,这就是问题所在。它符合模式,因为 lexer将选择两种可能性中较长的一种。注: 他们之间没有空隙 [20] [30]=>单词权重单词权重 还需要处

我想读取一个输入流,并将输入分为两种类型:模式和单词权重,定义如下

问题产生于这样一个事实,即为单词_WEIGHT定义的所有字符对模式也是有效的。当我们有多个单词权重,且两个单词之间没有空格时,lexer将匹配模式,而不是提供多个单词权重

我需要能够处理以下情况并获得指示结果:

  • [20] =>字的重量
  • cat=>模式
  • [狗]=>图案
这个案子,这就是问题所在。它符合模式,因为 lexer将选择两种可能性中较长的一种。注: 他们之间没有空隙

  • [20] [30]=>单词权重单词权重
还需要处理此情况(这对 可能的解决办法)。请注意,括号可能不匹配 作为一种模式

  • [[[cat]=>模式
语法如下:

grammar Brackets;

fragment
DIGIT
    : ('0'..'9')
    ;

fragment
WORD_WEIGHT_VALUE           
    : ('-' | '+')? DIGIT+ ('.' DIGIT+)? 
    | ('-' | '+')? '.' DIGIT+
    ;

WORD_WEIGHT 
    : '[' WORD_WEIGHT_VALUE ']' 
    ;

PATTERN   
    : ~(' ' | '\t' | '\r' | '\n' )+  
    ;

WS 
    : (' ' | '\t' | '\r' | '\n' )+ -> Skip
    ;


start : (PATTERN | WORD_WEIGHT)* EOF;
问题是,什么样的Lexer规则会给出期望的结果

我希望有一个功能,一个特殊的指令,可以为影响匹配过程的lexer规则指定。它将在规则匹配时指示lexer停止匹配过程并使用此匹配令牌

跟进-我们选择的解决方案:

将上面的单词_WEIGHT替换为:

fragment
WORD_WEIGHT 
    : '[' WORD_WEIGHT_VALUE ']'
    ;

WORD_WEIGHTS
    : WORD_WEIGHT (INNER_WS? WORD_WEIGHT)*
    ;

fragment
INNER_WS
    : (' ' | '\t' )+
    ;
此外,语法规则变为:

start : (PATTERN | WORD_WEIGHTS)* EOF;

现在,任何单词权重序列(空格分隔或不分隔)都将是单词权重标记的值。这也恰好符合我们的用法-我们的语法(不在上面的片段中)总是将单词权重定义为“一个或多个”。现在,多重性被“捕获”如果/当我们需要单独处理每个单词权重时,我们可以在应用程序(解析树侦听器)中拆分值。

您可以实现
单词权重
,如下所示:

WORD_WEIGHT
  : '[' WORD_WEIGHT_VALUE ']'
    PATTERN?
  ;
然后,在您的lexer中,您可以覆盖
emit
方法来更正lexer的位置,以删除添加到
单词权重
标记末尾的
模式(如果有)。您可以在AntlWorks 2中看到这方面的示例:

  • StringTemplate 4中的标记为
  • StringTemplate 4中的标记为
修改需要以下步骤

  • 重写
    lexeransimulator
    以添加方法
  • 在lexer类的构造函数中,将
    \u interp
    字段设置为自定义
    LexeranSimulator
    的实例
  • 计算您的令牌所需的结束位置,然后调用
    resetAcceptPosition
    。对于ST4示例中所示的固定宽度令牌,计算只是出现在令牌开头的固定运算符或关键字的长度。对于您的情况,您需要调用
    getText()
    并检查结果以确定
    单词权重
    标记的正确长度。由于
    单词权重
  • 规则无法匹配
    ]
    ,最简单的分析可能是找到
    getText()结果中第一个
    ]
    字符的索引(
    WORD\u WEIGHT
    的语法确保该字符始终存在)
    谢谢!我按照您的建议开始实施,但是出于可维护性的考虑(2年后,当其他人试图理解这一点时)…我们决定支持一个只涉及对lexer规则进行一些更改的解决方案。如果有人感兴趣,我会将更改添加到原始问题中(我想网站会允许我这么做……我是新来的)