如何在 lex 中打印注释?

How to print comments in lex?

所以标题可能有点误导,但我想不出更好的措辞方式。

基本上,我正在使用 cygwin/lex 编写 lexical-scanner。代码的一部分读取令牌 /* 。它会进入预定义状态 C_COMMENT,并在 C_COMMENT"/*" 时结束。下面是实际代码

"/*" {BEGIN(C_COMMENT); printf("%d: /*", linenum++);}
<C_COMMENT>"*/" { BEGIN(INITIAL); printf("*/\n"); }
<C_COMMENT>.    {printf("%s",yytext);}

注释在单行时代码有效,例如

/* * Example of comment */

它会打印当前行号,后面有注释。但如果评论跨越多行,它就不起作用。将第3行重写为

<C_COMMENT>.    {printf("%s",yytext);
                 printf("\n");}

不起作用。它将导致为注释中的每个字母打印 \n。我猜这与 C 没有字符串有关,或者我使用的状态有误。

希望有人能够帮助我:)

此外,如果您需要任何其他信息,尽管询问,我会提供。

  1. 回显模式扫描的令牌的最简单方法是使用特殊操作 ECHO:

    "/*"            { printf("%d: ", linenum++); ECHO; BEGIN(C_COMMENT); }
    <C_COMMENT>"*/" { ECHO; BEGIN(INITIAL); }
    <C_COMMENT>.    { ECHO; }
    
  2. None 以上规则匹配注释中的换行符,因为在 (f)lex 中 . 不匹配换行符:

    <C_COMMENT>\n   { linenum++; ECHO; }
    
  3. 识别 C 注释的更快方法是使用单个正则表达式,尽管它有点难以阅读:

    [/][*][^*]*[*]+([^/*][^*][*]+)*[/]
    

    在这种情况下,您必须重新扫描评论以计算换行符,除非您使用 flex 来计算行号。

  4. flex 扫描仪在 yylineno 中维护行号计数,如果您请求该功能(使用 %option yylineno)。它通常比自己记数更有效,而且总是更可靠。但是,在操作中,yylineno 的值是模式末尾的行数计数,而不是开头的行数,这可能会误导多行模式。一个常见的解决方法是在令牌扫描开始时将 yylineno 的值保存在另一个变量中。