Flex lexer 难以在flex/lex中获得c风格的注释
我想在flex中制定一个规则,使用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
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++;
"/*"([^*]*|(\*+[^/]))*"*/"