当flex-lexer生成的扫描器遇到文件结尾时,它会丢失之前规则中调用yytext[]
留下的内容。yymore()
这种错误行为只有在YY_INPUT()
重新定义时才会发生。
这可能是 flex 中的一个错误,但似乎缺少一些东西——flex 扫描器定义在重新定义YY_INPUT()
.
我已经在 Ubuntu 12.04.1 和 Windows 7 上使用 flex 2.5.35 进行了测试。在这两个系统上,yytext[]
如果要扫描的文本是通过YY_INPUT()
.
下面是一个flex-test.l
用于读取和打印 HTML 注释的示例 flex 扫描器 ( ),即使最后一条注释未终止。当它的输入是通过 提供时它可以正常工作yy_scan_string()
,但是当它的输入是由 的显式定义提供时它会失败YY_INPUT()
。在示例代码中,#if
's 用于在yy_scan_string()
和YY_INPUT()
实现之间进行选择。具体来说,预期输出:
Begin comment: <!--
More comment: <!--incomplete
EOF comment: <!--incomplete
如果扫描仪是使用构建的,则会出现
flex --nounistd flex-test.l && gcc -DREDEFINE_YY_INPUT=0 lex.yy.c
但是如果扫描仪是使用
flex --nounistd flex-test.l && gcc -DREDEFINE_YY_INPUT=1 lex.yy.c
(将=0更改为=1),然后出现此错误输出:
Begin comment: <!--
More comment: <!--incomplete
EOF comment:
请注意最后一行输出中没有任何注释文本。
这是示例代码:
/* A scanner demonstrating bad interaction between yymore() and <<EOF>>
* when YY_INPUT() is redefined: specifically, yytext[] content is lost. */
%{
#include <stdio.h>
int yywrap(void) { return 1; }
#if REDEFINE_YY_INPUT
#define MIN(a,b) ((a)<(b) ? (a) : (b))
const char *source_chars;
size_t source_length;
#define set_data(s) (source_chars=(s), source_length=strlen(source_chars))
size_t get_data(char *buf, size_t request_size) {
size_t copy_size = MIN(request_size, source_length);
memcpy(buf, source_chars, copy_size);
source_chars += copy_size;
source_length -= copy_size;
return copy_size;
}
#define YY_INPUT(buf,actual,ask) ((actual)=get_data(buf,ask))
#endif
%}
%x COMM
%%
"<!--" printf("Begin comment: %s\n", yytext); yymore(); BEGIN(COMM);
<COMM>[^-]+ printf("More comment: %s\n", yytext); yymore();
<COMM>. printf("More comment: %s\n", yytext); yymore();
<COMM>--+\ *[>] printf("End comment: %s\n", yytext); BEGIN(INITIAL);
<COMM><<EOF>> printf("EOF comment: %s\n", yytext); BEGIN(INITIAL); return 0;
. printf("Other: %s\n", yytext);
<<EOF>> printf("EOF: %s\n", yytext); return 0;
%%
int main(int argc, char **argv) {
char *text = "<!--incomplete";
#if REDEFINE_YY_INPUT
set_data(text);
yylex();
#else
YY_BUFFER_STATE state = yy_scan_string(text);
yylex();
yy_delete_buffer(state);
#endif
}