bug-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

inconsistant %destructor usage between union- and variant-based parsers


From: Alexandre Duret-Lutz
Subject: inconsistant %destructor usage between union- and variant-based parsers
Date: Wed, 16 Mar 2022 00:05:08 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux)

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

[Prev in Thread] Current Thread [Next in Thread]