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

时间:2015-01-21 16:13:46

标签: antlr grammar tokenize antlr4 lexical-analysis

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

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

helloXYZ

然后令牌规则应返回此令牌:

hello

如果输入是这样的:

Blah Blah XYZ

然后令牌规则应返回此令牌:

Blah Blah

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

3 个答案:

答案 0 :(得分: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 :(得分:1)

这个怎么样?

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

答案 2 :(得分:1)

使用Terrance在答案中提供的提示,我认为这正是Roger所寻求的:

grammar UseLookahead;

parserRule : LexerRule;

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

这分别给出了所需答案helloBlah Blah。我承认我不理解最终?的重要性。