%{
#include <stdio.h>
int sline=0,mline=0;
%}
%%
"/*"[a-zA-Z0-9 tn]*"*/" { 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 = %dnMultiline comments=%dnTotal comments = %dn",sline,mline,sline+mline);
return 0;
}
我正在尝试制作一个 Lex 程序,该程序将计算注释行的数量(单行注释和多行注释分开(。
使用此代码,我给出了一个 .c 文件和一个空白文本文件作为输入和输出参数。
当我在多行注释中有任何特殊字符时,它不适用于该多行,并且注释行的 mline 不会递增。
如何解决此问题?
下面是朝着正确方向的推动。你所做的和我所做的主要区别在于我只做了两个正则表达式 - 一个用于空格,一个用于标识符(标识符(。我所说的标识符是指您想要注释掉的任何内容。这个正则表达式显然可以扩展到包括其他字符和符号。我还刚刚定义了开始和结束注释的三种模式,并将它们与我们可以传递给语法分析器的标记相关联(但这是一个全新的主题(。
我还更改了将输入输入到程序的方式。我发现将输入从文件重定向到程序并将输出重定向到另一个文件更干净 - 如果您需要这个。
下面是如何使用此程序的示例:
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 [ tr]+
IDENT [a-zA-Z0-9]
%%
"//" {
printf("TOKEN: T_SLINE LEXEME: %sn", yytext);
sline++;
return T_SLINE;
}
"/*" {
printf("TOKEN: T_BEGIN_MLINE LEXEME: %sn", yytext);
return T_BEGIN_MLINE;
}
"*/" {
printf("TOKEN: T_END_MLINE LEXEME: %sn", yytext);
mline++;
return T_END_MLINE;
}
{IDENT} {/*Do nothing*/}
{WSPACE} { /*Do Nothing*/}
. {
printf("TOKEN: UNKNOWN LEXEME: %sn", yytext);
return T_UNKNOWN;
}
%%
int yywrap(void) { return 1; }
int main(void) {
while ( yylex() );
printf("Single-line comments = %dn Multi-line comments = %dn Total comments = %dn", sline, mline, (sline + mline));
return 0;
}
问题是您的多行注释正则表达式:
"/*"[a-zA-Z0-9 tn]*"*/"
这仅匹配仅包含字母、数字、空格、制表符和换行符的多行注释。 如果评论包含任何其他内容,则不匹配。 你想要这样的东西:
/"*"([^*]|"*"+[^*/])*"*"+/
这将匹配除/*
和*/
之间的*/
之外的任何内容。
下面是计算注释行和可执行行数的完整 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;
}
该程序将输入作为 abc 的 c++ 程序.cpp并将输出附加到文件 abc 中.txt