Lexer,重叠规则,但想要更短的匹配

时间:2014-05-22 17:26:37

标签: antlr4

我想读取输入流并将输入分为两种类型:PATTERN& WORD_WEIGHT,定义如下。

问题产生于为WORD_WEIGHT定义的所有字符对PATTERN也有效。当我们有多个不带空格的WORD_WEIGHT时,词法分析器将匹配PATTERN,而不是提供多个WORD_WEIGHT。

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

  • [20] => WORD_WEIGHT
  • cat => PATTERN
  • [dog] => PATTERN

这种情况,这就是问题所在。它与PATTERN匹配,因为 词法分析器将选择2种可能性中较长的一种。注意: 他们之间没有空间。

  • [20] [30] => WORD_WEIGHT WORD_WEIGHT

还需要处理这种情况(这对...施加了一些限制) 可能的解决方案)。请注意,括号可能不匹配 对于PATTERN ......

  • [[[cat] => PATTERN

这是语法:

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规则会给出所需的结果吗?

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

后续行动 - 我们选择的解决方案:

将上面的WORD_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_WEIGHTS标记的值。这恰好与我们的用法相匹配 - 我们的语法(不在上面的代码段中)总是将单词权重定义为"一个或多个"。现在,多样性被捕获了#34;由词法分析器而不是解析器。如果/当我们需要分别处理每个单词权重时,我们可以在应用程序中拆分值(解析树监听器)。

1 个答案:

答案 0 :(得分:1)

您可以按如下方式实施WORD_WEIGHT

WORD_WEIGHT
  : '[' WORD_WEIGHT_VALUE ']'
    PATTERN?
  ;

然后,在词法分析器中,您可以覆盖emit方法来更正词法分析器的位置,以删除添加到{{1}末尾的PATTERN(如果有)令牌。你可以在ANTLRWorks 2中看到这个例子:

修改需要以下步骤。

  1. 覆盖WORD_WEIGHT以添加resetAcceptPosition方法。
  2. 在lexer类的构造函数中将LexerATNSimulator字段设置为自定义_interp的实例。
  3. 计算令牌的所需结束位置,然后致电LexerATNSimulator。对于在ST4示例中看到的固定宽度令牌,计算只是在令牌开头出现的固定运算符或关键字的长度。对于您的情况,您需要致电resetAcceptPosition并检查结果以确定getText()令牌的正确长度。由于WORD_WEIGHT规则无法与WORD_WEIGHT_VALUE匹配,因此最简单的分析可能是查找]结果中第一个]字符的索引(getText()的语法1}}确保角色永远存在。)