The symbol destructor is currently the only means to clear a symbol. Unfortunately during error recovery we might have to clear the lookahead, which is a local variable (yyla) that has not yet reached its end of scope.
Rather that duplicating the code to destroy a symbol, or rather than destroying and recreating yyla, let's provide a means to clear a symbol. Reported by Antonio Silva Correia, with an analysis from Michel d'Hooge. <http://savannah.gnu.org/support/?108481> * data/c++.m4, data/lalr1.cc (basis_symbol::clear, by_state::clear) (by_type::clear): New. (basic_symbol::~basic_symbol): Use clear. --- data/c++.m4 | 24 +++++++++++++++++++++++- data/lalr1.cc | 12 +++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/data/c++.m4 b/data/c++.m4 index f9ea7e9..8494d21 100644 --- a/data/c++.m4 +++ b/data/c++.m4 @@ -215,6 +215,9 @@ m4_define([b4_public_types_declare], /// Destroy the symbol. ~basic_symbol (); + /// Destroy contents, and record that is empty. + void clear (); + /// Whether empty. bool empty () const; @@ -247,6 +250,9 @@ m4_define([b4_public_types_declare], /// Constructor from (external) token numbers. by_type (kind_type t); + /// Record that this symbol is empty. + void clear (); + /// Steal the symbol type from \a that. void move (by_type& that); @@ -329,6 +335,14 @@ m4_define([b4_public_types_define], template <typename Base> inline ]b4_parser_class_name[::basic_symbol<Base>::~basic_symbol () + { + clear (); + } + + template <typename Base> + inline + void + ]b4_parser_class_name[::basic_symbol<Base>::clear () {]b4_variant_if([[ // User destructor. symbol_number_type yytype = this->type_get (); @@ -341,6 +355,7 @@ m4_define([b4_public_types_define], // Type destructor. ]b4_symbol_variant([[yytype]], [[value]], [[template destroy]])])[ + Base::clear (); } template <typename Base> @@ -381,10 +396,17 @@ m4_define([b4_public_types_define], inline void + ]b4_parser_class_name[::by_type::clear () + { + type = empty_symbol; + } + + inline + void ]b4_parser_class_name[::by_type::move (by_type& that) { type = that.type; - that.type = empty_symbol; + that.clear (); } inline diff --git a/data/lalr1.cc b/data/lalr1.cc index 1c3481f..9ab9421 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -288,6 +288,9 @@ b4_location_define])])[ /// Copy constructor. by_state (const by_state& other); + /// Record that this symbol is empty. + void clear (); + /// Steal the symbol type from \a that. void move (by_state& that); @@ -544,10 +547,17 @@ m4_if(b4_prefix, [yy], [], inline void + ]b4_parser_class_name[::by_state::clear () + { + state = empty_state; + } + + inline + void ]b4_parser_class_name[::by_state::move (by_state& that) { state = that.state; - that.state = empty_state; + that.clear (); } inline -- 2.2.1
