lalr1.cc: provide %printer-based syntax-error messages.

	* data/c++.m4: .
	* data/lalr1.cc: .
	* data/variant.hh: .
diff --git a/data/c++.m4 b/data/c++.m4
index 92c2c5e..b8e1772 100644
--- a/data/c++.m4
+++ b/data/c++.m4
@@ -148,6 +148,16 @@
         [const semantic_type& v],
         b4_locations_if([const location_type& l]))[);
 
+      /// Release the memory allocated to members.
+      /// Reclaim the semantic value using the %destructor directive.
+      void clear ();
+
+      /// Print the semantic value using the %printer directive.
+      std::ostream& print (std::ostream& o) const;
+
+      /// Print everything about the symbol (type, value, location).
+      std::ostream& dump (std::ostream& o) const;
+
       /// Return this with its exact type.
       const Exact& self () const;
       Exact& self ();
@@ -155,6 +165,11 @@
       /// Return the type of this symbol.
       int type_get () const;
 
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+      /// The name for the type.
+      const char *type_name () const;
+#endif
+
       /// The semantic value.
       semantic_type value;]b4_locations_if([
 
@@ -186,7 +201,7 @@
       inline int type_get_ () const;
 
       /// Its token.
-      inline token_type token () const;
+      token_type token () const;
     };
 ]b4_symbol_constructor_declare])
 
@@ -220,6 +235,53 @@
   }
 
   template <typename Exact>
+  void
+  ]b4_parser_class_name[::symbol_base_type<Exact>::clear ()
+  {
+    int yytype = type_get ();
+    // User destructor.
+    switch (yytype)
+      {
+]b4_symbol_foreach([b4_symbol_destructor])dnl
+[       default:
+          break;
+      }]b4_variant_if([
+
+    // Type destructor.
+  b4_symbol_variant([[yytype]], [[value]], [[template destroy]])])[
+  }
+
+  template <typename Exact>
+  std::ostream&
+  ]b4_parser_class_name[::symbol_base_type<Exact>::print (std::ostream& yystream) const
+  {
+#define debug_stream() yystream
+    switch (type_get ())
+      {
+]b4_symbol_foreach([b4_symbol_printer])dnl
+[       default:
+	  break;
+      }
+#undef debug_stream
+    return yystream;
+  }
+
+  template <typename Exact>
+  std::ostream&
+  ]b4_parser_class_name[::symbol_base_type<Exact>::dump (std::ostream& yystream) const
+  {
+    int yytype = type_get ();
+    yystream << (yytype < yyntokens_ ? "token" : "nterm")
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+             << ' ' << type_name ()
+#endif
+             << " ("]b4_locations_if([
+             << location << ": "])[;
+    print (yystream);
+    return yystream << ')';
+  }
+
+  template <typename Exact>
   const Exact&
   ]b4_parser_class_name[::symbol_base_type<Exact>::self () const
   {
@@ -240,6 +302,14 @@
     return self ().type_get_ ();
   }
 
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+  template <typename Exact>
+  const char *
+  ]b4_parser_class_name[::symbol_base_type<Exact>::type_name () const
+  {
+    return ]b4_parser_class_name[::yytname_[type_get ()];
+  }
+#endif
   // symbol_type.
   ]b4_parser_class_name[::symbol_type::symbol_type ()
     : super_type ()
diff --git a/data/lalr1.cc b/data/lalr1.cc
index 5ad3328..0737258 100644
--- a/data/lalr1.cc
+++ b/data/lalr1.cc
@@ -29,7 +29,7 @@
 ])
 
 # b4_integral_parser_table_define(TABLE-NAME, CONTENT, COMMENT)
-# ---------------------------------------------
+# -------------------------------------------------------------
 # Define "parser::yy<TABLE-NAME>_" which contents is CONTENT.
 m4_define([b4_integral_parser_table_define],
 [  const b4_int_type_for([$2])
@@ -100,10 +100,10 @@
 m4_define([b4_symbol_action],
 [b4_symbol_if([$1], [has_$2],
 [m4_pushdef([b4_dollar_dollar],
-    [b4_symbol_value_template([yysym.value],
+    [b4_symbol_value_template([value],
                               b4_symbol_if([$1], [has_type],
                                            [b4_symbol([$1], [type])]))])dnl
-m4_pushdef([b4_at_dollar], [yysym.location])dnl
+m4_pushdef([b4_at_dollar], [location])dnl
       b4_symbol_case_([$1])
 b4_syncline([b4_symbol([$1], [$2_line])], ["b4_symbol([$1], [$2_file])"])
         b4_symbol([$1], [$2])
@@ -147,8 +147,9 @@
 ]b4_percent_code_get([[requires]])[
 
 ]b4_parse_assert_if([#include <cassert>])[
-#include <string>
 #include <iostream>
+#include <string>
+#include <sstream>
 #include "stack.hh"
 
 ]b4_namespace_open[
@@ -268,7 +269,7 @@
 #endif]b4_error_verbose_if([
 
     /// Convert the symbol name \a n to a form suitable for a diagnostic.
-    static std::string yytnamerr_ (const char *n);])[
+    static std::string yytnamerr_ (const std::string& n);])[
 
 #if YYDEBUG
 ]b4_integral_parser_table_declare([rline], [b4_rline],
@@ -365,8 +366,7 @@
 ]b4_parse_param_vars[
   };
 
-]b4_lex_symbol_if([b4_yytranslate_define
-b4_public_types_define])[
+]b4_lex_symbol_if([b4_yytranslate_define])[
 ]b4_namespace_close[
 
 ]b4_percent_define_flag_if([[global_tokens_and_yystype]],
@@ -465,12 +465,12 @@
      apostrophe, a comma, or backslash (other than backslash-backslash).
      YYSTR is taken from yytname.  */
   std::string
-  ]b4_parser_class_name[::yytnamerr_ (const char *yystr)
+  ]b4_parser_class_name[::yytnamerr_ (const std::string& yystr)
   {
-    if (*yystr == '"')
+    if (yystr[0] == '"')
       {
         std::string yyr = "";
-        char const *yyp = yystr;
+        char const *yyp = yystr.c_str ();
 
         for (;;)
           switch (*++yyp)
@@ -497,6 +497,8 @@
   }
 ]])[
 
+]b4_lex_symbol_if([b4_public_types_define])[
+
   /// Build a parser object.
   ]b4_parser_class_name::b4_parser_class_name[ (]b4_parse_param_decl[)]m4_ifset([b4_parse_param], [
     :])[
@@ -546,21 +548,9 @@
   ]b4_parser_class_name[::yy_destroy_ (const char* yymsg,
                                        symbol_base_type<Exact>& yysym) const
   {
-    int yytype = yysym.type_get ();
-    YYUSE (yymsg);
     if (yymsg)
       YY_SYMBOL_PRINT (yymsg, yysym);
-
-    // User destructor.
-    switch (yytype)
-      {
-]b4_symbol_foreach([b4_symbol_destructor])dnl
-[       default:
-          break;
-      }]b4_variant_if([
-
-    // Type destructor.
-  b4_symbol_variant([[yytype]], [[yysym.value]], [[template destroy]])])[
+    yysym.clear ();
   }
 
 #if YYDEBUG
@@ -569,17 +559,7 @@
   ]b4_parser_class_name[::yy_print_ (std::ostream& yyo,
                                      const symbol_base_type<Exact>& yysym) const
   {
-    int yytype = yysym.type_get ();
-    yyo << (yytype < yyntokens_ ? "token" : "nterm")
-        << ' ' << yytname_[yytype] << " ("]b4_locations_if([
-        << yysym.location << ": "])[;
-    switch (yytype)
-      {
-]b4_symbol_foreach([b4_symbol_printer])dnl
-[       default:
-	  break;
-      }
-    yyo << ')';
+    yysym.dump (yyo);
   }
 #endif
 
@@ -1021,10 +1001,17 @@
         }
         // Argument number.
         size_t yyi = 0;
+        // The unexpected token.  Try to print its value.
+        std::ostringstream yyo;
+        yyla.print (yyo);
         for (char const* yyp = yyformat; *yyp; ++yyp)
           if (yyp[0] == '%' && yyp[1] == 's' && yyi < yycount)
           {
-            yyres += yytnamerr_ (yyarg[yyi++]);
+            if (!yyi && !yyo.str ().empty ())
+              yyres += yyo.str ();
+            else
+              yyres += yytnamerr_ (yyarg[yyi]);
+            ++yyi;
             ++yyp;
           }
           else
diff --git a/data/variant.hh b/data/variant.hh
index ae26f5b..10ce56c 100644
--- a/data/variant.hh
+++ b/data/variant.hh
@@ -231,7 +231,7 @@
 # these SYMBOL-NUMBERS.  Use at class-level.
 m4_define([b4_symbol_constructor_declare_],
 [b4_symbol_if([$1], [is_token], [b4_symbol_if([$1], [has_id],
-[    static inline
+[    static // inline
     symbol_type
     make_[]b4_symbol_([$1], [id]) (dnl
 b4_args(b4_symbol_if([$1], [has_type],