flex中的规则排除

时间:2013-03-23 22:28:43

标签: flex-lexer

我正在尝试编写一个flex文件,该文件将(-! comment !-)识别为一个名为comment的标记。以下是我的档案:

%{
#include <stdio.h>

void showToken(char* name);
void error();
void enter();

int lineNum=1;
%}

%option yylineno
%option noyywrap

whitespace  ([\t ])
enter       ([\n])
startcomment (\(\-\!)
endcomment (\!\-\))
comment (^\!\-\))

%%

{startcomment}{comment}*{endcomment} showToken("COMMENT");
{enter} enter();
{whitespace}
.   error();

%%

void showToken(char* name){
    printf("%d %s %s %d% \n",lineNum,name, yytext); 
}

void enter(){
    lineNum++;
}

void error(){
printf("%d error %s \n",lineNum,yytext);
}

但我输入简单(-! comment !-)时失败,此文件确实识别(-!!-),但无法识别我的comment规则。我确实尝试用comment (^{endcomment})替换它,但它没有用,有什么建议吗?

1 个答案:

答案 0 :(得分:2)

您似乎认为^表示以下模式不匹配,但它表示匹配行的开头。在角色类^内部确实意味着除了角色类之外的所有东西,但在角色类之外它的含义完全不同。

回答你的问题以寻找替代方案。您的问题类似于C-comment /* comment */。以下表达式与C-comment匹配:

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

或者更直观(如果您愿意),您可以使用子自动机:

%x comment
%%
"/*"              { BEGIN(comment); }
<comment>(.|"\n") { /* Skip */ }
<comment>"*/"     { BEGIN(INITIAL); }
%%

我会将其作为练习将其应用于您的评论风格。将!-)作为评论的结束,使第一个解决方案变得更复杂。

请注意,通常第二种解决方案是首选,因为它不会导致使用大缓冲区。第一个解决方案将创建一个包含完整注释的缓冲区(可能很大),而第二个解决方案的缓冲区要求最多为两个字符。

维护行号的最简单方法是使用%option yylineno作为flex,然后跟踪变量int yylineno中的行号。或者,您可以计算yytext中新行的数量。在第二个解决方案中,您可以拆分第二个规则,为"\n"创建一个单独的案例,并在那里计算行号。