【问题标题】:Flex not counting lines properly on multiline commentsFlex 在多行注释上没有正确计算行数
【发布时间】:2014-08-21 00:15:30
【问题描述】:

我正在使用上述正则表达式来识别 Flex 中的多行 cmets:

[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/]       { /* 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。

有什么想法吗?

【问题讨论】:

  • 您需要包含更多代码 :) 我只能说,当我包含 %option yylineno 时,标识符、运算符和空格的模式,并打印 yylineno 和返回令牌,它工作正常。

标签: c compiler-construction flex-lexer


【解决方案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;
    }
  }
}

【讨论】:

  • 嘿@rici。谢谢你的时间。我刚刚找到了另一个解决方法。我发布了解决方案。
  • @adolfosrs: Como você gosta, mas o meu é mais fácil。 Porque você faz o trabalho que faz o flex sem carga? ... 从长远来看,让 flex 处理 yylineno 更易于维护。
【解决方案2】:

这是我在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);

【讨论】:

    【解决方案3】:

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

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

    所以我找到了另一种方法,即使使用正则表达式也能保持行数。解释如下:

    你知道 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 的数量,并将其添加到计算当前行数的全局变量中。

    我上面使用的计算字符出现次数的代码来自this post。 因此,使用上面的代码,我始终拥有正确的当前行号,并且代码可以完美运行。

    【讨论】:

      猜你喜欢
      • 2023-01-18
      • 2019-05-07
      • 1970-01-01
      • 2011-06-12
      • 2021-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多