Reputation: 183
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?
Upvotes: 2
Views: 1809
Reputation: 241671
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"
).
Upvotes: 1
Reputation: 183
@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!!!
Upvotes: 1