31

我想在 flex 中制定一个规则来使用像 /* */ 这样的 c 样式注释

我有以下

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

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

4

9 回答 9

47

我建议您改用开始条件

%x C_COMMENT

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

请注意,规则和规则之间不能有任何空格。<condition>

%x C_COMMENT定义 C_COMMENT 状态,并且规则/*启动它。一旦它开始,*/它会回到初始状态(INITIAL预定义),并且所有其他字符都将被消耗而无需任何特定操作。当两条规则匹配时,Flex 会通过匹配最长的一条来消除歧义,因此点规则不会阻止*/匹配。该\n规则是必要的,因为点匹配除换行符之外的所有内容

%x定义使 C_COMMENT 成为排他状态,这意味着词法分析器将仅匹配<C_COMMENT>进入状态后“标记”的规则。

这是一个小例子词法分析器,它通过打印除里面的所有内容来实现这个答案/* comments */

于 2010-01-25T04:00:28.110 回答
9

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

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

foo.l

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

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

%%
// c code..

希望对某人有所帮助!蒂夫

于 2013-01-29T02:55:13.670 回答
7

不知道为什么它没有被选中,但我知道这种模式可以产生大量的词汇元素。仅检测开始注释标记并将所有内容都扔到 bitbucket 中直到找到结束标记会更有效。

这个网站有代码可以做到这一点:

"/*" {
    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;
        }
    }
}
于 2010-01-25T04:01:09.577 回答
2

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

"/*"((\*+[^/*])|([^*]))*\**"*/"
于 2012-11-13T20:47:35.247 回答
1

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

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

    "/*" { int c1 = 0, c2 = input();
           为了(;;) {
             如果(c2 == EOF)中断;
             如果(c1 == '*' && c2 == '/')
               休息;
             c1 = c2;
             c2 = 输入();
           }
         }
    
于 2014-07-24T16:09:22.840 回答
1

Flex 手册中有一个工作示例,它可以正确处理粗糙的边缘情况:

<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++;
于 2016-09-25T09:37:42.487 回答
1

另一个例子:

"/*"([^*]*|(\*+[^/]))*"*/"
于 2021-01-18T10:05:24.987 回答
0

工作示例是:

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

ostermiller.org中找到

于 2013-08-08T12:28:28.210 回答
0

忽略空格和换行符

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

Kenneth C. Louden - Compiler Construction_Principles and Practice (1997) 第 2.2.3 节

于 2022-02-21T03:41:49.093 回答