%{
#include <stdio.h>
int sline=0,mline=0;
%}
%%
"/*"[a-zA-Z0-9 \t\n]*"*/" { mline++; }
"//".* { sline++; }
.|\n { fprintf(yyout,"%s",yytext); }
%%
int main(int argc,char *argv[])
{
if(argc!=3)
{
printf("Invalid number of arguments!\n");
return 1;
}
yyin=fopen(argv[1],"r");
yyout=fopen(argv[2],"w");
yylex();
printf("Single line comments = %d\nMultiline comments=%d\nTotal comments = %d\n",sline,mline,sline+mline);
return 0;
}
我正在尝试制作一个Lex计划,它会计算评论行的数量(单行注释和多行注释)。
使用此代码,我提供了一个.c文件和一个空白文本文件作为输入和输出参数 当我在多行注释中有任何特殊字符时,它不适用于该多行和mline不会增加注释行。
如何解决此问题?
答案 0 :(得分:2)
下面是正确方向的推动。你做了什么和做了什么之间的主要区别是我只做了两个正则表达式 - 一个用于空格,一个用于ident(标识符)。标识符的含义是您要注释掉的任何内容。这个正则表达式显然可以扩展为包含其他字符和符号。我还定义了开始和结束注释的三种模式,并将它们与我们可以传递给语法分析器的标记相关联(但这是一个全新的主题)。
我还改变了将输入提供给程序的方式。我发现将输入从文件重定向到程序并将输出重定向到另一个文件更加清晰 - 如果需要的话。
以下是您可以使用此程序的示例:
flex filename.l
g++ lex.yy.c -o lexer
./lexer < input.txt
如果需要,可以使用以下方法将输出重定向到另一个文件:
./lexer < input.txt > output.txt
而不是上面的最后一个命令。
注意:模式匹配结尾处的'。'(点)字符用作字符,字符序列,符号等没有匹配项的全能字符。
使用正则表达式来匹配注释行的模式匹配有很多细微差别。例如,即使注释行是字符串的一部分,它仍然会匹配。
实施例。 " //This is a comment in a string! "
你需要做一些工作才能克服这些细微差别 - 就像我说的那样,这是一个正确方向的推动。
你可以做类似的事情来实现你的目标:
%{
#include <stdio.h>
int sline = 0;
int mline = 0;
#define T_SLINE 0001
#define T_BEGIN_MLINE 0002
#define T_END_MLINE 0003
#define T_UNKNOWN 0004
%}
WSPACE [ \t\r]+
IDENT [a-zA-Z0-9]
%%
"//" {
printf("TOKEN: T_SLINE LEXEME: %s\n", yytext);
sline++;
return T_SLINE;
}
"/*" {
printf("TOKEN: T_BEGIN_MLINE LEXEME: %s\n", yytext);
return T_BEGIN_MLINE;
}
"*/" {
printf("TOKEN: T_END_MLINE LEXEME: %s\n", yytext);
mline++;
return T_END_MLINE;
}
{IDENT} {/*Do nothing*/}
{WSPACE} { /*Do Nothing*/}
. {
printf("TOKEN: UNKNOWN LEXEME: %s\n", yytext);
return T_UNKNOWN;
}
%%
int yywrap(void) { return 1; }
int main(void) {
while ( yylex() );
printf("Single-line comments = %d\n Multi-line comments = %d\n Total comments = %d\n", sline, mline, (sline + mline));
return 0;
}
答案 1 :(得分:1)
问题是您对多行评论的正则表达式:
"/*"[a-zA-Z0-9 \t\n]*"*/"
这仅匹配仅包含字母,数字,空格,制表符和换行符的多行注释。如果评论包含其他任何内容,则不匹配。你想要这样的东西:
/"*"([^*]|"*"+[^*/])*"*"+/
这将匹配*/
和/*
之间除*/
之外的任何内容。
答案 2 :(得分:0)
下面是完整的lex代码,用于计算注释行和可执行行的数量。
%{
int cc=0,cl=0,el=0,flag=0;
%}
%x cmnt
%%
^[ \t]*"//".*\n {cc++;cl++;}
.+"//".*\n {cc++;cl++;el++;}
^[ \t]*"/*" {BEGIN cmnt;}
<cmnt>\n {cl++;}
<cmnt>.\n {cl++;}
<cmnt>"*/"\n {cl++;cc++;BEGIN 0;}
<cmnt>"*/" {cl++;cc++;BEGIN 0;}
.*"/*".*"*/".+\n {cc++;cl++;}
.+"/*".*"*/".*\n {cc++;cl++;el++;}
.+"/*" {BEGIN cmnt;}
.\n {el++;}
%%
main()
{
yyin=fopen("abc.cpp","r");
yyout=fopen("abc.txt","w");
yylex();
fprintf(yyout,"Comment Count: %d \nCommented Lines: %d \nExecutable Lines: %d",cc,cl,el);
}
int yywrap()
{
return 1;
}
程序将输入作为cc程序abc.cpp并将输出附加到文件abc.txt