Flex lexer 难以在flex/lex中获得c风格的注释

Flex lexer 难以在flex/lex中获得c风格的注释,flex-lexer,Flex Lexer,我想在flex中制定一个规则,使用c风格的注释,如/**/ 我有以下几点 c_comment "/*"[\n.]*"*/" 但它从来没有匹配过。知道为什么吗?如果你需要更多的我的代码,请让我知道,我会提交整个事情。感谢所有回复您的人。我建议您改用 %x C\u注释 “/*”{开始(C_注释);} “*/”{开始(首字母);} \n{} . { } 请注意,与规则之间不得有任何空格 %x C_COMMENT定义C_COMMENT状态,规则/*将其启动。一旦启动,*/将使其返回初始状态(i

我想在flex中制定一个规则,使用c风格的注释,如/**/

我有以下几点

c_comment "/*"[\n.]*"*/"
但它从来没有匹配过。知道为什么吗?如果你需要更多的我的代码,请让我知道,我会提交整个事情。感谢所有回复您的人。

我建议您改用

%x C\u注释
“/*”{开始(C_注释);}
“*/”{开始(首字母);}
\n{}
.    { }
请注意,与规则之间不得有任何空格

%x C_COMMENT
定义C_COMMENT状态,规则
/*
将其启动。一旦启动,
*/
将使其返回初始状态(
initial
是预定义的),并且只会使用其他字符,而无需执行任何特定操作。当两个规则匹配时,Flex通过选择匹配时间最长的规则来消除歧义,因此点规则不会阻止
*/
匹配。
\n
规则是必需的,因为

%x
定义使C_注释成为独占状态,这意味着lexer在进入状态后将只匹配“标记”的规则


这是一个通过打印所有内容来实现这个答案的方法,除了
/*注释*/

不确定为什么没有被提取出来,但我知道这样的模式可以产生大量词汇元素。只检测开始注释标记,然后将所有内容都放入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;
        }
    }
}

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

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

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

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

foo.l
%{
//c代码。。
%}
%x C_评论
%%
“/*”{开始(C_注释);}
“*/”{开始(首字母);}
.    { }
%%
//c代码。。
希望这对别人有帮助! Tiff

工作示例如下:

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

中,我尝试了几种建议的解决方案,下面是结果

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

    "/*" { int c1 = 0, c2 = input(); for(;;) { if(c2 == EOF) break; if(c1 == '*' && c2 == '/') break; c1 = c2; c2 = input(); } } “/*”{int c1=0,c2=input(); 对于(;;){ 如果(c2==EOF)中断; 如果(c1=='*'&&c2=='/') 打破 c1=c2; c2=输入(); } }

中有一个成功的示例,它正确地处理了粗糙边缘的情况:

<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++;
“/*”开始(在注释中);
“*/”开始(首字母);
[^*\n]+//分块吃注释
“*”//吃孤星
\nyylineno++;
另一个例子:

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

我不知道为什么这里没有匹配项,但是您的表达式将吃掉文件中第一个“/*”和最后一个“*/”之间的所有内容。与注释内容匹配的表达式必须排除“*/”才能使用。一种方法是:谢谢,那个网站很有帮助。我不确定这样使用输入是否真的好这不是一种担忧的混合吗?我通常倾向于实用主义而不是教条主义:-)我在这里只看到一个担忧,那就是吃掉评论,这样你就可以继续使用真正的标记。然而,你可能会说这个例子没有利用flex提供的抽象机制来让你做的更清楚。@Nate,我不怀疑有更好的方法可以做到这一点,我只提供了一个解决方案。我的经验是使用lex/yacc,我从来没有使用过flex/bison,因为它们在我需要开发的平台上不可用。这是很久以前的事了,在那些日子里,编译器甚至从来没有看到过注释——它们是由预处理器剥离出来的,然后是我们开发环境中的一个单独的程序:AT&T 3B2 vintage,它应该表明我的年龄:-)在我看来,这是解决这个特定问题的一个很好的方法。在lex/flex框架中,C风格的注释无法非常清晰地表达出来,因此您不妨编写一些代码来处理它,正如您所做的那样。这样做的好处是不需要lex状态,我觉得这会使语法更难理解。我的评论更多的是对zneak的回应:只要这里的代码严格执行词法分析(事实上是这样),我觉得它在正确的位置,不会出现关注点分离的问题。即使它是正确的(我很难看到),它的效率很低,因为相当长的词素可能需要在
yytext
中缓冲。我知道我来晚了,但是这个正则表达式会错误地将
/*垃圾*/*/
识别为完整的块注释(从
/*
到第二个
*/
),与C样式块注释相反,在C样式块注释中,打开的
/*
被最近的关闭的
*/
终止,而另一个
*/
被识别为程序中的游离字符。下面的正则表达式(用于flex/lex)也处理这种情况
“/*”((((“*”[^/])?)|[^*])*“*/”
Source-[link]()。{},如果@zneak使用follopwing,它将被解析为
[^*\n]*“*”+[^*/\n]*
。它会吃掉所有的东西,除了*后面跟着/。所以在这种情况下,它将以第一个*结尾,然后是/。因此,
/*垃圾*/傻瓜*/
,它会评论
/*垃圾*/
,然后
<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++;
"/*"([^*]*|(\*+[^/]))*"*/"