用于C风格评论的ANTLR词法分析器

时间:2015-01-23 05:45:49

标签: regex parsing antlr grammar lexer

我目前正致力于支持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警告像/ * * /这样的模式可以匹配两种选择。

有人能帮我理解这一切吗?我的意思是,为什么在最后一个之上没有任何工作。

提前致谢。

1 个答案:

答案 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 */

如下:

enter image description here

这里的诀窍是在 PLUS_COMMENT之前定义C_COMMENT 。这样,如果词法分析器偶然发现"/* s",它会从PLUS_COMMENT回退到C_COMMENT,因为它与+不匹配。