【问题标题】:Lex program rules not workingLex 程序规则不起作用
【发布时间】:2013-09-03 04:36:20
【问题描述】:
%{
    #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 程序来计算注释行的数量(单行 cmets 和多行 cmets 分别)。

使用此代码,我提供了一个 .c 文件和一个空白文本文件作为输入和输出参数。
当我在多行 cmets 中有任何特殊字符时,它不适用于该多行,并且 mline 不会为注释行增加。

我该如何解决这个问题?

【问题讨论】:

    标签: lex


    【解决方案1】:

    下面是朝着正确方向的轻推。你所做的和我所做的主要区别在于我只做了两个正则表达式——一个用于空格,一个用于 ident(标识符)。我所说的标识符是指您想要注释掉的任何内容。这个正则表达式显然可以扩展为包含其他字符和符号。我还刚刚定义了三个开始和结束 cmets 的模式,并将它们与我们可以传递给语法分析器的标记相关联(但这是一个全新的主题)。

    我还更改了您向程序提供输入的方式。我发现将输入从文件重定向到程序并将输出重定向到另一个文件更简洁 - 如果您需要的话。

    以下是您如何使用此程序的示例:

    flex filename.l
    g++ lex.yy.c -o lexer
    ./lexer < input.txt
    

    如果需要,您可以使用以下命令将输出重定向到另一个文件:

    ./lexer &lt; input.txt &gt; 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;
    
    }
    

    【讨论】:

      【解决方案2】:

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

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

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

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

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

      【讨论】:

        【解决方案3】:

        以下是计算注释行和可执行行数的完整 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 中

        【讨论】:

          猜你喜欢
          • 2018-03-06
          • 1970-01-01
          • 1970-01-01
          • 2022-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多