1

我正在尝试编写一个可识别(-! 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})但它没有用,有什么建议吗?

4

1 回答 1

2

您似乎认为这^意味着以下模式不应该匹配,但它意味着匹配一行的开头。在字符类内部^确实意味着除了字符类之外的所有内容,但在字符类之外它的含义完全不同。

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

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

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

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

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

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

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

于 2013-03-24T03:37:25.587 回答