我正在尝试在语法中匹配 W 或 W * 。这是精简版:
grammar PdfStream;
content : stat* ;
stat
: wCap ;
wCap: 'W' '*'? ; // Set clipping path using nonzero winding ('W') or even-odd ('W*') rule
// Accept all characters except whitespace and defined delimiters ()<>[]{}/%
ID: ~[ \t\r\n\u000C\u0000()<>[\]{}/%]+ ;
WS: [ \t\r\n\u000C\u0000]+ -> skip ; // PDF defines six whitespace characters
当我用此输入尝试时:
W W * W
我的访客获得第一个 W ,但之后没有任何收获。
但是如果我改用这个定义:
wCap: ('W'|'W*') ;
访客获得所有三个陈述。
这是一个可行的解决方案,但是我很好奇为什么我的第一个定义不起作用。
答案 0 :(得分:2)
Antlr词法分析器规则倾向于最长的匹配,然后通过采用首先定义的规则来打破平局。
为了使事情更清楚,让我们将隐式标记'W'
和'*'
移入已命名的词法器规则中,因为这是antlr在内部所做的。我将它们称为DUB_U
和STAR
,以在引用规则与字符时避免混淆。因此,您的词法分析器确实是:
DUB_U: 'W' ;
STAR: '*' ;
ID: ~[ \t\r\n\u000C\u0000()<>[\]{}/%]+ ;
WS: [ \t\r\n\u000C\u0000]+ -> skip ;
匹配W W* W
时,您会获得令牌流:
DUB_U(W) WS( ) ID(W*) WS( ) DUB_U(W)
这是因为W*
匹配ID
,并且比简单匹配W
中的DUB_U
更长。
将规则更改为wCap: ('W'|'W*') ;
时,新的有效词法分析器为:
DUB_U: 'W' ;
DUB_U_STAR: 'W*' ;
ID: ~[ \t\r\n\u000C\u0000()<>[\]{}/%]+ ;
WS: [ \t\r\n\u000C\u0000]+ -> skip ;
匹配W W* W
时,您会获得令牌流:
DUB_U(W) WS( ) DUB_U_STAR(W*) WS( ) DUB_U(W)
这是因为W*
匹配两者 DUB_U_STAR
和ID
,但是首先定义了DUB_U_STAR
,并且决胜局做出了{{1} }令牌。