难以在flex / lex中获得c风格的评论

时间:2010-01-25 03:52:19

标签: flex-lexer

我想在flex中制定规则来使用像/ * * /

这样的c风格的注释

我有以下

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

但它永远不会匹配。知道为什么吗?如果您需要更多我的代码请告诉我,我会提交整件事。感谢任何回复的人。

9 个答案:

答案 0 :(得分:41)

我建议你改用start conditions

%x C_COMMENT

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

请注意必须<condition>和规则之间的任何空格。

%x C_COMMENT定义了C_COMMENT状态,规则/*启动了它。一旦启动,*/将使其返回到初始状态(INITIAL已预定义),并且所有其他角色将在没有任何特定操作的情况下被消费。当两个规则匹配时,Flex会通过选择具有最长匹配的规则来消除歧义,因此点规则不会阻止*/匹配。 \n规则是必要的,因为a dot matches everything except a newline

%x定义使C_COMMENT成为独占状态,这意味着词法分析器只会匹配一旦进入状态后被“标记”<C_COMMENT>的规则。

这是一个tiny example lexer,通过打印/* comments */内的所有内容来实现此答案。

答案 1 :(得分:9)

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

(基本上,你将“%x C_COMMENT”放在第一部分,其余部分放在第二部分,正如他的有用链接所解释的那样)

foo.l

%{
// c code..
%}
%x C_COMMENT

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

%%
// c code..

希望有人帮助! TIFF

答案 2 :(得分:7)

不确定为什么它没有被拾取但是我知道那种模式可以产生大的词汇元素。在找到结束标记之前,只检测开始注释标记并将所有内容丢弃在bitbucket中会更有效。

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;
        }
    }
}

答案 3 :(得分:2)

我相信这个解决方案更简单:

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

答案 4 :(得分:1)

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++;

答案 5 :(得分:0)

工作的例子是:

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

ostermiller.org

中找到

答案 6 :(得分:0)

我已经尝试了几种建议的解决方案,结果如下。

  • 我无法得到C_COMMENT解决方案,它具有最高的投票率和看起来很棒,在实践中完全可以工作(其中一条评论解释了至少一个原因)。它应该被投票,当然不应该是投票率最高的解决方案
  • Mugen的解决方案似乎适用于我在
  • 上运行的所有代码
  • 无法从安德利获得解决方案甚至在lex中编译。我查看了引用的网站,并使用那里的模式没有帮助
  • paxdiablo的答案奏效,并且具有易于阅读的优点。我进一步修改如下:

    "/*" { int c1 = 0, c2 = input();
           for(;;) {
             if(c2 == EOF) break;
             if(c1 == '*' && c2 == '/')
               break;
             c1 = c2;
             c2 = input();
           }
         }
    

答案 7 :(得分:0)

另一个例子:

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

答案 8 :(得分:-2)

"/*"(.|\n)"*/"将您的正则表达式更改为此,它肯定会有效。