我想要一个令牌规则,它会吞噬所有字符,直到它到达字符XYZ
。
因此,如果输入是这样的:
helloXYZ
然后令牌规则应返回此令牌:
hello
如果输入是这样的:
Blah Blah XYZ
然后令牌规则应返回此令牌:
Blah Blah
如何定义令牌规则来执行此操作?
答案 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')
}?
;
这分别给出了所需答案hello
和Blah Blah
。我承认我不理解最终?
的重要性。