C 使用Flex检测和跳过行注释
如何在Flex中检测像C 使用Flex检测和跳过行注释,c,compiler-construction,flex-lexer,C,Compiler Construction,Flex Lexer,如何在Flex中检测像/这样的单行注释并跳过这些行 另外,对于/*注释,以下代码片段是否足够 "/*" { comment(); } %% comment() { char c, c1; loop: while ((c = input()) != '*' && c != 0) putchar(c); if ((c1 = input()) != '/' &a
/
这样的单行注释并跳过这些行
另外,对于/*
注释,以下代码片段是否足够
"/*" { comment(); }
%%
comment()
{
char c, c1;
loop:
while ((c = input()) != '*' && c != 0)
putchar(c);
if ((c1 = input()) != '/' && c != 0)
{
unput(c1);
goto loop;
}
if (c != 0)
putchar(c1);
}
对于
/
,您可以一直阅读,直到找到\n
或EOF
行的结尾,如果注释位于文件末尾,例如:
static void
skip_single_line_comment(void)
{
int c;
/* Read until we find \n or EOF */
while((c = input()) != '\n' && c != EOF)
;
/* Maybe you want to place back EOF? */
if(c == EOF)
unput(c);
}
对于多行注释/**/
,您可以一直阅读直到看到*
,并查看下一个字符,如果是/
,这意味着这是注释的结尾,如果不只是用任何其他字符跳过它。您不应该期望EOF
,它意味着未关闭的注释:
static void
skip_multiple_line_comment(void)
{
int c;
for(;;)
{
switch(input())
{
/* We expect ending the comment first before EOF */
case EOF:
fprintf(stderr, "Error unclosed comment, expect */\n");
exit(-1);
goto done;
break;
/* Is it the end of comment? */
case '*':
if((c = input()) == '/')
goto done;
unput(c);
break;
default:
/* skip this character */
break;
}
}
done:
/* exit entry */ ;
}
完整文件:
%{
#include <stdio.h>
static void skip_single_line_comment(void);
static void skip_multiple_line_comment(void);
%}
%option noyywrap
%%
"//" { puts("short comment was skipped ");
skip_single_line_comment();}
"/*" { puts("long comment begins ");
skip_multiple_line_comment();
puts("long comment ends");}
" " { /* empty */ }
[\n|\r\n\t] { /* empty */ }
. { fprintf(stderr, "Tokenizing error: '%c'\n", *yytext);
yyterminate(); }
%%
static void
skip_single_line_comment(void)
{
int c;
/* Read until we find \n or EOF */
while((c = input()) != '\n' && c != EOF)
;
/* Maybe you want to place back EOF? */
if(c == EOF)
unput(c);
}
static void
skip_multiple_line_comment(void)
{
int c;
for(;;)
{
switch(input())
{
/* We expect ending the comment first before EOF */
case EOF:
fprintf(stderr, "Error unclosed comment, expect */\n");
exit(-1);
goto done;
break;
/* Is it the end of comment? */
case '*':
if((c = input()) == '/')
goto done;
unput(c);
break;
default:
/* skip this character */
break;
}
}
done:
/* exit entry */ ;
}
int main(int argc, char **argv)
{
yylex();
return 0;
}
%{
#包括
静态无效跳过单行注释(无效);
静态无效跳过多行注释(无效);
%}
%选项No yywrap
%%
“/”{puts(“跳过简短评论”);
跳过单行注释()}
“/*”{puts(“长评论开始”);
跳过多行注释();
puts(“长注释结束”);}
“”{/*空*/}
[\n |\r\n\t]{/*空*/}
. {fprintf(stderr,“标记化错误:'%c'\n',*yytext”);
yyterminate();}
%%
静态空隙
跳过单行注释(无效)
{
INTC;
/*阅读直到找到\n或EOF*/
而((c=input())!='\n'和&c!=EOF)
;
/*也许你想把EOF放回去*/
如果(c==EOF)
取消打印(c);
}
静态空隙
跳过多行注释(无效)
{
INTC;
对于(;;)
{
开关(输入())
{
/*我们希望在EOF之前先结束评论*/
案例EOF:
fprintf(标准,“错误未关闭注释,预期*/\n”);
出口(-1);
去做;
打破
/*这是评论的结尾吗*/
案例“*”:
如果((c=input())=='/'))
去做;
取消打印(c);
打破
违约:
/*跳过此字符*/
打破
}
}
完成:
/*出入境*/;
}
int main(int argc,字符**argv)
{
yylex();
返回0;
}
为什么不使用正则表达式来识别注释呢?lex/flex
的全部目的是避免您必须手工编写词汇扫描程序。您提供的代码应该可以工作(如果您将模式/*
放在行的开头),但是它有点难看,而且不明显它是否可以工作
您的问题表示您想跳过注释,但您提供的代码使用putchar()
打印注释,除了开头的/*
。你想做什么?如果要回显注释,可以使用echo
操作,而不是什么都不做
以下是正则表达式:
单行评论
这一点很简单,因为在lex/flex中,
与换行符不匹配。因此,以下内容将从/
匹配到行尾,然后不执行任何操作
"//".* { /* DO NOTHING */ }
多行评论
这有点棘手,而且*是正则表达式字符,也是注释标记的关键部分,这使得下面的正则表达式有点难以阅读。我使用[*]
作为识别字符*的模式;在flex/lex中,您可以使用“*”
。使用你觉得更可读的。基本上,正则表达式匹配以(字符串)*结尾的字符序列,直到找到下一个字符是/的字符序列。换句话说,它与您的C代码具有相同的逻辑
[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] { /* DO NOTHING */ }
上述要求终止*/
;未终止的注释将强制lexer备份到注释的开头,并接受其他标记,通常是/division运算符。这可能不是你想要的,但要从一条未终止的评论中恢复过来并不容易,因为没有真正好的方法知道该评论应该在哪里结束。因此,我建议添加一个错误规则:
[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] { /* DO NOTHING */ }
[/][*] { fatal_error("Unterminated comment"); }
要检测单行注释:
^"//" printf("This is a comment line\n");
^"/*"[^*]*|[*]*"*/" printf("This is a Multiline Comment\n");
这表示任何以//开头的行都将被视为注释行
要检测多行注释:
^"//" printf("This is a comment line\n");
^"/*"[^*]*|[*]*"*/" printf("This is a Multiline Comment\n");
*
说明:
*
^”/*“
这说明开头应该是/*
[^*]*
包括所有字符,包括但不包括*
[*]*
表示0个或更多的星星
[^*]|[*]*
-“或”运算符用于获取任何字符串
“*/”
将*/指定为结束
这在莱克斯身上非常有效
以下是lex文件的完整代码:
%{
#include <stdio.h>
int v=0;
%}
%%
^"//" printf("This is a comment line\n");
^"/*"[^*]*|[*]*"*/" printf("This is a Multiline Comment\n");
.|\n {}
%%
int yywrap()
{
return 1;
}
main()
{
yylex();
}
%{
#包括
int v=0;
%}
%%
^“//”printf(“这是注释行\n”);
^“/*”[^*]*|[*]*“*/”printf(“这是一个多行注释\n”);
.|\n{}
%%
int yywrap()
{
返回1;
}
main()
{
yylex();
}
您的多行注释解决方案简单而伟大,但我仍然有一个问题。。。我需要为每行注释增加一个行计数器,所以我需要考虑\n的内部注释…是否有可能保持您的正则表达式解决方案的主要思想?Thanksflex会帮你数台词。参见YYLINENOhmm。。真奇怪。Flex为我的输入返回了错误的行。。。它只计算带有初始注释符号的行。我刚刚提出了另一个问题来讨论这一点@达诺:不对。线路拼接可能发生在初始的/
之间。此外,如果您支持Trigraph,则可以将线拼接拼写为??/
。此处的多行注释显然不起作用。考虑:/*富吧**/