1
%{
    #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 不会为注释行增加。

我该如何解决这个问题?

4

3 回答 3

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;

}
于 2013-09-04T19:38:17.820 回答
1

问题是您的多行注释的正则表达式:

"/*"[a-zA-Z0-9 \t\n]*"*/"

这仅匹配仅包含字母、数字、空格、制表符和换行符的多行注释。如果评论包含其他任何内容,它将不匹配。你想要这样的东西:

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

这将匹配除and*/之间的任何内容。/**/

于 2013-09-04T20:18:11.053 回答
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;
}

该程序将输入作为 c++ 程序 abc.cpp 并将输出附加到文件 abc.txt 中

于 2015-07-27T15:55:33.253 回答