尝试编程 "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" 还有什么意思,但我希望这是对那个问题的回答。