当我使用 yymore() 时在 EOF 出现 flex 错误 "end of buffer missed"
flex error "end of buffer missed" at EOF when I use yymore()
我正在编写一个 flex 程序来处理字符串常量。
当输入文件在字符串中遇到 EOF 时,我想 return 一个 ERROR 标记。
文件遇到 EOF 并打印 "ERROR" 后出现以下错误:
fatal flex scanner internal error--end of buffer missed
这是我的代码:(可以重现此错误的简化版本)
%option noyywrap
#define ERROR 300
#define STRING 301
char *text;
%x str
%%
\" {BEGIN(str); yymore();}
<str>\" {BEGIN(INITIAL); text=yytext; return STRING;}
<str>. {yymore();}
<str><<EOF>> {BEGIN(INITIAL); return ERROR;}
%%
int main(){
int token;
while((token=yylex())!=0){
if(token==STRING)
printf("string:%s\n",text);
else if(token==ERROR)
printf("ERROR\n");
}
return 0;
}
当我删除yymore()
函数调用时,错误消失,打印"ERROR"后程序正常退出。
我想知道为什么会这样,我想在不删除的情况下解决它 yymore()
。
您收到 EOF 指示后无法继续词法扫描,因此您的 <str><<EOF>>
规则不正确,这就是错误消息所指示的。
与任何未定义的行为一样,在某些情况下,错误可能会导致任意行为,包括按照您错误地认为会起作用的方式工作。 (对于您的 flex 版本,如果您不使用 yymore
,就会发生这种情况。)
您需要确保在收到EOF 后不会重新进入扫描程序循环。例如,您可以 return 一个错误代码,指示无法读取更多令牌(与可重新启动的错误指示相反,如果需要的话)。或者您可以为词法分析器设置一个标志,使其立即return 发生不可恢复的错误后为 0。
这是第二种策略的示例(只是规则,因为没有其他变化):
%%
/* indented code before the first pattern is inserted
* at the beginning of yylex, allowing declaration of
* variables. The fatal_error flag is declared static,
* since this is not a reentrable lexer. If it were
* reentrable, we'd put the flag in the lexer context
* (as part of the "extra data"), which would be a lot cleaner.
*/
static int fatal_error = 0;
/* If the error we last returned was fatal, we do
* not re-enter the scanner loop; we just return EOF
*/
if (fatal_error) {
fatal_error = 0; /* reset the flag for reuse */
return 0;
}
\" {BEGIN(str); yymore();}
<str>\" {BEGIN(INITIAL); text=yytext; return STRING;}
<str>. {yymore();}
<str><<EOF>> {BEGIN(INITIAL);
fatal_error = 1; /* Set the fatal error flag */
return ERROR;}
%%
另一种可能的解决方案是使用 "push parser",其中 yylex
使用每个标记调用解析器,而不是相反。 bison
支持这种风格,往往方便很多;特别是,它允许一个动作向解析器发送多个令牌,在这种情况下,这将消除对静态本地标志的需要。
我正在编写一个 flex 程序来处理字符串常量。
当输入文件在字符串中遇到 EOF 时,我想 return 一个 ERROR 标记。
文件遇到 EOF 并打印 "ERROR" 后出现以下错误:
fatal flex scanner internal error--end of buffer missed
这是我的代码:(可以重现此错误的简化版本)
%option noyywrap
#define ERROR 300
#define STRING 301
char *text;
%x str
%%
\" {BEGIN(str); yymore();}
<str>\" {BEGIN(INITIAL); text=yytext; return STRING;}
<str>. {yymore();}
<str><<EOF>> {BEGIN(INITIAL); return ERROR;}
%%
int main(){
int token;
while((token=yylex())!=0){
if(token==STRING)
printf("string:%s\n",text);
else if(token==ERROR)
printf("ERROR\n");
}
return 0;
}
当我删除yymore()
函数调用时,错误消失,打印"ERROR"后程序正常退出。
我想知道为什么会这样,我想在不删除的情况下解决它 yymore()
。
您收到 EOF 指示后无法继续词法扫描,因此您的 <str><<EOF>>
规则不正确,这就是错误消息所指示的。
与任何未定义的行为一样,在某些情况下,错误可能会导致任意行为,包括按照您错误地认为会起作用的方式工作。 (对于您的 flex 版本,如果您不使用 yymore
,就会发生这种情况。)
您需要确保在收到EOF 后不会重新进入扫描程序循环。例如,您可以 return 一个错误代码,指示无法读取更多令牌(与可重新启动的错误指示相反,如果需要的话)。或者您可以为词法分析器设置一个标志,使其立即return 发生不可恢复的错误后为 0。
这是第二种策略的示例(只是规则,因为没有其他变化):
%%
/* indented code before the first pattern is inserted
* at the beginning of yylex, allowing declaration of
* variables. The fatal_error flag is declared static,
* since this is not a reentrable lexer. If it were
* reentrable, we'd put the flag in the lexer context
* (as part of the "extra data"), which would be a lot cleaner.
*/
static int fatal_error = 0;
/* If the error we last returned was fatal, we do
* not re-enter the scanner loop; we just return EOF
*/
if (fatal_error) {
fatal_error = 0; /* reset the flag for reuse */
return 0;
}
\" {BEGIN(str); yymore();}
<str>\" {BEGIN(INITIAL); text=yytext; return STRING;}
<str>. {yymore();}
<str><<EOF>> {BEGIN(INITIAL);
fatal_error = 1; /* Set the fatal error flag */
return ERROR;}
%%
另一种可能的解决方案是使用 "push parser",其中 yylex
使用每个标记调用解析器,而不是相反。 bison
支持这种风格,往往方便很多;特别是,它允许一个动作向解析器发送多个令牌,在这种情况下,这将消除对静态本地标志的需要。