如何在ANTLR4中指定可选的结尾字符?

时间:2019-06-21 21:16:39

标签: antlr4

我正在尝试在语法中匹配 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*') ;

访客获得所有三个陈述。

这是一个可行的解决方案,但是我很好奇为什么我的第一个定义不起作用。

1 个答案:

答案 0 :(得分:2)

Antlr词法分析器规则倾向于最长的匹配,然后通过采用首先定义的规则来打破平局。

为了使事情更清楚,让我们将隐式标记'W''*'移入已命名的词法器规则中,因为这是antlr在内部所做的。我将它们称为DUB_USTAR,以在引用规则与字符时避免混淆。因此,您的词法分析器确实是:

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_STARID,但是首先定义了DUB_U_STAR,并且决胜局做出了{{1} }令牌。