Antlr4 如何在antlr lexer中处理嵌套注释
如何处理antlr4 lexer中的嵌套注释?ie我需要计算此令牌中“/*”的数量,并仅在收到相同数量的“*/”后关闭。例如,D语言具有“/+…++/”等嵌套注释 例如,以下行应视为一组注释:Antlr4 如何在antlr lexer中处理嵌套注释,antlr4,Antlr4,如何处理antlr4 lexer中的嵌套注释?ie我需要计算此令牌中“/*”的数量,并仅在收到相同数量的“*/”后关闭。例如,D语言具有“/+…++/”等嵌套注释 例如,以下行应视为一组注释: /* comment 1 comment 2 /* comment 3 comment 4 */ // comment 5 comment 6 */ COMMENT : '/*' (COMMENT|.)*? '*/' -> channel(HIDDEN)
/* comment 1
comment 2
/* comment 3
comment 4
*/
// comment 5
comment 6
*/
COMMENT : '/*' (COMMENT|.)*? '*/' -> channel(HIDDEN) ;
LINE_COMMENT : '//' .*? '\n' -> channel(HIDDEN) ;
我的当前代码如下所示,它不适用于上述嵌套注释:
COMMENT : '/*' .*? '*/' -> channel(HIDDEN)
;
LINE_COMMENT : '//' ~('\n'|'\r')* '\r'? '\n' -> channel(HIDDEN)
;
我可以为您提供一个ANTLR3解决方案,您可以调整该解决方案以在ANTLR4中工作: 我认为可以使用递归规则调用。为/*…*/创建非贪婪注释规则这就叫它自己。这应该允许无限嵌套,而不必计算开始和结束注释标记:
COMMENT option { greedy = false; }:
('/*' ({LA(1) == '/' && LA(2) == '*'} => COMMENT | .) .* '*/') -> channel(HIDDEN)
;
甚至可能:
COMMENT option { greedy = false; }:
('/*' .* COMMENT? .* '*/') -> channel(HIDDEN)
;
我不确定ANTLR是否根据任何字符或注释介绍人正确选择了正确的路径。试试看。特伦斯·帕尔(Terence Parr)在他的词典中有两行词法分析器,用于对嵌套注释进行词法分析:
/* comment 1
comment 2
/* comment 3
comment 4
*/
// comment 5
comment 6
*/
COMMENT : '/*' (COMMENT|.)*? '*/' -> channel(HIDDEN) ;
LINE_COMMENT : '//' .*? '\n' -> channel(HIDDEN) ;
我正在使用:
COMMENT: '/*' ('/'*? COMMENT | ('/'* | '*'*) ~[/*])*? '*'*? '*/' -> skip;
这将强制注释中的任何/*
成为嵌套注释的开头,类似地,注释中的*/
也是如此。换句话说,除了在规则注释的开头和结尾之外,无法识别/*
和*/
这样,像/*/*/**/a*/
这样的东西将不会被完全识别为(坏的)注释(不匹配的/*
s和*/
s),就像使用注释:'/*'(注释|?'*/'->跳过代码>,但作为/
,后跟*
,后跟正确的嵌套注释/*/**/a*/
适用于Antlr3
允许在注释中嵌套注释和“*”
fragment
F_MultiLineCommentTerm
:
( {LA(1) == '*' && LA(2) != '/'}? => '*'
| {LA(1) == '/' && LA(2) == '*'}? => F_MultiLineComment
| ~('*')
)*
;
fragment
F_MultiLineComment
:
'/*'
F_MultiLineCommentTerm
'*/'
;
H_MultiLineComment
: r= F_MultiLineComment
{ $channel=HIDDEN;
printf(stder,"F_MultiLineComment[\%s]",$r->getText($r)->chars);
}
;
这将处理:“/*/*/”和“/*…/*/”,其中注释正文分别为“/”和“…/”
多行注释不会嵌套在单行注释内,因此不能在单行注释内启动或开始多行注释。
- 这不是有效的注释:'/*/*/'
- 您需要一个换行符来结束单行注释,然后才能使用“*/”来结束多行注释
- 这是有效的注释:'/*/*/\n/*/'
- 注释正文为:'/*/\n/'。如您所见,完整的单行注释包含在多行注释的主体中
虽然如果前面的字符为“*”,则“/*/”可以结束多行注释,但注释将在第一个“/”处结束,其余的“*/”将需要结束嵌套注释,否则将出现错误。最短路径获胜,这是非贪婪!
- 这不是有效的注释/***//
- 这是一条有效的注释/*/****/,注释正文为/****,它本身就是一条嵌套注释
前缀和后缀在多行注释正文中永远不会匹配
如果要为“D”语言实现此功能,请将“*”更改为“+”
COMMENT\u NEST
: '/*'
((“/”|“*”+)?~[*/]|注释|注释| INL)*?
('/'|'*'+?)?
'*/'
;代码>
COMMENT\u INL
:“/”(注释| ~[\n\r])*
;代码>谢谢。我首先在ANTLR3本身中尝试了您的解决方案,然后转到ANTLR4,但它不起作用。我刚刚用您的规则替换了我的注释规则,然后ANTLR3报告了错误,如:error(100):X.g:语法错误:antlr:MissingTokenException(在选项处插入[@-1,0:0=”,1927:8]记住Antlr3生成的lexer只有1个字符的前瞻性,除非你像上面的例子那样使用谓词。有没有办法也为未完成的块注释制定规则,从而引发自定义错误?