ANTLR 4 令牌规则匹配任何字符,直到遇到 XYZ

问题描述 投票:0回答:3

我想要一个令牌规则,它会吞噬所有字符,直到它到达字符

XYZ

因此,如果输入是这样的:

helloXYZ

那么令牌规则应该返回这个令牌:

hello

如果输入是这样的:

Blah Blah XYZ

那么令牌规则应该返回这个令牌:

Blah Blah

如何定义令牌规则来执行此操作?

antlr grammar tokenize antlr4 lexical-analysis
3个回答
2
投票

使用特伦斯在回答中给出的提示,我认为这就是罗杰正在寻找的:

grammar UseLookahead;

parserRule : LexerRule;

LexerRule : .+? { (_input.LA(1) == 'X') &&
                  (_input.LA(2) == 'Y') &&
                  (_input.LA(3) == 'Z') 
                }?
          ;

这分别给出了所需的答案,

hello
Blah Blah
。 我承认我不明白最后
?
的意义。


2
投票

如果你想要良好的性能,你需要使用不使用谓词的形式。如果令牌以 XYZ 结尾,我将使用在

PositionAdjustingLexer.g4
之后建模的代码来重置位置。

编辑: 不要低估使用语义谓词的答案对性能的影响。将为整个输入流的每个字符至少评估一次谓词,并且将阻止评估谓词的任何字符使用 DFA。上次我看到这样的东西在使用时,它占据了整个解析过程 95% 以上的执行时间,删除它后,性能从 20 多秒提高到不到 1 秒。

tokens {
  SpecialToken
}

mode SpecialTokenMode;

  // In your position adjusting lexer, if you see a token with the type
  // SpecialTokenWithXYZ, reset the position to remove the last 3 characters and set
  // the type to SpecialToken
  SpecialTokenWithXYZ
    : 'XYZ'
      -> popMode
    ;

  SpecialTokenCharacterAtEOF
    : . EOF
      -> type(SpecialToken), popMode
    ;

  SpecialTokenCharacter
    : .
      -> more
    ;

如果您想要更好的性能,您可以添加一些规则来优化对不包含任何

X
字符的序列的处理:

tokens {
  SpecialToken
}

mode SpecialTokenMode;

  // In your position adjusting lexer, if you see a token with the type
  // SpecialTokenWithXYZ, reset the position to remove the last 3 characters and set
  // the type to SpecialToken
  SpecialTokenWithXYZ
    : 'XYZ'
      -> popMode
    ;

  SpecialTokenCharacterSpanAtEOF
    : ~'X'+ EOF
      -> type(SpecialToken), popMode
    ;

  SpecialTokenCharacterSpan
    : ~'X'+
      -> more
    ;

  SpecialTokenXAtEOF
    : 'X' EOF
      -> type(SpecialToken), popMode
    ;

  SpecialTokenX
    : 'X'
      -> more
    ;

1
投票

这个怎么样?

HELLO : 'hello' {_input.LA(1)!=' '}? ;
© www.soinside.com 2019 - 2024. All rights reserved.