到目前为止,我已经阅读了很多关于(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的“偏好”一样。
有什么想法吗?
答案 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
上溢出它。如果您最终使用动态大小的字符串,则必须确保正确清理内存。