From: Theophile Ranquet Date: Fri, 21 Dec 2012 15:49:48 +0000 (+0100) Subject: lalr1.cc: change symbols implementation X-Git-Tag: v2.7.90~191 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/1dbaf37f5cd0bc0e7c6a91b8996ae974c8d2cdc1 lalr1.cc: change symbols implementation A "symbol" groups together the symbol type (INT, PLUS, etc.), its possible semantic value, and its optional location. The type is needed to access the value, as it is stored as a variant/union. There are two kinds of symbols. "symbol_type" are "external symbols": they have type, value and location, and are returned by yylex. "stack_symbol_type" are "internal symbols", they group state number, value and location, and are stored in the parser stack. The type of the symbol is computed from the state number. The class template symbol_base_type factors the code common to stack_symbol_type and symbol_type. It uses the Curiously Recurring Template pattern so that we can always (static_) downcast to the exact type. symbol_base_type features value and location, and delegates the handling of the type to its parameter. When trying to generalize the support for variant, a significant issue was revealed: because stack_symbol_type and symbol_type _derive_ from symbol_base_type, the type/state member is defined _after_ the value and location. In C++ the order of the definition of the members defines the order in which they are initialized, things go backward: the value is initialized _before_ the type. This is wrong, since the type is needed to access the value. Therefore, we need another means to factor the common code, one that ensures the order of the members. The idea is simple: define two (base) classes that code the symbol type ("by_type" codes it by its type, and "by_state" by the state number). Define basic_symbol as the class template that provides value and location support. Make it _derive_ from its parameter, by_type or by_state. Then define stack_symbol_type and symbol_type as basic_symbol, basic_symbol. The name basic_symbol was chosen by similarity with basic_string and basic_ostream. * data/c++.m4 (symbol_base_type): Remove, replace by... (basic_symbol): which derives from its parameter, one of... (by_state, by_type): which provide means to retrieve the actual type of symbol. (symbol_type): Is now basic_symbol. (stack_symbol_type): Is now basic_symbol. * data/lalr1.cc: Many adjustments. --- diff --git a/data/c++.m4 b/data/c++.m4 index dd051e16..020160c9 100644 --- a/data/c++.m4 +++ b/data/c++.m4 @@ -157,25 +157,37 @@ m4_define([b4_public_types_declare], /// Token type. typedef token::yytokentype token_type; - /// A complete symbol, with its type. - template - struct symbol_base_type + /// A complete symbol. + /// + /// Expects its Base type to provide access to the symbol type + /// via type_get(). + /// + /// Provide access to semantic value]b4_locations_if([ and location])[. + template + struct basic_symbol : Base { /// Default constructor. - inline symbol_base_type (); + inline basic_symbol (); +]b4_locations_if([ + /// Constructor. + inline basic_symbol (const location_type& l);])[ - /// Constructor.]b4_locations_if([ - inline symbol_base_type (const location_type& l);])[ - inline symbol_base_type (]b4_join( - [const semantic_type& v], + /// Copy constructor. + inline basic_symbol (const basic_symbol& other); + + /// Constructor for valueless symbols. + inline basic_symbol (]b4_join( + [typename Base::value_type t], b4_locations_if([const location_type& l]))[); - /// Return this with its exact type. - const Exact& self () const; - Exact& self (); + /// Constructor for symbols with semantic value. + inline basic_symbol (]b4_join( + [typename Base::value_type t], + [const semantic_type& v], + b4_locations_if([const location_type& l]))[); - /// Return the type of this symbol. - int type_get () const; + /// Destructive move, \a s is emptied. + inline void move (basic_symbol& s); /// The semantic value. semantic_type value;]b4_locations_if([ @@ -184,36 +196,33 @@ m4_define([b4_public_types_declare], location_type location;])[ }; - /// External form of a symbol: its type and attributes. - struct symbol_type : symbol_base_type + /// Type access provider for token (enum) based symbols. + struct by_type { - /// The parent class. - typedef symbol_base_type super_type; - /// Default constructor. - inline symbol_type (); + inline by_type (); - /// Destructive move, \a s is emptied. - inline void move (symbol_type& s); - - /// Constructor for tokens with semantic value. - inline symbol_type (]b4_join([token_type t], - [const semantic_type& v], - b4_locations_if([const location_type& l]))[); + /// Copy constructor. + inline by_type (const by_type& other); - /// Constructor for valueless tokens. - inline symbol_type (]b4_join([token_type t], - b4_locations_if([const location_type& l]))[); + /// Constructor. + inline by_type (token_type t); /// The symbol type. int type; - /// The symbol type. - inline int type_get_ () const; + /// The type (corresponding to \a type). + inline int type_get () const; /// The token. inline token_type token () const; + + typedef token_type value_type; }; + + /// "External" symbols: returned by the scanner. + typedef basic_symbol symbol_type; + ]b4_symbol_constructor_declare]) @@ -221,110 +230,102 @@ m4_define([b4_public_types_declare], # ---------------------- # Provide the implementation needed by the public types. m4_define([b4_public_types_define], -[[ inline +[[inline ]b4_parser_class_name[::syntax_error::syntax_error (]b4_locations_if([const location_type& l, ])[const std::string& m) : std::runtime_error (m)]b4_locations_if([ , location (l)])[ {} - // symbol_base_type. - template + // basic_symbol. + template inline - ]b4_parser_class_name[::symbol_base_type::symbol_base_type () - : value()]b4_locations_if([ - , location()])[ - { - }]b4_locations_if([[ - - template + ]b4_parser_class_name[::basic_symbol::basic_symbol () + : value () + {} +]b4_locations_if([ + template inline - ]b4_parser_class_name[::symbol_base_type::symbol_base_type (const location_type& l) - : value() - , location(l) - { - }]])[ + ]b4_parser_class_name[::basic_symbol::basic_symbol (const location_type& l) + : value () + , location (l) + {}])[ - template + template inline - ]b4_parser_class_name[::symbol_base_type::symbol_base_type (]b4_join( - [const semantic_type& v], - b4_locations_if([const location_type& l]))[) - : value(v)]b4_locations_if([ - , location(l)])[ + ]b4_parser_class_name[::basic_symbol::basic_symbol (const basic_symbol& other) + : Base (other) + , value ()]b4_locations_if([ + , location (other.location)])[ { + ]b4_variant_if([b4_symbol_variant([other.type_get ()], [value], [copy], + [other.value])], + [value = other.value;])[ } - template - inline - const Exact& - ]b4_parser_class_name[::symbol_base_type::self () const - { - return static_cast(*this); - } - template + template inline - Exact& - ]b4_parser_class_name[::symbol_base_type::self () + ]b4_parser_class_name[::basic_symbol::basic_symbol (]b4_join( + [typename Base::value_type t], + [const semantic_type& v], + b4_locations_if([const location_type& l]))[) + : Base (t) + , value ()]b4_locations_if([ + , location (l)])[ { - return static_cast(*this); + (void) v; /* FIXME: */ + ]b4_variant_if([b4_symbol_variant([this->type_get ()], [value], [copy], + [v])], + [value = v;])[ } - template + template inline - int - ]b4_parser_class_name[::symbol_base_type::type_get () const - { - return self ().type_get_ (); - } + ]b4_parser_class_name[::basic_symbol::basic_symbol (]b4_join( + [typename Base::value_type t], + b4_locations_if([const location_type& l]))[) + : Base (t)]b4_locations_if([ + , location (l)])[ + {} - // symbol_type. + template inline - ]b4_parser_class_name[::symbol_type::symbol_type () - : super_type () - , type () + void + ]b4_parser_class_name[::basic_symbol::move (basic_symbol& s) { + this->type = s.type_get ();]b4_locations_if([ + location = s.location;])[ + ]b4_variant_if([b4_symbol_variant([s.type_get ()], [value], [build], + [s.value])], + [value = s.value;])[ } + // by_type. inline - ]b4_parser_class_name[::symbol_type::symbol_type (]b4_join( - [token_type t], - b4_locations_if([const location_type& l]))[) - : super_type (]b4_locations_if([l])[) - , type (yytranslate_ (t)) - { - } + ]b4_parser_class_name[::by_type::by_type () + : type () + {} inline - ]b4_parser_class_name[::symbol_type::symbol_type (]b4_join( - [token_type t], - [const semantic_type& v], - b4_locations_if([const location_type& l]))[) - : super_type (v]b4_locations_if([, l])[) - , type (yytranslate_ (t)) - { - } + ]b4_parser_class_name[::by_type::by_type (const by_type& other) + : type (other.type) + {} inline - void - ]b4_parser_class_name[::symbol_type::move (symbol_type& s) - { - ]b4_variant_if([b4_symbol_variant([[s.type]], [value], [build], [s.value])], - [value = s.value;])[ - type = s.type;]b4_locations_if([ - location = s.location;])[ - } + ]b4_parser_class_name[::by_type::by_type (token_type t) + : type (yytranslate_ (t)) + {} inline int - ]b4_parser_class_name[::symbol_type::type_get_ () const + ]b4_parser_class_name[::by_type::type_get () const { return type; } ]b4_token_ctor_if([[ inline ]b4_parser_class_name[::token_type - ]b4_parser_class_name[::symbol_type::token () const + ]b4_parser_class_name[::by_type::token () const { // YYTOKNUM[NUM] -- (External) token number corresponding to the // (internal) symbol number NUM (which must be that of a token). */ diff --git a/data/lalr1.cc b/data/lalr1.cc index 91cb5cf0..930119f1 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -254,40 +254,44 @@ b4_location_define])])[ /// \brief Display a symbol type, value and location. /// \param yyo The output stream. /// \param yysym The symbol. - template + template void yy_print_ (std::ostream& yyo, - const symbol_base_type& yysym) const; + const basic_symbol& yysym) const; #endif /// \brief Reclaim the memory associated to a symbol. /// \param yymsg Why this token is reclaimed. /// If null, print nothing. /// \param s The symbol. - template + template inline void yy_destroy_ (const char* yymsg, - symbol_base_type& yysym) const; + basic_symbol& yysym) const; - /// Element of the stack: a state and its attributes. - struct stack_symbol_type : symbol_base_type + private: + /// Type access provider for state based symbols. + struct by_state { - /// The parent class. - typedef symbol_base_type super_type; - /// Default constructor. - inline stack_symbol_type (); + inline by_state (); /// Constructor. - inline stack_symbol_type (]b4_join([state_type s], - [const semantic_type& v], - b4_locations_if([const location_type& l]))[); + inline by_state (state_type s); + + /// Copy constructor. + inline by_state (const by_state& other); /// The state. state_type state; /// The type (corresponding to \a state). - inline int type_get_ () const; + inline int type_get () const; + + typedef state_type value_type; }; + /// "Internal" symbol: element of the stack. + typedef basic_symbol stack_symbol_type; + /// Stack type. typedef stack stack_type; @@ -506,33 +510,29 @@ m4_if(b4_prefix, [yy], [], ]b4_token_ctor_if([], [b4_public_types_define])[ - // stack_symbol_type. - ]b4_parser_class_name[::stack_symbol_type::stack_symbol_type () - : super_type () - , state () - { - } + // by_state. + ]b4_parser_class_name[::by_state::by_state () + : state () + {} - ]b4_parser_class_name[::stack_symbol_type::stack_symbol_type (]b4_join( - [state_type s], - [const semantic_type& v], - b4_locations_if([const location_type& l]))[) - : super_type (v]b4_locations_if([, l])[) - , state (s) - { - } + ]b4_parser_class_name[::by_state::by_state (const by_state& other) + : state (other.state) + {} + + ]b4_parser_class_name[::by_state::by_state (state_type s) + : state (s) + {} int - ]b4_parser_class_name[::stack_symbol_type::type_get_ () const + ]b4_parser_class_name[::by_state::type_get () const { return yystos_[state]; } - - template + template void ]b4_parser_class_name[::yy_destroy_ (const char* yymsg, - symbol_base_type& yysym) const + basic_symbol& yysym) const { if (yymsg) YY_SYMBOL_PRINT (yymsg, yysym); @@ -551,10 +551,10 @@ m4_if(b4_prefix, [yy], [], } #if ]b4_api_PREFIX[DEBUG - template + template void ]b4_parser_class_name[::yy_print_ (std::ostream& yyo, - const symbol_base_type& yysym) const + const basic_symbol& yysym) const { std::ostream& yyoutput = yyo; YYUSE (yyoutput); @@ -579,16 +579,14 @@ m4_if(b4_prefix, [yy], [], if (m) YY_SYMBOL_PRINT (m, sym); ]b4_variant_if( -[[ yystack_.push (stack_symbol_type (]b4_join( - [s], - [semantic_type()], - b4_locations_if([sym.location]))[)); - ]b4_symbol_variant([[yystos_[s]]], [[yystack_[0].value]], - [build], [sym.value])], -[[ yystack_.push (stack_symbol_type (]b4_join( - [s], - [sym.value], - b4_locations_if([sym.location]))[));]])[ +[[ + stack_symbol_type ss (]b4_join([s], + [sym.value], b4_locations_if([sym.location]))[); + ]b4_symbol_variant([sym.type_get ()], [sym.value], [destroy], [])[; + yystack_.push (ss); +]], +[[ yystack_.push (stack_symbol_type (]b4_join([s], + [sym.value], b4_locations_if([sym.location]))[));]])[ } void @@ -597,12 +595,12 @@ m4_if(b4_prefix, [yy], [], if (m) YY_SYMBOL_PRINT (m, s); ]b4_variant_if( -[[ yystack_.push (stack_symbol_type (]b4_join( - [s.state], - [semantic_type()], - b4_locations_if([s.location]))[)); - ]b4_symbol_variant([[yystos_[s.state]]], [[yystack_[0].value]], - [build], [s.value])], +[[ + stack_symbol_type ss (]b4_join([s.state], + [s.value], b4_locations_if([s.location]))[); + ]b4_symbol_variant([s.type_get ()], [s.value], [destroy], [])[; + yystack_.push (ss); +]], [ yystack_.push (s);])[ } @@ -730,7 +728,7 @@ b4_dollar_popdef])[]dnl YYCDEBUG << "Reading a token: "; try {]b4_token_ctor_if([[ - symbol_type yylookahead = ]b4_lex[; + symbol_type yylookahead (]b4_lex[); yyla.move (yylookahead);]], [[ yyla.type = yytranslate_ (]b4_lex[);]])[ }