【发布时间】:2013-01-03 07:44:24
【问题描述】:
当flex-lexer 生成的扫描程序遇到文件结尾时,它会丢失之前规则中yymore() 调用留下的yytext[] 的内容。只有在重新定义 YY_INPUT() 时才会发生这种错误行为。
这可能是 flex 中的一个错误,但似乎缺少某些东西——flex 扫描器定义在重新定义 YY_INPUT() 时应该提供的其他东西。
我已经在 Ubuntu 12.04.1 和 Windows 7 上使用 flex 2.5.35 进行了测试。在这两个系统上,如果要扫描的文本是通过 @ 的显式定义提供的,则扫描仪会在 EOF 处丢失 yytext[] 内容987654327@.
下面是一个示例 flex 扫描器 (flex-test.l),它旨在读取和打印 HTML cmets,即使最后一条评论未终止。当它的输入是通过yy_scan_string() 提供时它可以正常工作,但是当它的输入是由YY_INPUT() 的显式定义提供时它会失败。在示例代码中,#if 用于在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
}
【问题讨论】:
标签: flex-lexer flex-lexer