我目前正致力于支持C风格评论的ANTLR词法分析器规则。对于这样一个目标,有一个广泛推荐的规则:
C_COMMENT
:
'/*' (options {greedy=false;}: .)* '*/'
{ $channel=HIDDEN; }
;
然而,我想要的是另一种选择:'+'不允许成为评论正文的第一个非空格字符,例如: / * + blablabla * /不是有效的评论。 然后我尝试了这样的事情:
C_COMMENT
:
'/*' (' '|'\r'|'\t'|'\n')* ~(' '|'\r'|'\t'|'\n'|'+') (options {greedy=false;}: .)* '*/'
{ $channel=HIDDEN; }
;
除了空注释/ * * /之外,它几乎可以工作。所以我试过这样的事情:
C_COMMENT
:
'/*' (' '|'\r'|'\t'|'\n')*
(
'*/'
|
(~(' '|'\r'|'\t'|'\n'|'+') (options {greedy=false;}: .)* '*/')
)
{ $channel=HIDDEN; }
;
它和一些我没有列出的类似的东西从来没有奏效过。 * / in / * * /总是属于〜(''|'\ r'|'\ t'|'\ n'|'+')部分。
最后我得到了这样的工作:
C_COMMENT
:
'/*' (' '|'\r'|'\t'|'\n')* '*/'
{ $channel=HIDDEN; }
|
'/*' (' '|'\r'|'\t'|'\n')*
(
'*/'
|
(~(' '|'\r'|'\t'|'\n'|'+') (options {greedy=false;}: .)* '*/')
)
{ $channel=HIDDEN; }
;
虽然ANTLR警告像/ * * /这样的模式可以匹配两种选择。
有人能帮我理解这一切吗?我的意思是,为什么在最后一个之上没有任何工作。
提前致谢。
答案 0 :(得分:2)
为什么不这样做:
grammar T;
parse
: ( c_comment
| plus_comment
)*
EOF
;
c_comment
: C_COMMENT
;
plus_comment
: PLUS_COMMENT
;
PLUS_COMMENT
: '/*' S* '+' .* '*/'
;
C_COMMENT
: '/*' .* '*/'
;
SPACES
: S+ {skip();}
;
fragment S
: ' ' | '\t' | '\r' | '\n'
;
将解析输入:
/**/ /* + as*/ /* sdcdcds sdcds */
如下:
这里的诀窍是在 PLUS_COMMENT
之前定义C_COMMENT
。这样,如果词法分析器偶然发现"/* s"
,它会从PLUS_COMMENT
回退到C_COMMENT
,因为它与+
不匹配。