Flex无法正确计数多行注释中的行数

问题描述 投票:1回答:3

我使用上述正则表达式在Flex中标识多行注释:

[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/]       { /* DO NOTHING */ }

但是在我看来,flex / bison没有正确返回线路计数器。例如:

输入:

1  ___bqmu7ftc
2 // _qXnFEgQL9Zsyn8Ohtx7zhToLK68xbu3XRrOvRi 
3 /* "{ output 6 = <=W if u7 do nN)T!=$||JN,a9vR)7" 
4  -758939 
5 -31943.6165480 
6 // "RND" 
7  '_' 
8 */
9 [br _int]

输出:

1 TK_IDENT [___bqmu7ftc]
4 [
4 TK_IDENT [br]
4 TK_IDENT [_int]
4 ]

该行应为9而不是4。

有什么想法吗?

c compiler-construction flex-lexer
3个回答
1
投票

我不知道您如何在问题中生成测试输出,但是这是(几乎)如何使用yylineno的最小示例。对我来说效果很好:

%{
  #define ID 257
%}

%option yylineno
%option noinput nounput noyywrap

%%

[[:space:]]+                            { /* DO NOTHING */ }
"//".*                                  { /* DO NOTHING */ }
[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/]     { /* DO NOTHING */ }
[[:alpha:]_][[:alnum:]_]*               { return ID; }
.                                       { return *yytext; }

%%

int main(int argc, char** argv) {
  for (;;) {
    int token = yylex();
    switch (token) {
      case 0:   printf("%4d: %s\n",       yylineno, "EOF"); return 0;
      case ID:  printf("%4d: %-4s[%s]\n", yylineno, "ID", yytext); break;
      default:  printf("%4d: %c\n",       yylineno, token); break;
    }
  }
}

1
投票

这是我在Flex manual上找到的解决方案

记住在定义范围内声明int comment_caller;

%x comment 
%x foo
%%

"/*" {comment_caller = INITIAL;
    BEGIN(comment);
      }

     <foo>"/*"  {
      comment_caller = foo;
      BEGIN(comment);
      }

     <comment>[^*\n]*    {}
     <comment>"*"+[^*/\n]*   {}
     <comment>\n       {++line_num;}
     <comment>"*"+"/"    BEGIN(comment_caller);

0
投票

我在使用flex多行注释时遇到了同样的问题。我使用了this stackoverflow question中建议的正则表达式(与您在此问题中提到的正则表达式相同)

此正则表达式还在多行注释中获得了新行。因此,如果您用\ n计算当前行的数量,则会遇到麻烦。因为可能存在多行注释,并且正则表达式会一次选择整个多行注释。因此,它不允许您计算新行。

因此,我找到了另一种方法来保持行数,即使使用正则表达式也是如此。在下面解释:

[您知道flex将匹配的表达式保留在yytext变量中。因此,我们可以在多行注释中计算新行的数量,并且该代码与我测试的任何代码均能完美配合。这是我的代码:注意:numberOfCurrentLine变量是我用来保存当前行号的全局变量。

[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] {
        // The code below, the counts number of occurance of \n and then adds
        // the number to the numberOfCurrentLine variable
        // to keep the number of current line

        char* str = yytext;
        int i = 0;
        char *pch=strchr(str,'\n');
        while (pch!=NULL) {
            i++;
            pch=strchr(pch+1,'\n');
        }

        numberOfCurrentLine+=i;
    }

此代码计算所选注释中的\ n数,并将其添加到正在计算当前行数的全局变量中。

我上面使用的用于计算char出现次数的代码来自this post。因此,使用上面的代码,我总是可以得到当前行的正确编号,并且代码可以完美运行。

© www.soinside.com 2019 - 2024. All rights reserved.