(F)Lex:获取与规则不匹配的文本/获取默认输出

时间:2014-03-04 16:24:48

标签: c++ bison yacc lex flex-lexer

到目前为止,我已经阅读了很多关于(F)Lex的文章,但我找不到答案。 实际上我有2个问题,得到一个答案就足够了。

我有像:

这样的字符串
TOTO 123 CD123 RGF 32/FDS HGGH

对于我找到的每个标记,我将它放在一个向量中。例如,对于这个字符串,我得到一个这样的向量:

vector = TOTO, whitespace, CD, 123, whitespace, RGF, whitespace, 32, FDS, whitespace, HGGH

“/”与任何规则都不匹配,但是,当我到达它时,我想将它放在我的向量中并获得:

vector = TOTO, whitespace, CD, 123, whitespace, RGF, whitespace, 32, /, FDS, whitespace, HGGH

所以我的问题是:

1)当输入与任何规则不匹配时,是否有可能修改默认操作? (而不是在stdout上打印?)

2)如果不可能,怎么抓住这个?因为在这里,“/”是一个例子,但它可以是一切(%,C,3,Blabblabla等与我的规则不符),我不能把

 .*   { else();  }

因为Flex使用匹配最长字符串的正则表达式。我希望我的规则能够“排序”,而“。*”将是最后一个,就像改变Flex的“偏好”一样。

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

通常的方法是使用类似

的规则
.    { do_something_with_extra_char(*yytext); }

在规则的最后。这将匹配任何单个字符(除了换行符 - 您需要一个匹配换行符的规则)与任何其他规则不匹配。如果你有多个不匹配的字符,这个规则会多次触发,但通常都没问题。

答案 1 :(得分:1)

编辑:我认为Chris Dodd's answer更好。以下是两种替代解决方案。

一种解决方案是使用状态。当您读取一个无法识别的字符时,请进入另一个状态,并构建无法识别的标记。

%{
char str[1024];
int strUsed;
%}
%x UNRECOGNIZED
%%
{SOME_RULE} {/* do processing */ }
. {BEGIN(UNRECOGNIZED); str[0] = yytext[0]; strUsed = 1; }
<UNRECOGNIZED>{bad_input} { strcpy(str+strUsed, yytext); strUsed+=yyleng; }
<UNRECOGNIZED>{good_input} { str[strUsed] = 0; vector_add(str); BEGIN(INITIAL); }

如果编写正则表达式以匹配“坏”输入,则此解决方案很有效。另一个解决方案是慢慢建立不良字符,直到下一个有效匹配:

%{
char str[1024];
int strUsed = 0;
void goodMatch() {
  if(strUsed) {
    str[strUsed] = 0;
    vector_add(str);
    strUsed = 0;
  }
}
%}
%%
{SOME_RULE} { goodMatch(); /* do processing */ }
. {str[strUsed++] = yytext[0]; }

请注意,这需要您修改要在函数goodMatch的调用中添加的所有现有规则。

注意两种解决方案:如果使用静态大小的缓冲区,则必须确保不要在strcpy上溢出它。如果您最终使用动态大小的字符串,则必须确保正确清理内存。