Hi

The manual states that user-defined %destructors are called only on a
specific list of discarded symbols:

| “Discarded symbols” are the following:
|
|  • stacked symbols popped during the first phase of error recovery,
|  • incoming terminals during the second phase of error recovery,
|  • the current lookahead and the entire stack (except the current
|    right-hand side symbols) when the parser returns immediately, and
|  • the current lookahead and the entire stack (including the current
|    right-hand side symbols) when the C++ parser (‘lalr1.cc’) catches
|    an exception in ‘parse’,
|  • the start symbol, when the parser succeeds.

However it seems that this list is augmented to include all
stacked symbols when C++ variants are used.  That looks wrong to me.
Is this really intended?


Context: I'm trying to convert a union-based C++ parser to
variant-based one.

I used to do something like:

| %language "C++"
| // [...]
| %union
| {
|   std::string* str;
|   const spot::fnode* ltl;
|   unsigned num;
| }
| 
| %destructor { delete $$; } <str>
| %destructor { $$->destroy(); } <ltl>
| // [...]
| %token <str> rule1 rule2...
| %token <ltl> rule3 rule4...
| %token <num> rule5 rule6...

and I'm now changing that code to read

| %language "C++"
| %define api.value.type variant
| // [...]
| %destructor { $$->destroy(); } <const spot::fnode*>
| // [...]
| %token <std::string> rule1 rule2...
| %token <const spot::fnode*> rule3 rule4...
| %token <num> rule5 rule6...

I'm happy that I do not have to deal with the memory management of
strings anymore.  However this fnode* object is still something I want
to handle using a pointer (because of the pecular way I construct it).

Unfortunately, my new variant-based parser fails because of many extra
and unexpected calls to the above destroy() method.

Everytime the parser pops a basic_symbol from its stack as part of a
normal reduce operation, it calls ~basic_symbol() which in turns calls
basic_symbol::clear() which unexpectedly calls the used defined
destructor :-(

During reduce operations, I was expecting to see the standard
destructors of the types being used in the variant to be called (so
popping a basic_symbol that contains a std::string calls
std::string::~string(), and popping a basic_symbol that contains a
pointer or unsigned does nothing), but not the user-defined %destructors
(as per the documentation).


Alexandre

Reply via email to