尝试编程 "include" 功能时,flex / bison 程序中的调试断言失败错误
Debug assertion failed error in flex / bison program when trying to program "include" functionality
当 运行 一个 flex / bison 程序时,我得到一个 "debug assertion failed... Expression stream != NULL" 错误。这是 lex 文件顶部的相关代码:
%x include_state
%{
#define MAX_INCLUDE_DEPTH 10
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
int include_stack_ptr = 0;
%}
... 之后在 lex 文件中:
include[ \t]*\" { BEGIN(include_state); }
<include_state>[a-zA-Z0-9 ]+ {
if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
{
fprintf(stderr, "Includes nested too deeply");
exit(1);
}
include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
yyin = fopen(yytext, "r" );
if (!yyin)
sprintf(err_str, "Error opening include file: %s", yytext);
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner),
yyscanner);
}
<include_state>\"; { BEGIN(INITIAL); }
...它试图传递的文本是:
include "hello.txt";
我正在尝试向我的程序添加 "include" 功能。我正在使用 win flex 和 win bison。 (附带问题:如何拆分 lex 文件中的代码行?)
调试断言是 Windows 运行时告诉您您尝试读取或写入 FILE*
的方式,它是 NULL
,这意味着 fopen
失败。
在您的代码中:
yyin = fopen(yytext, "r" );
if (!yyin)
sprintf(err_str, "Error opening include file: %s", yytext);
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner),
yyscanner);
如果 fopen
失败,你会产生一个很好的错误消息,但似乎没有对它做任何事情:你既没有打印出来,也没有避免使用 [= 切换到新缓冲区14=] yyin
的值。
所以您的 fopen
很可能失败了,您继续尝试从 NULL
读取。
但是你的代码还有一个问题。
flex
开始条件不是缓冲区的一部分。它是全球性的。切换到新缓冲区 不会 保存开始条件(除非您将其保存在某处)。同样,除非您完成保存开始条件的工作,否则当您切换回原始缓冲区时无法恢复它。简而言之,由于您在切换缓冲区时处于开始条件 include_state
,因此当您开始标记包含的文件时,您仍处于该开始条件,这意味着该文件开头的字符串(如果它开始with [[:alnum:] ]
) 将用作要包含的文件名。这很可能就是您的 fopen
失败的原因。
我怀疑另一个明显的问题是剪切和粘贴问题。你有:
<include_state>[a-zA-Z0-9 ]+
{
这是一个带有空动作的模式,后面跟着一个独立的动作(永远不会被执行)。动作必须start与模式在同一行; flex
会一直读取动作,直到找到匹配的 }
,所以你只需要将 {
和模式放在同一行:
<include_state>[a-zA-Z0-9 ]+ {
我不确定 "split the code on different lines" 还有什么意思,但我希望这是对那个问题的回答。
当 运行 一个 flex / bison 程序时,我得到一个 "debug assertion failed... Expression stream != NULL" 错误。这是 lex 文件顶部的相关代码:
%x include_state
%{
#define MAX_INCLUDE_DEPTH 10
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
int include_stack_ptr = 0;
%}
... 之后在 lex 文件中:
include[ \t]*\" { BEGIN(include_state); }
<include_state>[a-zA-Z0-9 ]+ {
if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
{
fprintf(stderr, "Includes nested too deeply");
exit(1);
}
include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
yyin = fopen(yytext, "r" );
if (!yyin)
sprintf(err_str, "Error opening include file: %s", yytext);
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner),
yyscanner);
}
<include_state>\"; { BEGIN(INITIAL); }
...它试图传递的文本是:
include "hello.txt";
我正在尝试向我的程序添加 "include" 功能。我正在使用 win flex 和 win bison。 (附带问题:如何拆分 lex 文件中的代码行?)
调试断言是 Windows 运行时告诉您您尝试读取或写入 FILE*
的方式,它是 NULL
,这意味着 fopen
失败。
在您的代码中:
yyin = fopen(yytext, "r" );
if (!yyin)
sprintf(err_str, "Error opening include file: %s", yytext);
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner),
yyscanner);
如果 fopen
失败,你会产生一个很好的错误消息,但似乎没有对它做任何事情:你既没有打印出来,也没有避免使用 [= 切换到新缓冲区14=] yyin
的值。
所以您的 fopen
很可能失败了,您继续尝试从 NULL
读取。
但是你的代码还有一个问题。
flex
开始条件不是缓冲区的一部分。它是全球性的。切换到新缓冲区 不会 保存开始条件(除非您将其保存在某处)。同样,除非您完成保存开始条件的工作,否则当您切换回原始缓冲区时无法恢复它。简而言之,由于您在切换缓冲区时处于开始条件 include_state
,因此当您开始标记包含的文件时,您仍处于该开始条件,这意味着该文件开头的字符串(如果它开始with [[:alnum:] ]
) 将用作要包含的文件名。这很可能就是您的 fopen
失败的原因。
我怀疑另一个明显的问题是剪切和粘贴问题。你有:
<include_state>[a-zA-Z0-9 ]+
{
这是一个带有空动作的模式,后面跟着一个独立的动作(永远不会被执行)。动作必须start与模式在同一行; flex
会一直读取动作,直到找到匹配的 }
,所以你只需要将 {
和模式放在同一行:
<include_state>[a-zA-Z0-9 ]+ {
我不确定 "split the code on different lines" 还有什么意思,但我希望这是对那个问题的回答。