0
votes

I get a "debug assertion failed... Expression stream != NULL" error when running a flex / bison program. Here is the relevant code, at the top of the lex file:

%x include_state

%{
    #define MAX_INCLUDE_DEPTH 10
    YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
    int include_stack_ptr = 0;
%}

... and later in the lex file:

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); }

... the text it is trying to pass is:

include "hello.txt";

I am trying to add "include" functionality to my program. I am using win flex and win bison. (A side issue: how do I split lines of code in the lex file?)

1
You you don't have any accepted answer? aren't answers good enough for you?Iharob Al Asimi
can you format the lex file content please?Iharob Al Asimi
It is formatted now. I would like to format it in my code but win flex does not like it if I split the code on different lines.gornvix

1 Answers

2
votes

The debug assertion is the Windows runtime's way of telling you that you tried reading or writing a FILE* which is NULL, which would imply that the fopen failed.

In your code:

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);

If the fopen fails, you produce a nice error message, but don't seem to do anything with it: you neither print it out nor do you avoid switching to the new buffer with a NULL value for yyin.

So it seems most likely that your fopen failed and you proceeded to try to read from NULL.

But there is another problem with your code.

The flex start condition is not part of the buffer. It is global. Switching to a new buffer does not save the start condition (unless you save it somewhere). Similarly, unless you did the work to save the start condition, there is no way to restore it when you switch back to the original buffer. In short, since you were in start condition include_state when you switch buffers, you are still in that start condition when you start to tokenize the included file, which means that the string at the beginning of that file (if it starts with [[:alnum:] ]) will be used as a filename to include. That may well be why your fopen fails.

I suspect that the other obvious problem is a cut-and-paste issue. You have:

<include_state>[a-zA-Z0-9 ]+
{

which is a pattern with an empty action, followed by a free-standing action (which will never get executed). The action must start on the same line as the pattern; flex will keep reading the action until it finds the matching }, so you only need to put the { on the same line as the pattern:

<include_state>[a-zA-Z0-9 ]+     {

I'm not sure what else you mean by "split the code on different lines", but I hope that is the answer to that query.