将 C 中的 /* ... */ 注释干掉。
%x COMMENT,给 flex 增加了一个 state。通过 BEGIN(state) 进入某个 state,则以 <state> 开头的 pattern 就会启用。
flex 默认的 state 是 INITIAL。
通过 <COMMENT>.|\n 吃掉 /* */ 之间的所有字符。
%noyywrap 可以让最后编译的时候 gcc lex.yy.c -lfl 去掉 -lfl 选项。
%yylineno 会多一个 yylineno 的变量,碰到 \n 则自动 yylineno++。
\n { ECHO; yylineno++; }
. { ECHO; }
当没有任何 pattern 匹配时,则启用这两条规则。写出来只是更明了些。
===================== commen.l =======================
%option noyywrap yylineno
%x COMMENT
%{
#include <stdio.h>
const char *curfile;
%}
%%
"/*" { BEGIN(COMMENT); }
<COMMENT>"*/" { BEGIN(INITIAL); }
<COMMENT>.|\n
<COMMENT><<EOF>> { printf("%s:%d: unterminated comment\n", curfile, yylineno); yyterminate(); }
\n { ECHO; yylineno++; }
. { ECHO; }
%%
void parse_one_file(const char *file)
{
YY_BUFFER_STATE bs;
FILE *fp;
curfile = file;
fp = fopen(file, "r");
bs = yy_create_buffer(fp, YY_BUF_SIZE);
yy_switch_to_buffer(bs);
yylex();
yy_delete_buffer(bs);
fclose(fp);
}
int main(int argc, char *argv[])
{
int i;
if ( argc < 2 ) {
fprintf(stderr, "usage: ./a.out filename\n");
return 1;
}
for ( i = 1; i < argc; i++ )
parse_one_file(argv[i]);
return 0;
}
======================================================
$ flex comment.l
$ gcc -Wall lex.yy.c
$ ./a.out xxx.c
======================================================
<COMMENT>.|\n 每次只"吃掉"一个字符,可以这样写 <COMMENT>([^*]|\n)+|. 每次吃掉一串字符。
([^*]|\n)+ 只要不碰到 * 号,则可以匹配一串字符或换行,加快 pattern-match 的速度。
我们再把匹配规则改一下,则支持 nested comment。
"/*" { comment_recursive_cnt++; BEGIN(COMMENT); }
<COMMENT>"/*" { comment_recursive_cnt++; }
<COMMENT>"*/" { comment_recursive_cnt--; if (comment_recursive_cnt <= 0) BEGIN(INITIAL); }
<COMMENT>.|\n
<COMMENT><<EOF>> { printf("%s:%d: unterminated comment\n", curfile, yylineno); yyterminate(); }
评论