سؤال

I have a problem with Bison's error handling. I have the following grammar (I have cut out only the relevant part). Flex sends its tokens to Bison and returns the terminal symbol "KW_CONFIGPARAM" if the string "ConfigParam" is parsed. IDENT is a pointer to a C++ string object.

statementlist   : statement ';'               { $$ = new string("statementlist"); }
                | statementlist statement ';' { $$ = new string("statementlist"); }
;
statement       : KW_CONFIGPARAM IDENT        { $$ = new string("statement"); /* use $2, IDENT is used in main program */ }
;

I have the following destructor specified for strings like IDENT.

%destructor { printf ("free at line %d: %s\n",@$.first_line, $$->c_str()); delete($$); }

Now I have the following input. The first line is valid, the second line isn't (identifier is missing):

ConfigParam p;
ConfigParam;

Output:

In input 2:12 - 2:12 : syntax error
free at line 2: p
free at line 1: statementlist

Because of an error in the second line, Bison complains, returns a syntax error and calls the destructors of all objects on the parsing stack. Now I don't understand why the destructor of identifier "p" from the first line is called? It belongs to the first line and it was successfully parsed. The problem is that p is used in the main program and should be not removed by Bison.

If I choose as an (invalid) statement an arbitrary string ("foo") p is not removed by Bison.

ConfigParam p;
foo;

In input 2:1 - 2:3 : syntax error
free at line 1: statementlist
free at line 2: foo

Why this works?

هل كانت مفيدة؟

المحلول

It's not easy to tell the exact problem without seeing more of your file, but it's certainly not the case that

The first line was successfully parsed and should be popped off the stack

The stack at the point of the error looks like this:

statementlist KW_CONFIGPARAM

where statementlist was created by the reduction of the first line, as reported by bison.

You don't seem to be specifying a value for statement_list; if you excerpt is literal, then it will have been compiled as though it had been written:

statementlist   : statement ';'                 {$0 = $1;}

I can't tell what the value corresponding to statement was, but it is certainly conceivable that it includes the string "p". That depends on what you set $0 to during { /* do some stuff, create a new ConfigParam object */ }.

(Moved from a comment once it became evident that it's somewhat close to the right answer.) My other idea is this: Perhaps you've made all of your terminals and non-terminals have a type which triggers that destructor. And maybe your lexer does not modify yylval when it returns KW_CONFIGPARM. In that case, the bison parser cannot know that yylval is irrelevant, so it will use the left over yylval (which is a pointer to "p").

نصائح أخرى

@rici: Thanks a lot, you point me to the right direction. I have written

%token <str>    STRING    IDENT       NUMBER
                KW_CONFIGPARAM

but correct is of course...

%token <str>    STRING    IDENT       NUMBER
%token          KW_CONFIGPARAM

Arrghhh!

@rici: You have made my day!!!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top