]> git.saurik.com Git - bison.git/commitdiff
lalr1.cc: change symbols implementation
authorTheophile Ranquet <ranquet@lrde.epita.fr>
Fri, 21 Dec 2012 15:49:48 +0000 (16:49 +0100)
committerTheophile Ranquet <ranquet@lrde.epita.fr>
Fri, 11 Jan 2013 17:57:08 +0000 (18:57 +0100)
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<Exact> 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<Base> 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<by_state>, basic_symbol<by_type>.  The
name basic_symbol was chosen by similarity with basic_string and
basic_ostream.

* data/c++.m4 (symbol_base_type<Exact>): Remove, replace by...
(basic_symbol<Base>): 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<by_type>.
(stack_symbol_type): Is now basic_symbol<by_state>.
* data/lalr1.cc: Many adjustments.

data/c++.m4
data/lalr1.cc

index dd051e161b1802bd47b7e322a2fda07a53d3ca24..020160c9b85fc0d5f0a54253b50eca4ba1e56109 100644 (file)
@@ -157,25 +157,37 @@ m4_define([b4_public_types_declare],
     /// Token type.
     typedef token::yytokentype token_type;
 
-    /// A complete symbol, with its type.
-    template <typename Exact>
-    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 <typename Base>
+    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<symbol_type>
+    /// Type access provider for token (enum) based symbols.
+    struct by_type
     {
-      /// The parent class.
-      typedef symbol_base_type<symbol_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<by_type> 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 <typename Exact>
+  // basic_symbol.
+  template <typename Base>
   inline
-  ]b4_parser_class_name[::symbol_base_type<Exact>::symbol_base_type ()
-    : value()]b4_locations_if([
-    , location()])[
-  {
-  }]b4_locations_if([[
-
-  template <typename Exact>
+  ]b4_parser_class_name[::basic_symbol<Base>::basic_symbol ()
+    : value ()
+  {}
+]b4_locations_if([
+  template <typename Base>
   inline
-  ]b4_parser_class_name[::symbol_base_type<Exact>::symbol_base_type (const location_type& l)
-    : value()
-    , location(l)
-  {
-  }]])[
+  ]b4_parser_class_name[::basic_symbol<Base>::basic_symbol (const location_type& l)
+    : value ()
+    , location (l)
+  {}])[
 
-  template <typename Exact>
+  template <typename Base>
   inline
-  ]b4_parser_class_name[::symbol_base_type<Exact>::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<Base>::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 <typename Exact>
-  inline
-  const Exact&
-  ]b4_parser_class_name[::symbol_base_type<Exact>::self () const
-  {
-    return static_cast<const Exact&>(*this);
-  }
 
-  template <typename Exact>
+  template <typename Base>
   inline
-  Exact&
-  ]b4_parser_class_name[::symbol_base_type<Exact>::self ()
+  ]b4_parser_class_name[::basic_symbol<Base>::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<Exact&>(*this);
+    (void) v; /* FIXME: */
+    ]b4_variant_if([b4_symbol_variant([this->type_get ()], [value], [copy],
+                                      [v])],
+                   [value = v;])[
   }
 
-  template <typename Exact>
+  template <typename Base>
   inline
-  int
-  ]b4_parser_class_name[::symbol_base_type<Exact>::type_get () const
-  {
-    return self ().type_get_ ();
-  }
+  ]b4_parser_class_name[::basic_symbol<Base>::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 <typename Base>
   inline
-  ]b4_parser_class_name[::symbol_type::symbol_type ()
-    : super_type ()
-    , type ()
+  void
+  ]b4_parser_class_name[::basic_symbol<Base>::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).  */
index 91cb5cf09e7ba8366fae23b95e02fc89a1765adf..930119f1926ed003e95ef35eee6c8a85483ecd2c 100644 (file)
@@ -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 <typename Exact>
+    template <typename Base>
     void yy_print_ (std::ostream& yyo,
-                    const symbol_base_type<Exact>& yysym) const;
+                    const basic_symbol<Base>& 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 <typename Exact>
+    template <typename Base>
     inline void yy_destroy_ (const char* yymsg,
-                             symbol_base_type<Exact>& yysym) const;
+                             basic_symbol<Base>& yysym) const;
 
-    /// Element of the stack: a state and its attributes.
-    struct stack_symbol_type : symbol_base_type<stack_symbol_type>
+  private:
+    /// Type access provider for state based symbols.
+    struct by_state
     {
-      /// The parent class.
-      typedef symbol_base_type<stack_symbol_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<by_state> stack_symbol_type;
+
     /// Stack type.
     typedef stack<stack_symbol_type> 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 <typename Exact>
+  template <typename Base>
   void
   ]b4_parser_class_name[::yy_destroy_ (const char* yymsg,
-                                       symbol_base_type<Exact>& yysym) const
+                                       basic_symbol<Base>& yysym) const
   {
     if (yymsg)
       YY_SYMBOL_PRINT (yymsg, yysym);
@@ -551,10 +551,10 @@ m4_if(b4_prefix, [yy], [],
   }
 
 #if ]b4_api_PREFIX[DEBUG
-  template <typename Exact>
+  template <typename Base>
   void
   ]b4_parser_class_name[::yy_print_ (std::ostream& yyo,
-                                     const symbol_base_type<Exact>& yysym) const
+                                     const basic_symbol<Base>& 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[);]])[
           }