代码之家  ›  专栏  ›  技术社区  ›  adhanlon

难以在flex/lex中获得C样式的评论

  •  25
  • adhanlon  · 技术社区  · 15 年前

    我想用flex做一个规则来使用C风格的注释,比如/**/

    我有以下内容

    c_comment "/*"[\n.]*"*/"
    

    但它从来都不匹配。你知道为什么吗?如果你需要更多的我的代码,请告诉我,我会提交整个事情。感谢任何回复的人。

    8 回复  |  直到 7 年前
        1
  •  38
  •   rici    7 年前

    我建议你用 start conditions 相反。

    %x C_COMMENT
    
    "/*"            { BEGIN(C_COMMENT); }
    <C_COMMENT>"*/" { BEGIN(INITIAL); }
    <C_COMMENT>\n   { }
    <C_COMMENT>.    { }
    

    注意那里 不能 中间有空白 <condition> 还有规则。

    %x C_COMMENT 定义注释状态和规则 /* 开始吧。一旦启动, */ 它会回到初始状态吗( INITIAL 是预先定义的),并且所有其他字符都将在没有任何特定操作的情况下被使用。当两个规则匹配时,flex通过采用最长匹配的规则消除歧义,因此点规则不会阻止 */ 从匹配。这个 \n 规则是必要的,因为 a dot matches everything except a newline .

    这个 %x 定义使注释 独占状态 ,这意味着lexer将只匹配“标记”的规则。 <C_COMMENT> 一旦进入状态。

    这里是一个 tiny example lexer 通过打印除内部内容以外的所有内容来实现此答案 /* comments */ .

        2
  •  9
  •   user1747935    12 年前

    以下是一个例子,以防有人对如何使用zneak的答案感到困惑:

    (基本上,您将“%x c_comment”放在第一节中,其余部分放在第二节中,正如他的帮助链接所解释的那样)

    foo.l
    
    %{
    // c code..
    %}
    %x C_COMMENT
    
    %%
    "/*"            { BEGIN(C_COMMENT); }
    <C_COMMENT>"*/" { BEGIN(INITIAL); }
    <C_COMMENT>.    { }
    
    %%
    // c code..
    

    希望能帮助别人! 口角

        3
  •  7
  •   paxdiablo    15 年前

    不知道为什么没有人找到它,但我知道这种模式可以产生大量的词汇元素。更有效的方法是只检测开始注释标记,并将所有内容放入位桶中,直到找到结束标记。

    This site 有这样做的代码:

    "/*" {
        for (;;) {
            while ((c = input()) != '*' && c != EOF)
                ; /* eat up text of comment */
            if (c == '*') {
                while ((c = input()) == '*')
                    ;
                if (c == '/')
                    break; /* found the end */
            }
            if (c == EOF) {
                error ("EOF in comment");
                break;
            }
        }
    }
    
        4
  •  2
  •   Optimus Prime    11 年前

    我认为这个解决方案更简单:

    "/*"((\*+[^/*])|([^*]))*\**"*/"
    
        5
  •  1
  •   rici    7 年前

    有一个很好的例子 the Flex manual 使粗糙边缘的情况正确:

    <INITIAL>"/*"         BEGIN(IN_COMMENT);
    <IN_COMMENT>"*/"      BEGIN(INITIAL);
    <IN_COMMENT>[^*\n]+   // eat comment in chunks
    <IN_COMMENT>"*"       // eat the lone star
    <IN_COMMENT>\n        yylineno++;
    
        6
  •  0
  •   mwag    11 年前

    我已经尝试了几个建议的解决方案,下面是结果。

    • 我找不到投票最多、看起来很棒的C_评论解决方案,无法在实践中发挥作用(其中一条评论至少解释了一个原因)。它应该被否决,当然也不应该是投票最高的解决方案。
    • 穆根的解决方案似乎适用于我运行它的所有代码。
    • 无法从Andrey那里获得解决方案,甚至无法在lex中编译。我查看了参考的网站,使用那里的模式没有帮助
    • Paxdiablo的答案很有效,而且易于阅读。我进一步修改如下:

      "/*" { int c1 = 0, c2 = input();
             for(;;) {
               if(c2 == EOF) break;
               if(c1 == '*' && c2 == '/')
                 break;
               c1 = c2;
               c2 = input();
             }
           }
      
        7
  •  0
  •   rici    10 年前

    工作示例是:

    \/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/
    

    发现在 ostermiller.org

        8
  •  -2
  •   user3790829    10 年前

    "/*"(.|\n)"*/" 将正则表达式改为这个,它肯定会起作用。