]> git.saurik.com Git - bison.git/blobdiff - data/lalr1.cc
Use variants to support objects as semantic values.
[bison.git] / data / lalr1.cc
index 433c62b3ce2eb7eb5307f81ca271c4b29e7f3f58..de2c1defb06cec3fc121aa77b193a8b5ef4de8ea 100644 (file)
@@ -1,28 +1,94 @@
 # C++ skeleton for Bison
 
-# Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
 
-# This program is free software; you can redistribute it and/or modify
+# This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# the Free Software Foundation, either version 3 of the License, or
 # (at your option) any later version.
-
+#
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
-
+#
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301  USA
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 m4_include(b4_pkgdatadir/[c++.m4])
 
+# How the semantic value is extracted when using variants.
+b4_variant_if([
+  # b4_symbol_value(VAL, [TYPE])
+  # ----------------------------
+  m4_define([b4_symbol_value],
+  [m4_ifval([$2],
+            [$1.as<$2>()],
+            [$1])])
+]) # b4_variant_if
+
+
+# b4_symbol_action_(SYMBOL-TAG, SYMBOL-NUM, SYMBOL-TYPENAME)
+# ----------------------------------------------------------
+# Invoke b4_dollar_dollar(SYMBOL_TYPENAME) for each symbol.
+m4_define([b4_symbol_action_],
+[m4_ifval($3,
+[      case $2: // $1
+        b4_dollar_dollar($@);
+       break;
+])])
+
+
+# b4_symbol_variant(YYTYPE, YYVAL, ACTION)
+# ----------------------------------------
+# Run some ACTION ("build", or "destroy") on YYVAL of symbol type
+# YYTYPE.
+m4_define([b4_symbol_variant],
+[m4_pushdef([b4_dollar_dollar],
+            [$2.$3<$][3>()])dnl
+  switch ($1)
+    {
+m4_map([b4_symbol_action_], m4_defn([b4_type_names]))
+     default:
+       break;
+    }
+m4_popdef([b4_dollar_dollar])dnl
+])
+
+
+# _b4_char_sizeof_counter
+# -----------------------
+# A counter used by _b4_char_sizeof_dummy to create fresh symbols.
+m4_define([_b4_char_sizeof_counter],
+[0])
+
+# _b4_char_sizeof_dummy
+# ---------------------
+# At each call return a new C++ identifier.
+m4_define([_b4_char_sizeof_dummy],
+[m4_define([_b4_char_sizeof_counter], m4_incr(_b4_char_sizeof_counter))dnl
+dummy[]_b4_char_sizeof_counter])
+
+
+# b4_char_sizeof(SYMBOL-TAG, SYMBOL-NUM, SYMBOL-TYPENAME)
+# -------------------------------------------------------
+# To be mapped on the list of type names to produce:
+#
+#    char dummy1[sizeof(type_name_1)];
+#    char dummy2[sizeof(type_name_2)];
+#
+# for defined type names.
+# $3 is doubly-quoted, do not quote it again.
+m4_define([b4_char_sizeof],
+[m4_ifval($3,
+[
+      char _b4_char_sizeof_dummy@{sizeof($3)@}; // $1])dnl
+])
+
+
 m4_define([b4_parser_class_name],
-          [b4_get_percent_define([[parser_class_name]])])
-m4_define([b4_namespace],
-          [b4_get_percent_define([[namespace]])])
+          [b4_percent_define_get([[parser_class_name]])])
 
 # The header is mandatory.
 b4_defines_if([],
@@ -38,7 +104,7 @@ m4_divert_push(0)dnl
 b4_defines_if(
 [@output(b4_spec_defines_file@)
 b4_copyright([Skeleton interface for Bison LALR(1) parsers in C++],
-  [2002, 2003, 2004, 2005, 2006])
+             [2002, 2003, 2004, 2005, 2006, 2007, 2008])
 dnl FIXME: This is wrong, we want computed header guards.
 [
 /* C++ LALR(1) parser skeleton written by Akim Demaille.  */
@@ -46,17 +112,61 @@ dnl FIXME: This is wrong, we want computed header guards.
 #ifndef PARSER_HEADER_H
 # define PARSER_HEADER_H
 
-]b4_get_percent_code([[requires]])[
+]b4_percent_code_get([[requires]])[
 
 #include <string>
 #include <iostream>
 #include "stack.hh"
 
-namespace ]b4_namespace[
-{
+]b4_namespace_open[
   class position;
   class location;
-}
+]b4_variant_if([[
+  /// A char[S] buffer to store and retrieve objects.
+  ///
+  /// Sort of a variant, but does not keep track of the nature
+  /// of the stored data, since that knowledge is available
+  /// via the current state.
+  template <size_t S>
+  struct variant
+  {
+    /// Instantiate a \a T in here.
+    template <typename T>
+    inline void
+    build()
+    {
+      new (buffer) T;
+    }
+
+    /// Destroy the stored \a T.
+    template <typename T>
+    inline void
+    destroy()
+    {
+      reinterpret_cast<T&>(buffer).~T();
+    }
+
+    /// Accessor to a built \a T.
+    template <typename T>
+    inline T&
+    as()
+    {
+      return reinterpret_cast<T&>(buffer);
+    }
+
+    /// Const accessor to a built \a T (for %printer).
+    template <typename T>
+    inline const T&
+    as() const
+    {
+      return reinterpret_cast<const T&>(buffer);
+    }
+
+    /// A buffer large enough to store any of the semantic values.
+    char buffer[S];
+  };
+]])[
+]b4_namespace_close[
 
 #include "location.hh"
 
@@ -97,27 +207,34 @@ do {                                                       \
 } while (false)
 #endif
 
-namespace ]b4_namespace[
-{
+]b4_namespace_open[
 
   /// A Bison parser.
   class ]b4_parser_class_name[
   {
   public:
-    /// Symbol semantic values.
 #ifndef YYSTYPE
-]m4_ifdef([b4_stype],
+]b4_variant_if(
+[    /// An auxiliary type to compute the largest semantic type.
+    union union_type
+    {]m4_map([b4_char_sizeof], m4_defn([b4_type_names]))[
+    };
+
+    /// Symbol semantic values.
+    typedef variant<sizeof(union_type)> semantic_type;],
+[    /// Symbol semantic values.
+m4_ifdef([b4_stype],
 [    union semantic_type
-b4_user_stype
-       ;],
+    {b4_user_stype
+    };],
 [m4_if(b4_tag_seen_flag, 0,
 [[    typedef int semantic_type;]],
-[[    typedef YYSTYPE semantic_type;]])])[
+[[    typedef YYSTYPE semantic_type;]])])])[
 #else
     typedef YYSTYPE semantic_type;
 #endif
     /// Symbol locations.
-    typedef ]b4_get_percent_define([[location_type]])[ location_type;
+    typedef ]b4_percent_define_get([[location_type]])[ location_type;
     /// Tokens.
     struct token
     {
@@ -134,6 +251,7 @@ b4_user_stype
     /// \returns  0 iff parsing succeeded.
     virtual int parse ();
 
+#if YYDEBUG
     /// The current debugging stream.
     std::ostream& debug_stream () const;
     /// Set the current debugging stream.
@@ -145,6 +263,7 @@ b4_user_stype
     debug_level_type debug_level () const;
     /// Set the current debugging level.
     void set_debug_level (debug_level_type l);
+#endif
 
   private:
     /// Report a syntax error.
@@ -286,24 +405,24 @@ b4_error_verbose_if([, int tok])[);
     static const token_number_type yyundef_token_;
 ]b4_parse_param_vars[
   };
-}
+]b4_namespace_close[
 
-]m4_ifval(b4_get_percent_define([[global_tokens_and_yystype]]),
+]b4_percent_define_flag_if([[global_tokens_and_yystype]],
 [b4_token_defines(b4_tokens)
 
 #ifndef YYSTYPE
  /* Redirection for backward compatibility.  */
-# define YYSTYPE b4_namespace::b4_parser_class_name::semantic_type
+# define YYSTYPE b4_namespace_ref::b4_parser_class_name::semantic_type
 #endif
 ])
-b4_get_percent_code([[provides]])[]dnl
+b4_percent_code_get([[provides]])[]dnl
 
 [#endif /* ! defined PARSER_HEADER_H */]
 ])dnl
 @output(b4_parser_file_name@)
 b4_copyright([Skeleton implementation for Bison LALR(1) parsers in C++],
-  [2002, 2003, 2004, 2005, 2006])
-b4_get_percent_code([[top]])[]dnl
+             [2002, 2003, 2004, 2005, 2006, 2007, 2008])
+b4_percent_code_get([[top]])[]dnl
 m4_if(b4_prefix, [yy], [],
 [
 // Take the name prefix into account.
@@ -317,7 +436,7 @@ b4_defines_if([[
 
 /* User implementation prologue.  */
 ]b4_user_post_prologue
-b4_get_percent_code[]dnl
+b4_percent_code_get[]dnl
 
 [#ifndef YY_
 # if YYENABLE_NLS
@@ -371,12 +490,15 @@ do {                                      \
 
 #endif /* !YYDEBUG */
 
+#define yyerrok                (yyerrstatus_ = 0)
+#define yyclearin      (yychar = yyempty_)
+
 #define YYACCEPT       goto yyacceptlab
 #define YYABORT                goto yyabortlab
 #define YYERROR                goto yyerrorlab
+#define YYRECOVERING()  (!!yyerrstatus_)
 
-namespace ]b4_namespace[
-{
+]b4_namespace_open[
 #if YYERROR_VERBOSE
 
   /* Return YYSTR after stripping away unnecessary quotes and
@@ -538,7 +660,7 @@ namespace ]b4_namespace[
     /// Location of the lookahead.
     location_type yylloc;
     /// The locations where the error started and ended.
-    location yyerror_range[2];
+    location_type yyerror_range[2];
 
     /// $$.
     semantic_type yyval;
@@ -630,7 +752,6 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
 
     /* Discard the token being shifted.  */
     yychar = yyempty_;
-
     yysemantic_stack_.push (yylval);
     yylocation_stack_.push (yylloc);
 
@@ -655,7 +776,11 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
   | yyreduce -- Do a reduction.  |
   `-----------------------------*/
   yyreduce:
-    yylen = yyr2_[yyn];
+    yylen = yyr2_[yyn];]b4_variant_if([
+    /* Variants are always initialized to an empty instance of the
+       correct type. The default $$=$1 rule is NOT applied when using
+       variants */
+    ]b4_symbol_variant([[yyr1_@{yyn@}]], [yyval], [build])[],[
     /* If YYLEN is nonzero, implement the default value of the action:
        `$$ = $1'.  Otherwise, use the top of the stack.
 
@@ -663,9 +788,9 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
        This behavior is undocumented and Bison
        users should not rely upon it.  */
     if (yylen)
-      yyval = yysemantic_stack_[yylen - 1];
+      yyval = yysemantic_stack_@{yylen - 1@};
     else
-      yyval = yysemantic_stack_[0];
+      yyval = yysemantic_stack_@{0@};])[
 
     {
       slice<location_type, location_stack_type> slice (yylocation_stack_, yylen);
@@ -675,14 +800,14 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
     switch (yyn)
       {
        ]b4_user_actions[
-       default: break;
+       default:
+          break;
       }
     YY_SYMBOL_PRINT ("-> $$ =", yyr1_[yyn], &yyval, &yyloc);
 
     yypop_ (yylen);
     yylen = 0;
     YY_STACK_PRINT ();
-
     yysemantic_stack_.push (yyval);
     yylocation_stack_.push (yyloc);
 
@@ -793,7 +918,7 @@ b4_error_verbose_if([, yytoken])[));
 
     /* Shift the error token.  */
     YY_SYMBOL_PRINT ("Shifting", yystos_[yyn],
-                  &yysemantic_stack_[0], &yylocation_stack_[0]);
+                    &yysemantic_stack_[0], &yylocation_stack_[0]);
 
     yystate = yyn;
     goto yynewstate;
@@ -1011,7 +1136,7 @@ b4_error_verbose_if([, int tok])[)
     int yynrhs = yyr2_[yyrule];
     /* Print the symbols being reduced, and their result.  */
     *yycdebug_ << "Reducing stack by rule " << yyrule - 1
-              << " (line " << yylno << "), ";
+              << " (line " << yylno << "):" << std::endl;
     /* The symbols being reduced.  */
     for (int yyi = 0; yyi < yynrhs; yyi++)
       YY_SYMBOL_PRINT ("   $" << yyi + 1 << " =",
@@ -1049,21 +1174,20 @@ b4_error_verbose_if([, int tok])[)
   const unsigned int ]b4_parser_class_name[::yyuser_token_number_max_ = ]b4_user_token_number_max[;
   const ]b4_parser_class_name[::token_number_type ]b4_parser_class_name[::yyundef_token_ = ]b4_undef_token_number[;
 
-} // namespace ]b4_namespace[
+]b4_namespace_close[
 
 ]b4_epilogue
 dnl
 @output(b4_dir_prefix[]stack.hh@)
 b4_copyright([Stack handling for Bison parsers in C++],
-  [2002, 2003, 2004, 2005, 2006])[
+             [2002, 2003, 2004, 2005, 2006, 2007, 2008])[
 
 #ifndef BISON_STACK_HH
 # define BISON_STACK_HH
 
 #include <deque>
 
-namespace ]b4_namespace[
-{
+]b4_namespace_open[
   template <class T, class S = std::deque<T> >
   class stack
   {
@@ -1149,7 +1273,8 @@ namespace ]b4_namespace[
     const S& stack_;
     unsigned int range_;
   };
-}
+]b4_namespace_close[
 
-#endif // not BISON_STACK_HH]
+#endif // not BISON_STACK_HH[]dnl
+]
 m4_divert_pop(0)