我想要一个令牌规则,它会吞噬所有字符,直到它到达字符
XYZ
。
因此,如果输入是这样的:
helloXYZ
那么令牌规则应该返回这个令牌:
hello
如果输入是这样的:
Blah Blah XYZ
那么令牌规则应该返回这个令牌:
Blah Blah
如何定义令牌规则来执行此操作?
使用特伦斯在回答中给出的提示,我认为这就是罗杰正在寻找的:
grammar UseLookahead;
parserRule : LexerRule;
LexerRule : .+? { (_input.LA(1) == 'X') &&
(_input.LA(2) == 'Y') &&
(_input.LA(3) == 'Z')
}?
;
这分别给出了所需的答案,
hello
和Blah 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
;
这个怎么样?
HELLO : 'hello' {_input.LA(1)!=' '}? ;