如何在 ANTLR 词法分析器中处理嵌套注释



如何处理antlr4词法分析器中的嵌套注释? 即我需要计算此令牌中的"/*"数量,并在收到相同数量的"*/"后关闭。例如,D 语言具有诸如"/+ ... +/"之类的嵌套注释

例如,以下行应被视为一个注释块:

/* comment 1
   comment 2
   /* comment 3
      comment 4
   */
   // comment 5
   comment 6
*/

我当前的代码如下,它不适用于上面的嵌套注释:

COMMENT : '/*' .*? '*/' -> channel(HIDDEN)
        ;
LINE_COMMENT : '//' ~('n'|'r')* 'r'? 'n'  -> channel(HIDDEN)
        ;

Terence Parr 在他的 Swift Antlr4 语法中有这两行词法分析器,用于谱写嵌套注释:

COMMENT : '/*' (COMMENT|.)*? '*/' -> channel(HIDDEN) ;
LINE_COMMENT  : '//' .*? 'n' -> channel(HIDDEN) ;

我正在使用:

COMMENT: '/*' ('/'*? COMMENT | ('/'* | '*'*) ~[/*])*? '*'*? '*/' -> skip;

这会强制注释中的任何/*成为嵌套注释的开头,与 */ 类似。换句话说,除了在规则COMMENT的开头和结尾之外,没有办法识别/**/

这样,像 /* /* /* */ a */ 这样的东西就不会像使用 COMMENT: '/*' (COMMENT|.)*? '*/' -> skip; 那样被完全识别为(错误(注释(/* 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); 
    }
;

我可以给你一个ANTLR3解决方案,你可以调整它以在ANTLR4中工作:

我认为您可以使用递归规则调用。为/* ... */创建一个非贪婪的注释规则,该规则调用自身。这应该允许无限嵌套,而不必计算开始+结束注释标记:

COMMENT option { greedy = false; }:
    ('/*' ({LA(1) == '/' && LA(2) == '*'} => COMMENT | .) .* '*/') -> channel(HIDDEN)
;

甚至可能:

COMMENT option { greedy = false; }:
    ('/*' .* COMMENT? .* '*/') -> channel(HIDDEN)
;

我不确定 ANTLR 是否根据任何字符或评论介绍人正确选择了正确的路径。试试吧。

    这将处理:"/*/*/"和"/*.../*/">
  1. ,其中注释正文分别为"/"和".../"。
  2. 多行注释不会嵌套在单行注释中
  3. ,因此不能在单行注释中开始或开始多行注释。
    • 这不是一个有效的注释:"/*//*/"。
    • 您需要一个换行符来结束单行注释,然后才能使用"*/"来结束多行注释。
    • 这是一个有效的注释:"/*//*//*/"。
    • 注释正文为: '//*//'。 如您所见,完整的单行注释包含在多行注释的正文中。
  4. 尽管如果前面的字符是"*",则"/*/"可以结束多行注释,但注释将在第一个"/">
  5. 结束,其余的"*/"将需要结束嵌套注释,否则会出现错误。 最短路径获胜,这是不贪婪!
    • 这不是一个有效的评论/****/*/
    • 这是一个有效的注释/*/****/
    • */,注释正文是/****/,它本身就是一个嵌套注释。
  6. 前缀和后缀在多行注释正文中永远不会匹配。
  7. 如果要为"D"语言实现此功能,请将"*"更改为"+"。

COMMENT_NEST : '/*' ( ('/'|'*'+)? ~[*/] | COMMENT_NEST | COMMENT_INL )*? ('/'|'*'+?)? '*/' ;

COMMENT_INL : '//' ( COMMENT_INL | ~[nr] )* ;

相关内容

  • 没有找到相关文章

最新更新