[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
- inconsistant %destructor usage between union- and variant-based parsers,
Alexandre Duret-Lutz <=