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

ANTLR 4 token rule that matches any characters until it encounters XYZ

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

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

helloXYZ

那么令牌规则应该return这个令牌:

hello

如果输入是这样的:

Blah Blah XYZ

那么令牌规则应该return这个令牌:

Blah Blah

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

这个怎么样?

HELLO : 'hello' {_input.LA(1)!=' '}? ;

根据 Terrance 在他的回答中给出的提示,我认为这就是 Roger 正在寻找的内容:

grammar UseLookahead;

parserRule : LexerRule;

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

这给出了所需的答案,分别为 helloBlah Blah。我承认我不明白最后的 ?.

的意义

如果你想要好的性能,你需要使用不使用谓词的形式。如果令牌以 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
    ;