yytext匹配正则表达式的结尾

时间:2014-09-16 01:57:02

标签: regex flex-lexer lex

我有一个lex文件,我试图用它来解析代码。例如,我有这样的事情:

...
%%
COMMENT ("(^"|"/^")(.|\n)*("^)"|"^/")
%%
{COMMENT} printf( "comment: %s\n", yytext );
[.]*      printf( "other: %s\n", yytext );
%%
...

在这种情况下输入

(^^^^^^^^^
this is a comment
^)

function(arg);
sometext

正在输出:

comment: (^^^^^^^^^
this is a comment
^)

function(arg)
other: ;
sometext

等。所以它匹配")"但不是" ^)"并且它与下一个看到的" ^)"不匹配但是文件的最后一个。调用lex时我没有选项或命令行参数。我确定这与我如何使用文字字符串匹配有关,但我无法弄明白。

1 个答案:

答案 0 :(得分:1)

您应该阅读弹性手册,或者至少阅读patterns和以下"How the input is matched"部分的章节。从后者,我引用:

  

如果未找到匹配项,则执行默认规则:输入中的下一个字符被视为匹配并复制到标准输出。

这非常重要。您的匹配实际上停在您期望的位置,但以下文本与任何规则都不匹配,因此默认规则将其回显到输出。这种行为令人困惑,并且 - 在极少数情况下 - 不合需要。所以我建议您通过放置

来关闭它
%option nodefault

在flex输入的第一部分中。这会迫使你编写自己的后备规则,因为不匹配的字符会引发错误。

大多数现代正则表达式库允许“非贪婪”重复。 (但是,有些库并没有非常有效地实现这个功能。)但Flex没有。所以在Perl中,正则表达式\(.*?\)*?是非贪婪的匹配)将匹配第一个左括号和直到下一个右括号的字符,而\(.*\)将匹配第一个打开括号直到 last 关闭括号。在Flex中,两种模式都将匹配最后一个括号。

请注意\([^()]*\)是一个更有用的正则表达式:它将匹配第一个最里面的括号表达式:即,一个没有插入括号的开括号和右括号。因为我们明确说明了我们准备在中间匹配的内容,所以贪婪和非贪婪匹配之间没有区别;模式很精确。如果可能,这几乎总是一个更好的解决方案。但是,在反向匹配长度超过一个字符的情况下应用是很棘手的。

虽然总是可以制作一个与另一个正则表达式相反的正则表达式,但它并不总是那么容易。另一个合理的选择是使用flex "start conditions"。在该部分中,您将找到lexing C comments的示例,它与您尝试的内容有些类似。