bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2] glr2.cc: fork glr.cc to a c++ version


From: Valentin Tolmer
Subject: [PATCH 1/2] glr2.cc: fork glr.cc to a c++ version
Date: Wed, 26 Aug 2020 16:57:34 +0200

This is a fork of glr.cc to be c++-first instead of a wrapper around
glr.c.
---
 NEWS                    |   13 +
 data/local.mk           |    1 +
 data/skeletons/bison.m4 |    2 +-
 data/skeletons/c++.m4   |    1 -
 data/skeletons/c.m4     |    7 +-
 data/skeletons/glr2.cc  | 3306 +++++++++++++++++++++++++++++++++++++++
 src/reader.c            |    1 +
 tests/actions.at        |    8 +-
 tests/c++.at            |    1 +
 tests/calc.at           |    1 +
 tests/conflicts.at      |    2 +-
 tests/input.at          |    1 +
 tests/local.at          |    2 +-
 tests/regression.at     |    1 +
 tests/scanner.at        |    2 +-
 tests/synclines.at      |    4 +-
 tests/types.at          |    2 +-
 17 files changed, 3344 insertions(+), 11 deletions(-)
 create mode 100644 data/skeletons/glr2.cc

diff --git a/NEWS b/NEWS
index 68bbbb81..6ef3132e 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,19 @@ GNU Bison NEWS

 * Noteworthy changes in release ?.? (????-??-??) [?]

+** Changes
+
+  A new version of the generated C++ GLR parser was added as "glr2.cc". It is
+  forked from the existing glr.c/cc parser, with the objective of making it a
+  more modern, truly C++ parser (instead of a C++ wrapper around a C parser).
+  Down the line, the goal is to support `std::variant` and maybe share code
+  with lalr1.cc.
+
+  The current parser should be identical in terms of interface, functionality
+  and performance to "glr.cc". To try it out, simply use
+
+  %skeleton "glr2.cc"
+

 * Noteworthy changes in release 3.7.1 (2020-08-02) [stable]

diff --git a/data/local.mk b/data/local.mk
index 21106451..1ad9d235 100644
--- a/data/local.mk
+++ b/data/local.mk
@@ -28,6 +28,7 @@ dist_skeletons_DATA =                           \
   data/skeletons/c.m4                           \
   data/skeletons/glr.c                          \
   data/skeletons/glr.cc                         \
+  data/skeletons/glr2.cc                        \
   data/skeletons/java-skel.m4                   \
   data/skeletons/java.m4                        \
   data/skeletons/lalr1.cc                       \
diff --git a/data/skeletons/bison.m4 b/data/skeletons/bison.m4
index 8c5fbdf5..0591de5c 100644
--- a/data/skeletons/bison.m4
+++ b/data/skeletons/bison.m4
@@ -402,7 +402,7 @@ b4_define_flag_if([yacc])               # Whether
POSIX Yacc is emulated.
 # b4_glr_cc_if([IF-TRUE], [IF-FALSE])
 # -----------------------------------
 m4_define([b4_glr_cc_if],
-          [m4_if(b4_skeleton, ["glr.cc"], $@)])
+          [m4_if(m4_bregexp(b4_skeleton, [^"glr2?.cc"$]), [0], $@)])


 ## --------- ##
diff --git a/data/skeletons/c++.m4 b/data/skeletons/c++.m4
index b7a2a3a8..bd267f69 100644
--- a/data/skeletons/c++.m4
+++ b/data/skeletons/c++.m4
@@ -109,7 +109,6 @@ b4_percent_define_default([[api.filename.type]],
[[const std::string]])
 # Make it a warning for those who used betas of Bison 3.0.
 b4_percent_define_default([[api.namespace]], m4_defn([b4_prefix]))

-b4_percent_define_default([[global_tokens_and_yystype]], [[false]])
 b4_percent_define_default([[define_location_comparison]],
                           [m4_if(b4_percent_define_get([[filename_type]]),
                                  [std::string], [[true]], [[false]])])
diff --git a/data/skeletons/c.m4 b/data/skeletons/c.m4
index 2452ed2e..894af042 100644
--- a/data/skeletons/c.m4
+++ b/data/skeletons/c.m4
@@ -127,7 +127,12 @@ m4_define([b4_lex],
 # b4_user_args
 # ------------
 m4_define([b4_user_args],
-[m4_ifset([b4_parse_param], [, b4_args(b4_parse_param)])])
+[m4_ifset([b4_parse_param], [, b4_user_args_no_comma])])
+
+# b4_user_args_no_comma
+# ------------
+m4_define([b4_user_args_no_comma],
+[m4_ifset([b4_parse_param], [b4_args(b4_parse_param)])])


 # b4_user_formals
diff --git a/data/skeletons/glr2.cc b/data/skeletons/glr2.cc
new file mode 100644
index 00000000..dbdc84e5
--- /dev/null
+++ b/data/skeletons/glr2.cc
@@ -0,0 +1,3306 @@
+# C++ GLR skeleton for Bison
+
+# Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc.
+
+# 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 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, see <http://www.gnu.org/licenses/>.
+
+# b4_tname_if(TNAME-NEEDED, TNAME-NOT-NEEDED)
+# -------------------------------------------
+m4_define([b4_tname_if],
+[m4_case(b4_percent_define_get([[parse.error]]),
+         [verbose],         [$1],
+         [b4_token_table_if([$1],
+                            [$2])])])
+
+# This skeleton produces a C++ class that encapsulates a C glr parser.
+# This is in order to reduce the maintenance burden.  The glr.c
+# skeleton is clean and pure enough so that there are no real
+# problems.  The C++ interface is the same as that of lalr1.cc.  In
+# fact, glr.c can replace yacc.c without the user noticing any
+# difference, and similarly for glr.cc replacing lalr1.cc.
+#
+# The passing of parse-params
+#
+#   The additional arguments are stored as members of the parser
+#   object, yyparser.  The C routines need to carry yyparser
+#   throughout the C parser; that's easy: make yyparser an
+#   additional parse-param.  But because the C++ skeleton needs to
+#   know the "real" original parse-param, we save them
+#   (b4_parse_param_orig).  Note that b4_parse_param is overquoted
+#   (and c.m4 strips one level of quotes).  This is a PITA, and
+#   explains why there are so many levels of quotes.
+#
+# The locations
+#
+#   We use location.cc just like lalr1.cc, but because glr.c stores
+#   the locations in a union, the position and location classes
+#   must not have a constructor.  Therefore, contrary to lalr1.cc, we
+#   must not define "b4_location_constructors".  As a consequence the
+#   user must initialize the first positions (in particular the
+#   filename member).
+
+# We require a pure interface.
+m4_define([b4_pure_flag], [1])
+
+m4_include(b4_skeletonsdir/[c++.m4])
+b4_bison_locations_if([m4_include(b4_skeletonsdir/[location.cc])])
+
+m4_define([b4_parser_class],
+          [b4_percent_define_get([[api.parser.class]])])
+
+# Save the parse parameters.
+m4_define([b4_parse_param_orig], m4_defn([b4_parse_param]))
+
+# b4_parse_param_wrap
+# -------------------
+# New ones.
+m4_ifset([b4_parse_param],
+[m4_define([b4_parse_param_wrap],
+           [[b4_namespace_ref::b4_parser_class[& yyparser], [[yyparser]]],]
+m4_defn([b4_parse_param]))],
+[m4_define([b4_parse_param_wrap],
+           [[b4_namespace_ref::b4_parser_class[& yyparser], [[yyparser]]]])
+])
+
+# b4_yy_symbol_print_define
+# -------------------------
+# Bypass the default implementation to generate the "yy_symbol_print"
+# and "yy_symbol_value_print" functions.
+m4_define([b4_yy_symbol_print_define],
+[[/*--------------------.
+| Print this symbol.  |
+`--------------------*/
+
+static void
+yy_symbol_print (FILE *,
]b4_namespace_ref::b4_parser_class[::symbol_kind_type yytoken,
+                 const
]b4_namespace_ref::b4_parser_class[::semantic_type
*yyvaluep]b4_locations_if([[,
+                 const
]b4_namespace_ref::b4_parser_class[::location_type
*yylocationp]])[]b4_user_formals[)
+{
+]b4_parse_param_use[]dnl
+[  yyparser.yy_symbol_print_ (yytoken, yyvaluep]b4_locations_if([,
yylocationp])[);
+}
+]])[
+
+# Hijack the initial action to initialize the locations.
+]b4_bison_locations_if([m4_define([b4_initial_action],
+[yylloc.initialize ();]m4_ifdef([b4_initial_action], [
+m4_defn([b4_initial_action])]))])[
+
+# Hijack the post prologue to declare yyerror.
+]m4_append([b4_post_prologue],
+[b4_syncline([@oline@], [@ofile@])dnl
+[static void
+yyerror (]b4_locations_if([[const
]b4_namespace_ref::b4_parser_class[::location_type *yylocationp,
+         ]])[]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param),
+         ])[const std::string& msg);]])[
+
+
+]m4_define([b4_define_symbol_kind],
+[m4_format([#define %-15s %s],
+           b4_symbol($][1, kind_base),
+           b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol($1,
kind_base))
+])
+
+# b4_glr_cc_setup
+# ---------------
+# Setup redirections for glr.c: Map the names used in c.m4 to the ones used
+# in c++.m4.
+m4_define([b4_glr_cc_setup],
+[[#ifndef ]b4_api_PREFIX[STYPE
+# define ]b4_api_PREFIX[STYPE
]b4_namespace_ref[::]b4_parser_class[::semantic_type
+#endif
+#ifndef ]b4_api_PREFIX[LTYPE
+# define ]b4_api_PREFIX[LTYPE
]b4_namespace_ref[::]b4_parser_class[::location_type
+#endif
+typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind_type
yysymbol_kind_t;
+]])
+# b4_glr_cc_cleanup
+# -----------------
+# Remove redirections for glr.c.
+m4_define([b4_glr_cc_cleanup],
+[[#undef ]b4_symbol(-2, [id])[
+#undef ]b4_symbol(0, [id])[
+#undef ]b4_symbol(1, [id])[
+#undef ]b4_symbol_prefix[YYEMPTY
+#undef ]b4_symbol_prefix[YYerror
+#undef ]b4_symbol_prefix[YYEOF
+#undef ]b4_symbol_prefix[YYUNDEF
+]])
+
+# b4_shared_declarations(hh|cc)
+# -----------------------------
+# Declaration that might either go into the header (if --defines, $1 = hh)
+# or in the implementation file.
+m4_define([b4_shared_declarations],
+[m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
+b4_percent_code_get([[requires]])[
+#include <algorithm>
+#include <cstddef> // ptrdiff_t
+#include <iostream>
+#include <stdexcept>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+]b4_cxx_portability[
+]m4_ifdef([b4_location_include],
+          [[# include ]b4_location_include])[
+]b4_variant_if([b4_variant_includes])[
+
+]b4_attribute_define[
+]b4_cast_define[
+]b4_null_define[
+
+template <typename Parameter>
+class StrongIndexAlias
+{
+ public:
+  static StrongIndexAlias create(std::ptrdiff_t value) {
+    StrongIndexAlias result;
+    result.value_ = value;
+    return result;
+  }
+
+  std::ptrdiff_t const& get() const {return value_; }
+
+  size_t uget() const {return YY_CAST(size_t, value_); }
+
+  StrongIndexAlias operator+(std::ptrdiff_t other) const {
+    return StrongIndexAlias(get() + other);
+  }
+
+  void operator+=(std::ptrdiff_t other) {
+    value_ += other;
+  }
+
+  StrongIndexAlias operator-(std::ptrdiff_t other) {
+    return StrongIndexAlias(get() - other);
+  }
+
+  void operator-=(std::ptrdiff_t other) {
+    value_ -= other;
+  }
+
+  size_t operator-(StrongIndexAlias other) {
+    return StrongIndexAlias(get() - other.get());
+  }
+
+  StrongIndexAlias& operator++() {
+    ++value_;
+    return *this;
+  }
+
+  bool isValid() const {
+    return value_ != INVALID_INDEX;
+  }
+
+  void setInvalid() {
+    value_ = INVALID_INDEX;
+  }
+
+  bool operator==(StrongIndexAlias other) {
+    return get() == other.get();
+  }
+
+  bool operator!=(StrongIndexAlias other) {
+    return get() != other.get();
+  }
+
+  bool operator<(StrongIndexAlias other) {
+    return get() < other.get();
+  }
+
+ private:
+  static const ptrdiff_t INVALID_INDEX = PTRDIFF_MAX;
+
+  // WARNING: 0-initialized.
+  std::ptrdiff_t value_;
+};
+
+
+// This skeleton is based on C, yet compiles it as C++.
+// So expect warnings about C style casts.
+#if defined __clang__ && 306 <= __clang_major__ * 100 + __clang_minor__
+# pragma clang diagnostic ignored "-Wold-style-cast"
+#elif defined __GNUC__ && 406 <= __GNUC__ * 100 + __GNUC_MINOR__
+# pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+// On MacOS, PTRDIFF_MAX is defined as long long, which Clang's
+// -pedantic reports as being a C++11 extension.
+#if defined __APPLE__ && YY_CPLUSPLUS < 201103L \
+    && defined __clang__ && 4 <= __clang_major__
+# pragma clang diagnostic ignored "-Wc++11-long-long"
+#endif
+
+// Whether we are compiled with exception support.
+#ifndef YY_EXCEPTIONS
+# if defined __GNUC__ && !defined __EXCEPTIONS
+#  define YY_EXCEPTIONS 0
+# else
+#  define YY_EXCEPTIONS 1
+# endif
+#endif
+
+]b4_YYDEBUG_define[
+
+]b4_namespace_open[
+
+]b4_bison_locations_if([m4_ifndef([b4_location_file],
+                                  [b4_location_define])])[
+
+  /// A Bison parser.
+  class ]b4_parser_class[
+  {
+  public:
+]b4_public_types_declare[
+]b4_symbol_type_define[
+
+    /// Build a parser object.
+    ]b4_parser_class[ (]b4_parse_param_decl[);
+    virtual ~]b4_parser_class[ ();
+
+    /// Parse.  An alias for parse ().
+    /// \returns  0 iff parsing succeeded.
+    int operator() ();
+
+    /// Parse.
+    /// \returns  0 iff parsing succeeded.
+    virtual int parse ();
+
+#if ]b4_api_PREFIX[DEBUG
+    /// The current debugging stream.
+    std::ostream& debug_stream () const;
+    /// Set the current debugging stream.
+    void set_debug_stream (std::ostream &);
+
+    /// Type for debugging levels.
+    typedef int debug_level_type;
+    /// The current debugging level.
+    debug_level_type debug_level () const;
+    /// Set the current debugging level.
+    void set_debug_level (debug_level_type l);
+#endif
+
+    /// Report a syntax error.]b4_locations_if([[
+    /// \param loc    where the syntax error is found.]])[
+    /// \param msg    a description of the syntax error.
+    virtual void error (]b4_locations_if([[const location_type& loc,
]])[const std::string& msg);
+
+]b4_parse_error_bmatch(
+[custom\|detailed],
+[[    /// The user-facing name of the symbol whose (internal) number is
+    /// YYSYMBOL.  No bounds checking.
+    static const char *symbol_name (symbol_kind_type yysymbol);]],
+[simple],
+[[#if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
+    /// The user-facing name of the symbol whose (internal) number is
+    /// YYSYMBOL.  No bounds checking.
+    static const char *symbol_name (symbol_kind_type yysymbol);
+#endif // #if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
+]],
+[verbose],
+[[    /// The user-facing name of the symbol whose (internal) number is
+    /// YYSYMBOL.  No bounds checking.
+    static std::string symbol_name (symbol_kind_type yysymbol);]])[
+
+# if ]b4_api_PREFIX[DEBUG
+  public:
+    /// \brief Report a symbol value on the debug stream.
+    /// \param yykind       The symbol kind.
+    /// \param yyvaluep     Its semantic value.]b4_locations_if([[
+    /// \param yylocationp  Its location.]])[
+    virtual void yy_symbol_value_print_ (symbol_kind_type yykind,
+                                         const semantic_type*
yyvaluep]b4_locations_if([[,
+                                         const location_type*
yylocationp]])[) const;
+    /// \brief Report a symbol on the debug stream.
+    /// \param yykind       The symbol kind.
+    /// \param yyvaluep     Its semantic value.]b4_locations_if([[
+    /// \param yylocationp  Its location.]])[
+    virtual void yy_symbol_print_ (symbol_kind_type yykind,
+                                   const semantic_type*
yyvaluep]b4_locations_if([[,
+                                   const location_type* yylocationp]])[) const;
+  private:
+    /// Debug stream.
+    std::ostream* yycdebug_;
+#endif
+
+  public: // FIXME: Private
+]b4_parse_error_bmatch(
+[simple],
+[[#if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
+    /// For a symbol, its name in clear.
+    static const char* const yytname_[];
+#endif // #if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
+]],
+[verbose],
+[[    /// Convert the symbol name \a n to a form suitable for a diagnostic.
+    static std::string yytnamerr_ (const char *yystr);
+
+    /// For a symbol, its name in clear.
+    static const char* const yytname_[];
+]])[
+
+    /// \brief Reclaim the memory associated to a symbol.
+    /// \param yymsg     Why this token is reclaimed.
+    ///                  If null, print nothing.
+    /// \param yysym     The symbol.
+    void yy_destroy_ (const char* yymsg, symbol_kind_type yykind,
+                      const semantic_type* yyvaluep]b4_locations_if([[,
+                      const location_type* yylocationp]])[);
+
+]b4_parse_param_vars[
+  };
+
+]b4_namespace_close[
+
+]b4_percent_code_get([[provides]])[
+]m4_popdef([b4_parse_param])dnl
+])[
+
+]b4_defines_if(
+[b4_output_begin([b4_spec_header_file])
+b4_copyright([Skeleton interface for Bison GLR parsers in C++],
+             [2002-2015, 2018-2020])[
+// C++ GLR parser skeleton written by Valentin Tolmer.
+
+]b4_disclaimer[
+]b4_cpp_guard_open([b4_spec_mapped_header_file])[
+]b4_shared_declarations[
+]b4_cpp_guard_close([b4_spec_mapped_header_file])[
+]b4_output_end])
+
+# Let glr.c (and b4_shared_declarations) believe that the user
+# arguments include the parser itself.
+m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_wrap]))
+
+## ---------------- ##
+## Default values.  ##
+## ---------------- ##
+
+# Stack parameters.
+m4_define_default([b4_stack_depth_max], [10000])
+m4_define_default([b4_stack_depth_init],  [200])
+
+
+
+## ------------------------ ##
+## Pure/impure interfaces.  ##
+## ------------------------ ##
+
+b4_define_flag_if([pure])
+
+# b4_user_formals
+# ---------------
+# The possible parse-params formal arguments preceded by a comma.
+#
+# This is not shared with yacc.c in c.m4 because  GLR relies on ISO C
+# formal argument declarations.
+m4_define([b4_user_formals],
+[m4_ifset([b4_parse_param], [, b4_user_formals_no_comma])])
+
+# b4_user_formals_no_comma
+# ---------------
+# The possible parse-params formal arguments.
+m4_define([b4_user_formals_no_comma],
+[m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)])])
+
+# b4_yyerror_args
+# ---------------
+# Optional effective arguments passed to yyerror: user args plus yylloc, and
+# a trailing comma.
+m4_define([b4_yyerror_args],
+[b4_pure_if([b4_locations_if([yylocp, ])])dnl
+m4_ifset([b4_parse_param], [b4_args(b4_parse_param), ])])
+
+
+# b4_lyyerror_args
+# ----------------
+# Same as above, but on the lookahead, hence &yylloc instead of yylocp.
+m4_define([b4_lyyerror_args],
+[b4_pure_if([b4_locations_if([&yylloc, ])])dnl
+m4_ifset([b4_parse_param], [b4_args(b4_parse_param), ])])
+
+
+# b4_pure_args
+# ------------
+# Same as b4_yyerror_args, but with a leading comma.
+m4_define([b4_pure_args],
+[b4_pure_if([b4_locations_if([, yylocp])])[]b4_user_args])
+
+
+# b4_lpure_args
+# -------------
+# Same as above, but on the lookahead, hence &yylloc instead of yylocp.
+m4_define([b4_lpure_args],
+[b4_pure_if([b4_locations_if([, &yylloc])])[]b4_user_args])
+
+
+
+# b4_pure_formals
+# ---------------
+# Arguments passed to yyerror: user formals plus yylocp with leading comma.
+m4_define([b4_pure_formals],
+[b4_pure_if([b4_locations_if([, YYLTYPE *yylocp])])[]b4_user_formals])
+
+
+# b4_locuser_formals(LOC = yylocp)
+# --------------------------------
+# User formal arguments, possibly preceded by location argument.
+m4_define([b4_locuser_formals],
+[b4_locations_if([, YYLTYPE *m4_default([$1], [yylocp])])[]b4_user_formals])
+
+
+# b4_locuser_args(LOC = yylocp)
+# -----------------------------
+m4_define([b4_locuser_args],
+[b4_locations_if([, m4_default([$1], [yylocp])])[]b4_user_args])
+
+
+# b4_symbol_kind(NUM)
+# -------------------
+m4_define([b4_symbol_kind],
+[symbol_kind::b4_symbol_kind_base($@)])
+
+
+## ----------------- ##
+## Semantic Values.  ##
+## ----------------- ##
+
+
+# b4_lhs_value(SYMBOL-NUM, [TYPE])
+# --------------------------------
+# See README.
+m4_define([b4_lhs_value],
+[b4_symbol_value([(*yyvalp)], [$1], [$2])])
+
+
+# b4_rhs_data(RULE-LENGTH, POS)
+# -----------------------------
+# See README.
+m4_define([b4_rhs_data],
+[((yyGLRStackItem const *)yyvsp)@{YYFILL (b4_subtract([$2],
[$1]))@}.getState()])
+
+
+# b4_rhs_value(RULE-LENGTH, POS, SYMBOL-NUM, [TYPE])
+# --------------------------------------------------
+# Expansion of $$ or $<TYPE>$, for symbol SYMBOL-NUM.
+m4_define([b4_rhs_value],
+[b4_symbol_value([b4_rhs_data([$1], [$2]).semanticVal()], [$3], [$4])])
+
+
+
+## ----------- ##
+## Locations.  ##
+## ----------- ##
+
+# b4_lhs_location()
+# -----------------
+# Expansion of @$.
+m4_define([b4_lhs_location],
+[(*yylocp)])
+
+
+# b4_rhs_location(RULE-LENGTH, NUM)
+# ---------------------------------
+# Expansion of @NUM, where the current rule has RULE-LENGTH symbols
+# on RHS.
+m4_define([b4_rhs_location],
+[(b4_rhs_data([$1], [$2]).yyloc)])
+
+
+## -------------- ##
+## Output files.  ##
+## -------------- ##
+
+# Unfortunately the order of generation between the header and the
+# implementation file matters (for glr.c) because of the current
+# implementation of api.value.type=union.  In that case we still use a
+# union for YYSTYPE, but we generate the contents of this union when
+# setting up YYSTYPE.  This is needed for other aspects, such as
+# defining yy_symbol_value_print, since we need to now the name of the
+# members of this union.
+#
+# To avoid this issue, just generate the header before the
+# implementation file.  But we should also make them more independant.
+
+
+# ------------------------- #
+# The implementation file.  #
+# ------------------------- #
+
+b4_output_begin([b4_parser_file_name])
+b4_copyright([Skeleton implementation for Bison GLR parsers in C],
+             [2002-2015, 2018-2019])[
+/* New C++ GLR parser skeleton written by Akim Demaille, adapted by Valentin
+ * Tolmer.  */
+
+]b4_disclaimer[
+]b4_identification[
+
+]b4_percent_code_get([[top]])[
+]m4_if(b4_api_prefix, [yy], [],
+[[/* Substitute the type names.  */
+#define YYSTYPE ]b4_api_PREFIX[STYPE]b4_locations_if([[
+#define YYLTYPE ]b4_api_PREFIX[LTYPE]])])[
+]m4_if(b4_prefix, [yy], [],
+[[/* Substitute the variable and function names.  */
+#define yyparse ]b4_prefix[parse
+#define yylex   ]b4_prefix[lex
+#define yyerror ]b4_prefix[error
+#define yydebug ]b4_prefix[debug]]b4_pure_if([], [[
+#define yylval  ]b4_prefix[lval
+#define yychar  ]b4_prefix[char
+#define yynerrs ]b4_prefix[nerrs]b4_locations_if([[
+#define yylloc  ]b4_prefix[lloc]])]))[
+
+]b4_user_pre_prologue[
+
+]b4_null_define[
+
+]b4_defines_if([[#include "@basename(]b4_spec_header_file[@)"]],
+               [b4_shared_declarations])[
+
+]b4_glr_cc_setup[
+
+#ifndef ]b4_api_PREFIX[STYPE
+# define ]b4_api_PREFIX[STYPE
]b4_namespace_ref[::]b4_parser_class[::semantic_type
+#endif
+#ifndef ]b4_api_PREFIX[LTYPE
+# define ]b4_api_PREFIX[LTYPE
]b4_namespace_ref[::]b4_parser_class[::location_type
+#endif
+
+typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind_type
yysymbol_kind_t;
+
+/* Default (constant) value used for initialization for null
+   right-hand sides.  Unlike the standard yacc.c template, here we set
+   the default value of $$ to a zeroed-out value.  Since the default
+   value is undefined, this behavior is technically correct.  */
+static YYSTYPE yyval_default;]b4_locations_if([[
+static YYLTYPE yyloc_default][]b4_yyloc_default;])[
+
+]b4_user_post_prologue[
+]b4_percent_code_get[]dnl
+
+[#include <cstdio>
+#include <cstdlib>
+
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YYFREE
+# define YYFREE free
+#endif
+#ifndef YYMALLOC
+# define YYMALLOC malloc
+#endif
+
+#define YYSIZEMAX YY_CAST(size_t, -1)
+
+#ifndef YYSETJMP
+# include <setjmp.h>
+# define YYJMP_BUF jmp_buf
+# define YYSETJMP(Env) setjmp (Env)
+/* Pacify Clang and ICC.  */
+# define YYLONGJMP(Env, Val)                    \
+ do {                                           \
+   longjmp (Env, Val);                          \
+   YYASSERT (0);                                \
+ } while (false)
+#endif
+
+]b4_attribute_define([noreturn])[
+
+#ifndef YYASSERT
+# define YYASSERT(Condition) ((void) ((Condition) || (abort (), 0)))
+#endif
+
+#ifdef YYDEBUG
+# define YYDASSERT(Condition) YYASSERT(Condition)
+#else
+# define YYDASSERT(Condition)
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  ]b4_final_state_number[
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   ]b4_last[
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  ]b4_tokens_number[
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  ]b4_nterms_number[
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  ]b4_rules_number[
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  ]b4_states_number[
+/* YYMAXRHS -- Maximum number of symbols on right-hand side of rule.  */
+#define YYMAXRHS ]b4_r2_max[
+/* YYMAXLEFT -- Maximum number of symbols to the left of a handle
+   accessed by $0, $-1, etc., in any rule.  */
+#define YYMAXLEFT ]b4_max_left_semantic_context[
+
+/* YYUNDEFTOK -- Symbol number (for yytoken) that denotes an unknown
+   token.  */
+#define YYUNDEFTOK  ]b4_undef_token_number[
+
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, with out-of-bounds checking.  */
+]b4_api_token_raw_if(dnl
+[[#define YYTRANSLATE(YYX) YY_CAST
(]b4_namespace_ref::b4_parser_class[::symbol_kind_type, YYX)]],
+[[#define YYTRANSLATE(YYX)                                \
+  (0 <= (YYX) && (YYX) <= ]b4_code_max[                     \
+   ? YY_CAST (]b4_namespace_ref::b4_parser_class[::symbol_kind_type,
yytranslate[YYX])        \
+   : ]b4_namespace_ref::b4_parser_class::symbol_kind::b4_symbol(-2, kind)[)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex.  */
+static const ]b4_int_type_for([b4_translate])[ yytranslate[] =
+{
+  ]b4_translate[
+};]])[
+
+#if ]b4_api_PREFIX[DEBUG
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const ]b4_int_type_for([b4_rline])[ yyrline[] =
+{
+  ]b4_rline[
+};
+#endif
+
+#define YYPACT_NINF ]b4_pact_ninf[
+#define YYTABLE_NINF ]b4_table_ninf[
+
+]b4_parser_tables_define[
+
+/* YYDPREC[RULE-NUM] -- Dynamic precedence of rule #RULE-NUM (0 if none).  */
+static const ]b4_int_type_for([b4_dprec])[ yydprec[] =
+{
+  ]b4_dprec[
+};
+
+/* YYMERGER[RULE-NUM] -- Index of merging function for rule #RULE-NUM.  */
+static const ]b4_int_type_for([b4_merger])[ yymerger[] =
+{
+  ]b4_merger[
+};
+
+/* YYIMMEDIATE[RULE-NUM] -- True iff rule #RULE-NUM is not to be deferred, as
+   in the case of predicates.  */
+static const bool yyimmediate[] =
+{
+  ]b4_immediate[
+};
+
+/* YYCONFLP[YYPACT[STATE-NUM]] -- Pointer into YYCONFL of start of
+   list of conflicting reductions corresponding to action entry for
+   state STATE-NUM in yytable.  0 means no conflicts.  The list in
+   yyconfl is terminated by a rule number of 0.  */
+static const ]b4_int_type_for([b4_conflict_list_heads])[ yyconflp[] =
+{
+  ]b4_conflict_list_heads[
+};
+
+/* YYCONFL[I] -- lists of conflicting rule numbers, each terminated by
+   0, pointed into by YYCONFLP.  */
+]dnl Do not use b4_int_type_for here, since there are places where
+dnl pointers onto yyconfl are taken, whose type is "short*".
+dnl We probably ought to introduce a type for confl.
+[static const short yyconfl[] =
+{
+  ]b4_conflicting_rules[
+};
+
+/* Error token number */
+#define YYTERROR 1
+
+]b4_locations_if([[
+]b4_yylloc_default_define[
+# define YYRHSLOC(Rhs, K) ((Rhs)[K].getState().yyloc)
+]])[
+
+]b4_pure_if(
+[
+#undef yynerrs
+#define yynerrs (yystackp->yyerrcnt)
+#undef yychar
+#define yychar (yystackp->yyrawchar)
+#undef yylval
+#define yylval (yystackp->yyval)
+#undef yylloc
+#define yylloc (yystackp->yyloc)
+m4_if(b4_prefix[], [yy], [],
+[#define b4_prefix[]nerrs yynerrs
+#define b4_prefix[]char yychar
+#define b4_prefix[]lval yylval
+#define b4_prefix[]lloc yylloc])],
+[YYSTYPE yylval;]b4_locations_if([[
+YYLTYPE yylloc;]])[
+
+int yynerrs;
+int yychar;])[
+
+typedef enum { yyok, yyaccept, yyabort, yyerr } YYRESULTTAG;
+
+#define YYCHK(YYE)                              \
+  do {                                          \
+    YYRESULTTAG yychk_flag = YYE;               \
+    if (yychk_flag != yyok)                     \
+      return yychk_flag;                        \
+  } while (0)
+
+#if ]b4_api_PREFIX[DEBUG
+
+# ifndef YYFPRINTF
+#  define YYFPRINTF fprintf
+# endif
+
+]b4_yy_location_print_define[
+
+# define YYDPRINTF(Args)                        \
+  do {                                          \
+    if (yydebug)                                \
+      YYFPRINTF Args;                           \
+  } while (0)
+
+]b4_yy_symbol_print_define[
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                  \
+  do {                                                                  \
+    if (yydebug)                                                        \
+      {                                                                 \
+        YYFPRINTF (stderr, "%s ", Title);                               \
+        yy_symbol_print (stderr, Type,
Value]b4_locuser_args([Location])[);        \
+        YYFPRINTF (stderr, "\n");                                       \
+      }                                                                 \
+  } while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+
+struct yyGLRStack;
+static void yypstack (struct yyGLRStack* yystackp, size_t yyk)
+  YY_ATTRIBUTE_UNUSED;
+static void yypdumpstack (struct yyGLRStack* yystackp)
+  YY_ATTRIBUTE_UNUSED;
+
+#else /* !]b4_api_PREFIX[DEBUG */
+
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+
+#endif /* !]b4_api_PREFIX[DEBUG */
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH ]b4_stack_depth_init[
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYMAXDEPTH * sizeof (GLRStackItem)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH ]b4_stack_depth_max[
+#endif
+
+/* Minimum number of free items on the stack allowed after an
+   allocation.  This is to allow allocation and initialization
+   to be completed by functions that call yyexpandGLRStack before the
+   stack is expanded, thus insuring that all necessary pointers get
+   properly redirected to new data.  */
+#define YYHEADROOM 2
+
+#ifndef YYSTACKEXPANDABLE
+#  define YYSTACKEXPANDABLE 1
+#endif
+
+/** State numbers, as in LALR(1) machine */
+typedef int yyStateNum;
+
+/** Rule numbers, as in LALR(1) machine */
+typedef int yyRuleNum;
+
+/** Item references, as in LALR(1) machine */
+typedef short yyItemNum;
+
+// Forward declarations.
+struct yyGLRState;
+struct yySemanticOption;
+struct yyGLRStackItem;
+struct yyGLRStack;
+
+typedef StrongIndexAlias<struct yyGLRStateSetTag> yyStateSetIndex;
+
+yyStateSetIndex yycreateStateSetIndex(std::ptrdiff_t value) {
+  return yyStateSetIndex::create(value);
+}
+
+#define yypact_value_is_default(Yystate) \
+  ]b4_table_value_equals([[pact]], [[Yystate]], [b4_pact_ninf], [YYPACT_NINF])[
+
+#define yytable_value_is_error(Yytable_value) \
+  ]b4_table_value_equals([[table]], [[Yytable_value]],
[b4_table_ninf], [YYTABLE_NINF])[
+
+]m4_define([b4_yygetToken_call],
+           [[yygetToken (&yychar][]b4_pure_if([, yystackp])[]b4_user_args[)]])[
+
+static inline ]b4_namespace_ref::b4_parser_class[::symbol_kind_type
+yygetToken (int *yycharp][]b4_pure_if([, yyGLRStack*
yystackp])[]b4_user_formals[);
+
+static inline bool
+yyisShiftAction (int yyaction)
+{
+  return 0 < yyaction;
+}
+
+static inline bool
+yyisErrorAction (int yyaction)
+{
+  return yyaction == 0;
+}
+
+static inline int
+yygetLRActions (yyStateNum yystate,
]b4_namespace_ref::b4_parser_class[::symbol_kind_type yytoken, const
short** yyconflicts);
+
+/** True iff LR state YYSTATE has only a default reduction (regardless
+ *  of token).  */
+static inline bool
+yyisDefaultedState (yyStateNum yystate)
+{
+  return yypact_value_is_default (yypact[yystate]);
+}
+
+/** The default reduction for YYSTATE, assuming it has one.  */
+static inline yyRuleNum
+yydefaultAction (yyStateNum yystate)
+{
+  return yydefact[yystate];
+}
+
+static inline int
+yyrhsLength (yyRuleNum yyrule);
+
+
+class yyGLRState {
+ public:
+  yyGLRState()
+  : yyresolved(false)
+  , yylrState(0)
+  , yyposn(0)
+  , yypred(0)
+  {}
+
+  /// Build with a semantic value.
+  yyGLRState(yyStateNum lrState, size_t posn, YYSTYPE
sval]b4_locations_if([[, YYLTYPE loc]])[)
+  : yyresolved(true)
+  , yylrState(lrState)
+  , yyposn(posn)
+  , yypred(0)]b4_locations_if([[
+  , yyloc(loc)]])[ {
+    semanticVal() = sval;
+  }
+
+  /// Build with a semantic option.
+  yyGLRState(yyStateNum lrState, size_t posn)
+  : yyresolved(false)
+  , yylrState(lrState)
+  , yyposn(posn)
+  , yypred(0)
+  , yyfirstVal(0)
+  {}
+
+  void copyFrom(const yyGLRState& other) {
+    *this = other;
+    setPred(other.pred());
+    setFirstVal(other.firstVal());
+  }
+
+  /** Type tag for   If true, yysval applies, otherwise
+   *  yyfirstVal applies.  */
+  bool yyresolved;
+  /** Number of corresponding LALR(1) machine state.  */
+  yyStateNum yylrState;
+  /** Source position of the last token produced by my symbol */
+  size_t yyposn;
+
+  /// Only call pred() and setPred() on objects in yyitems, not temporaries.
+  yyGLRState* pred();
+  const yyGLRState* pred() const;
+  void setPred(const yyGLRState* state);
+
+  /// Only call firstVal() and setFirstVal() on objects in yyitems, not
+  /// temporaries.
+  yySemanticOption* firstVal();
+  const yySemanticOption* firstVal() const;
+  void setFirstVal(const yySemanticOption* option);
+
+  YYSTYPE& semanticVal() {
+    return yysval;
+  }
+
+  const YYSTYPE& semanticVal() const {
+    return yysval;
+  }
+
+  void
+  destroy (char const *yymsg]b4_user_formals[);
+
+  /* DEBUGGING ONLY */
+#if ]b4_api_PREFIX[DEBUG
+  void yy_yypstack() const
+  {
+    if (pred() != YY_NULLPTR)
+      {
+        pred()->yy_yypstack();
+        YYFPRINTF (stderr, " -> ");
+      }
+    YYFPRINTF (stderr, "%d@@%lu", yylrState,
+               (unsigned long) yyposn);
+  }
+#endif
+
+  std::ptrdiff_t indexIn(yyGLRStackItem* array);
+
+  yyGLRStackItem* asItem() {
+    return asItem(this);
+  }
+
+ private:
+  template <typename T>
+  static const yyGLRStackItem* asItem(const T* state) {
+    return reinterpret_cast<const yyGLRStackItem*>(state);
+  }
+  template <typename T>
+  static yyGLRStackItem* asItem(T* state) {
+    return reinterpret_cast<yyGLRStackItem*>(state);
+  }
+  /** Preceding state in this stack */
+  std::ptrdiff_t yypred;
+  union {
+    /** First in a chain of alternative reductions producing the
+     *  nonterminal corresponding to this state, threaded through
+     *  yyfirstVal.  */
+    std::ptrdiff_t yyfirstVal;
+    /** Semantic value for this state.  */
+    YYSTYPE yysval;
+  };]b4_locations_if([[
+ public:
+  /** Source location for this state.  */
+  YYLTYPE yyloc;]])[
+};
+
+/** A stack of GLRState representing the different heads during
+  * nondeterministic evaluation. */
+class yyGLRStateSet {
+ public:
+  /** Initialize YYSET to a singleton set containing an empty stack.  */
+  yyGLRStateSet()
+    : yylastDeleted(YY_NULLPTR)
+  {
+    yystates.push_back(YY_NULLPTR);
+    yylookaheadNeeds.push_back(false);
+  }
+
+  // Behave like a vector of states.
+  yyGLRState*& operator[](yyStateSetIndex index) {
+    return yystates[index.uget()];
+  }
+
+  yyGLRState* operator[](yyStateSetIndex index) const {
+    return yystates[index.uget()];
+  }
+
+  size_t size() const {
+    return yystates.size();
+  }
+
+  std::vector<yyGLRState*>::iterator begin() {
+    return yystates.begin();
+  }
+
+  std::vector<yyGLRState*>::iterator end() {
+    return yystates.end();
+  }
+
+
+  bool lookaheadNeeds(yyStateSetIndex index) const {
+    return yylookaheadNeeds[index.uget()];
+  }
+
+  bool setLookaheadNeeds(yyStateSetIndex index, bool value) {
+    return yylookaheadNeeds[index.uget()] = value;
+  }
+
+  /** Invalidate stack #YYK.  */
+  inline void
+  yymarkStackDeleted (yyStateSetIndex yyk)
+  {
+    size_t k = yyk.uget();
+    if (yystates[k] != YY_NULLPTR)
+      yylastDeleted = yystates[k];
+    yystates[k] = YY_NULLPTR;
+  }
+
+  /** Undelete the last stack in *this that was marked as deleted.  Can
+      only be done once after a deletion, and only when all other stacks have
+      been deleted.  */
+  void
+  yyundeleteLastStack ()
+  {
+    if (yylastDeleted == YY_NULLPTR || !yystates.empty())
+      return;
+    yystates.push_back(yylastDeleted);
+    YYDPRINTF ((stderr, "Restoring last deleted stack as stack #0.\n"));
+    clearLastDeleted();
+  }
+
+  /** Remove the dead stacks (yystates[i] == YY_NULLPTR) and shift the later
+   * ones.  */
+  inline void
+  yyremoveDeletes ()
+  {
+    std::ptrdiff_t newsize = YY_CAST(std::ptrdiff_t, yystates.size());
+    /* j is the number of live stacks we have seen.  */
+    for (size_t i = 0, j = 0; i < yystates.size(); ++i)
+      {
+        if (yystates[i] == YY_NULLPTR)
+          {
+            if (i == j)
+              {
+                YYDPRINTF ((stderr, "Removing dead stacks.\n"));
+              }
+            newsize -= 1;
+          }
+        else
+          {
+            yystates[j] = yystates[i];
+            /* In the current implementation, it's unnecessary to copy
+               yylookaheadNeeds[i] since, after
+               yyremoveDeletes returns, the parser immediately either enters
+               deterministic operation or shifts a token.  However, it doesn't
+               hurt, and the code might evolve to need it.  */
+            yylookaheadNeeds[j] = yylookaheadNeeds[i];
+            if (j != i)
+              {
+                YYDPRINTF ((stderr, "Rename stack %zu -> %zu.\n", i, j));
+              }
+            j += 1;
+          }
+        i += 1;
+      }
+    yystates.erase(yystates.begin() + newsize, yystates.end());
+    yylookaheadNeeds.erase(yylookaheadNeeds.begin() + newsize,
+                           yylookaheadNeeds.end());
+  }
+
+
+  yyStateSetIndex
+  yysplitStack (yyStateSetIndex yyk)
+  {
+    size_t k = yyk.uget();
+    yystates.push_back(yystates[k]);
+    yylookaheadNeeds.push_back(yylookaheadNeeds[k]);
+    return yycreateStateSetIndex(YY_CAST (std::ptrdiff_t,
yystates.size() - 1));
+  }
+
+  void clearLastDeleted() {
+    yylastDeleted = YY_NULLPTR;
+  }
+
+ private:
+
+  std::vector<yyGLRState*> yystates;
+  /** During nondeterministic operation, yylookaheadNeeds tracks which
+   *  stacks have actually needed the current lookahead.  During deterministic
+   *  operation, yylookaheadNeeds[0] is not maintained since it would merely
+   *  duplicate yychar != ]b4_symbol(-2, id)[.  */
+  std::vector<bool> yylookaheadNeeds;
+
+  /** The last stack we invalidated.  */
+  yyGLRState* yylastDeleted;
+
+  static const size_t INITIAL_NUMBER_STATES = 16;
+};
+
+struct yySemanticOption {
+  yySemanticOption()
+  : yyrule(0)
+  , yystate(0)
+  , yynext(0)
+  , yyrawchar(0)
+  {}
+
+  yySemanticOption(yyRuleNum rule, int rawChar)
+  : yyrule(rule)
+  , yystate(0)
+  , yynext(0)
+  , yyrawchar(rawChar)
+  {}
+
+  /// Only call state() and setState() on objects in yyitems, not temporaries.
+  yyGLRState* state();
+  const yyGLRState* state() const;
+  void setState(const yyGLRState* s);
+
+  yySemanticOption* next();
+  void setNext(const yySemanticOption* s);
+
+  std::ptrdiff_t indexIn(yyGLRStackItem* array);
+
+  /** True iff YYY0 and YYY1 represent identical options at the top level.
+   *  That is, they represent the same rule applied to RHS symbols
+   *  that produce the same terminal symbols.  */
+  bool
+  isIdenticalTo (yySemanticOption* yyy1)
+  {
+    if (this->yyrule == yyy1->yyrule)
+      {
+        yyGLRState *yys0, *yys1;
+        int yyn;
+        for (yys0 = this->state(),
+             yys1 = yyy1->state(),
+             yyn = yyrhsLength (this->yyrule);
+             yyn > 0;
+             yys0 = yys0->pred(),
+             yys1 = yys1->pred(), yyn -= 1)
+          if (yys0->yyposn != yys1->yyposn)
+            return false;
+        return true;
+      }
+    else
+      return false;
+  }
+
+  /** Assuming identicalOptions (YYY0,YYY1), destructively merge the
+   *  alternative semantic values for the RHS-symbols of YYY1 and YYY0.  */
+  void
+  mergeWith (yySemanticOption* yyy1)
+  {
+    yyGLRState *yys0 = this->state();
+    yyGLRState *yys1 = yyy1->state();
+    for (int yyn = yyrhsLength (this->yyrule);
+         yyn > 0;
+         yyn -= 1,
+         yys0 = yys0->pred(),
+         yys1 = yys1->pred())
+      {
+        if (yys0 == yys1)
+          break;
+        else if (yys0->yyresolved)
+          {
+            yys1->yyresolved = true;
+            yys1->semanticVal() = yys0->semanticVal();
+          }
+        else if (yys1->yyresolved)
+          {
+            yys0->yyresolved = true;
+            yys0->semanticVal() = yys1->semanticVal();
+          }
+        else
+          {
+            yySemanticOption* yyz0prev = YY_NULLPTR;
+            yySemanticOption* yyz0 = yys0->firstVal();
+            yySemanticOption* yyz1 = yys1->firstVal();
+            while (true)
+              {
+                if (yyz1 == yyz0 || yyz1 == YY_NULLPTR)
+                  break;
+                else if (yyz0 == YY_NULLPTR)
+                  {
+                    if (yyz0prev != YY_NULLPTR) {
+                      yyz0prev->setNext(yyz1);
+                    } else {
+                      yys0->setFirstVal(yyz1);
+                    }
+                    break;
+                  }
+                else if (yyz0 < yyz1)
+                  {
+                    yySemanticOption* yyz = yyz0;
+                    if (yyz0prev != YY_NULLPTR) {
+                      yyz0prev->setNext(yyz1);
+                    } else {
+                      yys0->setFirstVal(yyz1);
+                    }
+                    yyz1 = yyz1->next();
+                    yyz0->setNext(yyz);
+                  }
+                yyz0prev = yyz0;
+                yyz0 = yyz0->next();
+              }
+            yys1->setFirstVal(yys0->firstVal());
+          }
+      }
+  }
+
+  /** Rule number for this reduction */
+  yyRuleNum yyrule;
+
+ private:
+  template <typename T>
+  static const yyGLRStackItem* asItem(const T* state) {
+    return reinterpret_cast<const yyGLRStackItem*>(state);
+  }
+  template <typename T>
+  static yyGLRStackItem* asItem(T* state) {
+    return reinterpret_cast<yyGLRStackItem*>(state);
+  }
+  /** The last RHS state in the list of states to be reduced.  */
+  std::ptrdiff_t yystate;
+  /** Next sibling in chain of options.  To facilitate merging,
+   *  options are chained in decreasing order by address.  */
+  std::ptrdiff_t yynext;
+ public:
+  /** The lookahead for this reduction.  */
+  int yyrawchar;
+  YYSTYPE yyval;]b4_locations_if([[
+  YYLTYPE yyloc;]])[
+};
+
+/** Type of the items in the GLR stack.  The isState_ field
+ *  indicates which item of the union is valid.  */
+struct yyGLRStackItem {
+  yyGLRStackItem(bool isState = true)
+    : isState_(isState) {
+      if (isState) {
+        new (&raw_) yyGLRState;
+      } else {
+        new (&raw_) yySemanticOption;
+      }
+  }
+
+  ~yyGLRStackItem() {
+    if (isState()) {
+      getState().~yyGLRState();
+    } else {
+      getOption().~yySemanticOption();
+    }
+  }
+
+  yyGLRState& getState() {
+    YYDASSERT(isState());
+    return *(yyGLRState*)&raw_;
+  }
+  const yyGLRState& getState() const {
+    YYDASSERT(isState());
+    return *(yyGLRState*)&raw_;
+  }
+
+  yySemanticOption& getOption() {
+    YYDASSERT(!isState());
+    return *(yySemanticOption*)&raw_;
+  }
+  const yySemanticOption& getOption() const {
+    YYDASSERT(!isState());
+    return *(yySemanticOption*)&raw_;
+  }
+  bool isState() const {
+    return isState_;
+  }
+ private:
+  /// The possible contents of raw_. Since they have constructors, they cannot
+  /// be directly included in the union.
+  struct contents {
+    union {
+      char yystate[sizeof(yyGLRState)];
+      char yyoption[sizeof(yySemanticOption)];
+    };
+  };
+  enum { union_size = sizeof(contents) };
+  union {
+    /// Strongest alignment constraints.
+    long double yyalign_me;
+    /// A buffer large enough to store the contents.
+    char raw_[union_size];
+  };
+  /** Type tag for the union. */
+  bool isState_;
+};
+
+yyGLRState* yyGLRState::pred() {
+  return yypred ? &(asItem(this) - yypred)->getState() : YY_NULLPTR;
+}
+
+const yyGLRState* yyGLRState::pred() const {
+  return yypred ? &(asItem(this) - yypred)->getState() : YY_NULLPTR;
+}
+
+void yyGLRState::setPred(const yyGLRState* state) {
+  yypred = state ? asItem(this) - asItem(state) : 0;
+}
+
+yySemanticOption* yyGLRState::firstVal() {
+  return yyfirstVal ? &(asItem(this) - yyfirstVal)->getOption() : YY_NULLPTR;
+}
+
+const yySemanticOption* yyGLRState::firstVal() const {
+  return yyfirstVal ? &(asItem(this) - yyfirstVal)->getOption() : YY_NULLPTR;
+}
+
+void yyGLRState::setFirstVal(const yySemanticOption* option) {
+  yyfirstVal = option ? asItem(this) - asItem(option) : 0;
+}
+
+std::ptrdiff_t yyGLRState::indexIn(yyGLRStackItem* array) {
+  return asItem(this) - array;
+}
+
+std::ptrdiff_t yySemanticOption::indexIn(yyGLRStackItem* array) {
+  return asItem(this) - array;
+}
+
+yyGLRState* yySemanticOption::state() {
+  return yystate ? &(asItem(this) - yystate)->getState() : YY_NULLPTR;
+}
+
+const yyGLRState* yySemanticOption::state() const {
+  return yystate ? &(asItem(this) - yystate)->getState() : YY_NULLPTR;
+}
+
+void yySemanticOption::setState(const yyGLRState* s) {
+  yystate = s ? asItem(this) - asItem(s) : 0;
+}
+
+yySemanticOption* yySemanticOption::next() {
+  return yynext ? &(asItem(this) - yynext)->getOption() : YY_NULLPTR;
+}
+
+void yySemanticOption::setNext(const yySemanticOption* s) {
+  yynext = s ? asItem(this) - asItem(s) : 0;
+}
+
+void yyGLRState::destroy (char const *yymsg]b4_user_formals[)
+{
+  if (yyresolved)
+    yyparser.yy_destroy_ (yymsg, YY_CAST
(]b4_namespace_ref::b4_parser_class[::symbol_kind_type,
yystos[yylrState]),
+                &semanticVal()]b4_locations_if([, &yyloc])[);
+  else
+    {
+#if ]b4_api_PREFIX[DEBUG
+      if (yydebug)
+        {
+          if (firstVal() != YY_NULLPTR)
+            YYFPRINTF (stderr, "%s unresolved", yymsg);
+          else
+            YYFPRINTF (stderr, "%s incomplete", yymsg);
+          YY_SYMBOL_PRINT ("", YY_CAST
(]b4_namespace_ref::b4_parser_class[::symbol_kind_type,
yystos[yylrState]), YY_NULLPTR, &yyloc);
+        }
+#endif
+
+      if (firstVal() != YY_NULLPTR)
+        {
+          yySemanticOption *yyoption = firstVal();
+          yyGLRState *yyrh = yyoption->state();
+          for (int yyn = yyrhsLength (yyoption->yyrule); yyn > 0; yyn -= 1)
+            {
+              yyrh->destroy (yymsg]b4_user_args[);
+              yyrh = yyrh->pred();
+            }
+        }
+    }
+}
+
+
+static int
+yypreference (yySemanticOption* y0, yySemanticOption* y1);
+
+static void
+yyuserMerge (int yyn, YYSTYPE* yy0, YYSTYPE* yy1);
+
+
+/** Left-hand-side symbol for rule #YYRULE.  */
+static inline ]b4_namespace_ref::b4_parser_class[::symbol_kind_type
+yylhsNonterm (yyRuleNum yyrule)
+{
+  return YY_CAST
(]b4_namespace_ref::b4_parser_class[::symbol_kind_type, yyr1[yyrule]);
+}
+
+static inline yyStateNum
+yyLRgotoState (yyStateNum yystate,
]b4_namespace_ref::b4_parser_class[::symbol_kind_type yysym);
+
+#undef YYFILL
+#define YYFILL(N) yyfill (yyvsp, &yylow, (N), yynormal)
+
+struct yyStateStack {
+ public:
+  /** Initialize to a single empty stack, with total maximum
+   *  capacity for all stacks of YYSIZE.  */
+  yyStateStack (size_t yysize)
+    : yysplitPoint(YY_NULLPTR)
+  {
+    yyitems.reserve(yysize);
+  }
+
+#if YYSTACKEXPANDABLE
+  /** Returns false if it tried to expand but could not. */
+  bool
+  yyexpandGLRStackIfNeeded() {
+    return spaceLeft() < YYHEADROOM && yyexpandGLRStack();
+  }
+
+ private:
+  /** If *this is expandable, extend it.  WARNING: Pointers into the
+      stack from outside should be considered invalid after this call.
+      We always expand when there are 1 or fewer items left AFTER an
+      allocation, so that we can avoid having external pointers exist
+      across an allocation.  */
+  bool
+  yyexpandGLRStack()
+  {
+    if (YYMAXDEPTH - YYHEADROOM < yyitems.size())
+      return false;
+    const size_t yynewSize = YYMAXDEPTH < 2 * yyitems.size() ?
YYMAXDEPTH : 2 * yyitems.size();
+    yyitems.reserve(yynewSize);
+    return true;
+  }
+ public:
+#else
+  bool yyexpandGLRStackIfNeeded() {
+    return yystateStack.spaceLeft() < YYHEADROOM;
+  }
+#endif
+
+  static bool yyGLRStateNotNull(yyGLRState* s) {
+    return s != YY_NULLPTR;
+  }
+
+  bool
+  reduceToOneStack() {
+    const std::vector<yyGLRState*>::iterator begin =
+      yytops.begin();
+    const std::vector<yyGLRState*>::iterator end =
+      yytops.end();
+    std::vector<yyGLRState*>::iterator yyit =
+      std::find_if(begin, end, yyGLRStateNotNull);
+    if (yyit == end)
+      return false;
+    for (yyStateSetIndex yyk = yycreateStateSetIndex(yyit + 1 - begin);
+         yyk.uget() != numTops(); ++yyk)
+      yytops.yymarkStackDeleted (yyk);
+    yytops.yyremoveDeletes ();
+    yycompressStack ();
+    return true;
+  }
+
+  void
+  yycompressStack ()
+  {
+    if (yytops.size() != 1 || !isSplit())
+      return;
+
+    yyGLRState* yyr = YY_NULLPTR;
+    for (yyGLRState *yyp = firstTop(), *yyq = yyp->pred();
+         yyp != yysplitPoint;
+         yyr = yyp, yyp = yyq, yyq = yyp->pred())
+      yyp->setPred(yyr);
+
+    yyGLRStackItem* nextFreeItem = yysplitPoint->asItem() + 1;
+    yysplitPoint = YY_NULLPTR;
+    yytops.clearLastDeleted();
+
+    while (yyr != YY_NULLPTR)
+      {
+        yyGLRState& nextFreeState = nextFreeItem->getState();
+        nextFreeState.copyFrom(*yyr);
+        yyr = yyr->pred();
+        nextFreeState.setPred(&(nextFreeItem - 1)->getState());
+        setFirstTop(&nextFreeState);
+        ++nextFreeItem;
+      }
+    yyitems.resize(YY_CAST (size_t, nextFreeItem - yyitems.data()));
+  }
+
+  bool isSplit() const {
+    return yysplitPoint != YY_NULLPTR;
+  }
+
+  // Present the interface of a vector of yyGLRStackItem.
+  std::vector<yyGLRStackItem>::const_iterator begin() const {
+    return yyitems.begin();
+  }
+
+  std::vector<yyGLRStackItem>::const_iterator end() const {
+    return yyitems.end();
+  }
+
+  size_t size() const {
+    return yyitems.size();
+  }
+
+  yyGLRStackItem& operator[](size_t i) {
+    return yyitems[i];
+  }
+
+  yyGLRStackItem& stackItemAt(size_t index) {
+    return yyitems[index];
+  }
+
+  size_t numTops() const {
+    return yytops.size();
+  }
+
+  yyGLRState* firstTop() {
+    return yytops[yycreateStateSetIndex(0)];
+  }
+
+  yyGLRState* topAt(yyStateSetIndex i) {
+    return yytops[i];
+  }
+
+  void setFirstTop(yyGLRState* value) {
+    yytops[yycreateStateSetIndex(0)] = value;
+  }
+
+  void setTopAt(yyStateSetIndex i, yyGLRState* value) {
+    yytops[i] = value;
+  }
+
+  void pop_back() {
+    yyitems.pop_back();
+  }
+
+  void pop_back(size_t n) {
+    yyitems.resize(yyitems.size() - n);
+  }
+
+  yyStateSetIndex
+  yysplitStack (yyStateSetIndex yyk)
+  {
+    if (!isSplit())
+      {
+        YYASSERT (yyk.get() == 0);
+        yysplitPoint = topAt(yyk);
+      }
+    return yytops.yysplitStack(yyk);
+  }
+
+  /** Assuming that YYS is a GLRState somewhere on *this, update the
+   *  splitpoint of *this, if needed, so that it is at least as deep as
+   *  YYS.  */
+  inline void
+  yyupdateSplit (yyGLRState& yys)
+  {
+    if (isSplit() && &yys < yysplitPoint)
+      yysplitPoint = &yys;
+  }
+
+  /** Return a fresh GLRState.
+   * Callers should call yyreserveStack afterwards to make sure there is
+   * sufficient headroom.  */
+  yyGLRState& yynewGLRState(yyGLRState newState) {
+    yyGLRState& state = yyitems[yynewGLRStackItem(true)].getState();
+#if 201103L <= YY_CPLUSPLUS
+    state = std::move(newState);
+#else
+    state = newState;
+#endif
+    return state;
+  }
+
+  /** Return a fresh SemanticOption.
+   * Callers should call yyreserveStack afterwards to make sure there is
+   * sufficient headroom.  */
+  yySemanticOption& yynewSemanticOption(yySemanticOption newOption) {
+    yySemanticOption& option = yyitems[yynewGLRStackItem(false)].getOption();
+#if 201103L <= YY_CPLUSPLUS
+    option = std::move(newOption);
+#else
+    option = newOption;
+#endif
+    return option;
+  }
+
+  /* Do nothing if YYNORMAL or if *YYLOW <= YYLOW1.  Otherwise, fill in
+   * YYVSP[YYLOW1 .. *YYLOW-1] as in yyfillin and set *YYLOW = YYLOW1.
+   * For convenience, always return YYLOW1.  */
+  inline int
+  yyfill (yyGLRStackItem *yyvsp, int *yylow, int yylow1, bool yynormal)
+  {
+    if (!yynormal && yylow1 < *yylow)
+      {
+        yyfillin (yyvsp, *yylow, yylow1);
+        *yylow = yylow1;
+      }
+    return yylow1;
+  }
+
+  /** Fill in YYVSP[YYLOW1 .. YYLOW0-1] from the chain of states starting
+   *  at YYVSP[YYLOW0].getState().pred().  Leaves
YYVSP[YYLOW1].getState().pred()
+   *  containing the pointer to the next state in the chain.  */
+  void
+  yyfillin (yyGLRStackItem *yyvsp, int yylow0, int yylow1)
+  {
+    yyGLRState* s = yyvsp[yylow0].getState().pred();
+    for (int i = yylow0-1; i >= yylow1; i -= 1, s = s->pred())
+      {
+        yyGLRState& yys = yyvsp[i].getState();
+#if ]b4_api_PREFIX[DEBUG
+        yys.yylrState = s->yylrState;
+#endif
+        yys.yyresolved = s->yyresolved;
+        if (s->yyresolved)
+          yys.semanticVal() = s->semanticVal();
+        else
+          /* The effect of using semanticVal or yyloc (in an immediate rule) is
+           * undefined.  */
+          yys.setFirstVal(YY_NULLPTR);]b4_locations_if([[
+        yys.yyloc = s->yyloc;]])[
+        yys.setPred(s->pred());
+      }
+  }
+
+#if !]b4_api_PREFIX[DEBUG
+# define YY_REDUCE_PRINT(Args)
+#else
+# define YY_REDUCE_PRINT(Args)          \
+  do {                                  \
+    if (yydebug)                        \
+      yystateStack.yy_reduce_print Args;             \
+  } while (0)
+
+  /*----------------------------------------------------------------------.
+  | Report that stack #YYK of *YYSTACKP is going to be reduced by YYRULE. |
+  `----------------------------------------------------------------------*/
+
+  inline void
+  yy_reduce_print (bool yynormal, yyGLRStackItem* yyvsp, yyStateSetIndex yyk,
+                   yyRuleNum yyrule]b4_user_formals[)
+  {
+    int yynrhs = yyrhsLength (yyrule);]b4_locations_if([
+    int yylow = 1;])[
+    int yyi;
+    YYFPRINTF (stderr, "Reducing stack %lu by rule %d (line %lu):\n",
+               (unsigned long) yyk.get(), yyrule - 1,
+               (unsigned long) yyrline[yyrule]);
+    if (! yynormal)
+      yyfillin (yyvsp, 1, -yynrhs);
+    /* The symbols being reduced.  */
+    for (yyi = 0; yyi < yynrhs; yyi++)
+      {
+        YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+        yy_symbol_print (stderr,
+                         YY_CAST
(]b4_namespace_ref::b4_parser_class[::symbol_kind_type,
yystos[yyvsp[yyi - yynrhs + 1].getState().yylrState]),
+                         &yyvsp[yyi - yynrhs +
1].getState().semanticVal()]b4_locations_if([,
+                         &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
+                         b4_user_args[);
+        if (!yyvsp[yyi - yynrhs + 1].getState().yyresolved)
+          YYFPRINTF (stderr, " (unresolved)");
+        YYFPRINTF (stderr, "\n");
+      }
+  }
+
+
+#define YYINDEX(YYX)                                                         \
+    ((YYX) == YY_NULLPTR ? -1 : (YYX)->indexIn(yyitems.data()))
+
+  void
+  dumpStack ()
+  {
+    for (size_t yyi = 0; yyi < size(); ++yyi)
+      {
+        yyGLRStackItem& item = yyitems[yyi];
+        YYFPRINTF (stderr, "%3zu. ", yyi);
+        if (item.isState())
+          {
+            YYFPRINTF (stderr, "Res: %d, LR State: %d, posn: %zu, pred: %td",
+                       item.getState().yyresolved, item.getState().yylrState,
+                       item.getState().yyposn,
+                       YYINDEX(item.getState().pred()));
+            if (! item.getState().yyresolved)
+              YYFPRINTF (stderr, ", firstVal: %td",
+                         YYINDEX(item.getState().firstVal()));
+          }
+        else
+          {
+            YYFPRINTF (stderr, "Option. rule: %d, state: %td, next: %td",
+                       item.getOption().yyrule - 1,
+                       YYINDEX(item.getOption().state()),
+                       YYINDEX(item.getOption().next()));
+          }
+        YYFPRINTF (stderr, "\n");
+      }
+    YYFPRINTF (stderr, "Tops:");
+    for (yyStateSetIndex yyi = yycreateStateSetIndex(0); yyi.uget() <
numTops(); ++yyi) {
+      YYFPRINTF (stderr, "%lu: %td; ",
+                 (unsigned long) yyi.get(),
+                 YYINDEX(topAt(yyi)));
+    }
+    YYFPRINTF (stderr, "\n");
+  }
+
+#undef YYINDEX
+#endif
+
+  YYRESULTTAG
+  yyreportAmbiguity (yySemanticOption* yyx0,
+                     yySemanticOption* yyx1]b4_pure_formals[)
+  {
+    YYUSE (yyx0);
+    YYUSE (yyx1);
+
+#if ]b4_api_PREFIX[DEBUG
+    YYFPRINTF (stderr, "Ambiguity detected.\n");
+    YYFPRINTF (stderr, "Option 1,\n");
+    yyreportTree (yyx0, 2);
+    YYFPRINTF (stderr, "\nOption 2,\n");
+    yyreportTree (yyx1, 2);
+    YYFPRINTF (stderr, "\n");
+#endif
+
+    yyerror (]b4_yyerror_args[YY_("syntax is ambiguous"));
+    return yyabort;
+  }
+
+  /* DEBUGGING ONLY */
+#if ]b4_api_PREFIX[DEBUG
+  void
+  yypstates (const yyGLRState* yyst)
+  {
+    if (yyst != YY_NULLPTR)
+      yyst->yy_yypstack();
+    else
+      YYFPRINTF (stderr, "<null>");
+    YYFPRINTF (stderr, "\n");
+  }
+#endif
+
+ private:
+  size_t spaceLeft() const {
+    return yyitems.capacity() - yyitems.size();
+  }
+
+  /** Return a fresh GLRStackItem in this.  The item is an LR state
+   *  if YYISSTATE, and otherwise a semantic option.  Callers should call
+   *  yyreserveStack afterwards to make sure there is sufficient
+   *  headroom.  */
+  inline size_t
+  yynewGLRStackItem (bool yyisState)
+  {
+    YYDASSERT(yyitems.size() < yyitems.capacity());
+    yyitems.push_back(yyGLRStackItem(yyisState));
+    return yyitems.size() - 1;
+  }
+
+
+#if ]b4_api_PREFIX[DEBUG
+  void
+  yyreportTree (yySemanticOption* yyx, int yyindent)
+  {
+    int yynrhs = yyrhsLength (yyx->yyrule);
+    yyGLRState* yystates[1 + YYMAXRHS];
+    yyGLRState yyleftmost_state;
+
+    {
+      yyGLRState* yys = yyx->state();
+      for (int yyi = yynrhs; 0 < yyi; yyi -= 1)
+        {
+          yystates[yyi] = yys;
+          yys = yys->pred();
+        }
+      if (yys == YY_NULLPTR)
+        {
+          yyleftmost_state.yyposn = 0;
+          yystates[0] = &yyleftmost_state;
+        }
+      else
+        yystates[0] = yys;
+    }
+
+    std::string yylhs =
]b4_namespace_ref::b4_parser_class[::symbol_name (yylhsNonterm
(yyx->yyrule));
+    if (yyx->state()->yyposn < yystates[0]->yyposn + 1)
+      YYFPRINTF (stderr, "%*s%s -> <Rule %d, empty>\n",
+                 yyindent, "", yylhs.c_str(),
+                 yyx->yyrule - 1);
+    else
+      YYFPRINTF (stderr, "%*s%s -> <Rule %d, tokens %zu .. %zu>\n",
+                 yyindent, "", yylhs.c_str(),
+                 yyx->yyrule - 1, yystates[0]->yyposn + 1,
+                 yyx->state()->yyposn);
+    for (int yyi = 1; yyi <= yynrhs; yyi += 1)
+      {
+        if (yystates[yyi]->yyresolved)
+          {
+            std::string yysym =
]b4_namespace_ref::b4_parser_class[::symbol_name (YY_CAST
(]b4_namespace_ref::b4_parser_class[::symbol_kind_type,
yystos[yystates[yyi]->yylrState]));
+            if (yystates[yyi-1]->yyposn+1 > yystates[yyi]->yyposn)
+              YYFPRINTF (stderr, "%*s%s <empty>\n", yyindent+2, "",
+                         yysym.c_str());
+            else
+              YYFPRINTF (stderr, "%*s%s <tokens %zu .. %zu>\n", yyindent+2, "",
+                         yysym.c_str(),
+                         yystates[yyi-1]->yyposn + 1,
+                         yystates[yyi]->yyposn);
+          }
+        else
+          yyreportTree (yystates[yyi]->firstVal(),
+                        yyindent+2);
+      }
+  }
+#endif
+
+ public:
+
+  std::vector<yyGLRStackItem> yyitems;
+  yyGLRState* yysplitPoint;
+  yyGLRStateSet yytops;
+};
+
+#undef YYFILL
+#define YYFILL(N) yystateStack.yyfill (yyvsp, &yylow, (N), yynormal)
+
+#define yystackp this
+struct yyGLRStack {
+
+  yyGLRStack(size_t yysize, ]b4_parse_param_decl[)
+    : yyerrState(0)
+    , yystateStack(yysize)
+    , yyerrcnt(0)
+    , yyrawchar(0)
+    ,]b4_parse_param_cons[
+  {}
+
+  ~yyGLRStack ()
+  {
+    if (yychar !=
]b4_namespace_ref::b4_parser_class::token::b4_symbol(-2, id)[)
+      yyparser.yy_destroy_ ("Cleanup: discarding lookahead",
+                  YYTRANSLATE (yychar), &yylval]b4_locations_if([, &yylloc])[);
+    popall();
+  }
+
+  int yyerrState;
+]b4_locations_if([[  /* To compute the location of the error token.  */
+  yyGLRStackItem yyerror_range[3];]])[
+]b4_pure_if(
+[
+  yyStateStack yystateStack;
+  int yyerrcnt;
+  int yyrawchar;
+  YYSTYPE yyval;]b4_locations_if([[
+  YYLTYPE yyloc;]])[
+])[
+  YYJMP_BUF yyexception_buffer;
+
+  void yyreserveGlrStack() {
+    if (yystateStack.yyexpandGLRStackIfNeeded ())
+      yyMemoryExhausted();
+  }
+
+  _Noreturn void
+  yyMemoryExhausted ()
+  {
+    YYLONGJMP (yyexception_buffer, 2);
+  }
+
+  _Noreturn void
+  yyFail (const char* yymsg]b4_pure_formals[)
+  {
+    if (yymsg != YY_NULLPTR)
+      yyerror (]b4_yyerror_args[yymsg);
+    YYLONGJMP (yyexception_buffer, 1);
+  }
+
+                                /* GLRStates */
+
+
+  /** Add a new semantic action that will execute the action for rule
+   *  YYRULE on the semantic values in YYRHS to the list of
+   *  alternative actions for YYSTATE.  Assumes that YYRHS comes from
+   *  stack #YYK of *this. */
+  void
+  yyaddDeferredAction (yyStateSetIndex yyk, yyGLRState* yystate,
+                       yyGLRState* yyrhs, yyRuleNum yyrule)
+  {
+    yySemanticOption& yynewOption =
+      yystateStack.yynewSemanticOption(yySemanticOption(yyrule,
]b4_namespace_ref::b4_parser_class::token::b4_symbol(-2, id)[));
+    yynewOption.setState(yyrhs);
+    yynewOption.setNext(yystate->firstVal());
+    if (yystateStack.yytops.lookaheadNeeds(yyk))
+      {
+        yynewOption.yyrawchar = yychar;
+        yynewOption.yyval = yylval;]b4_locations_if([
+        yynewOption.yyloc = yylloc;])[
+      }
+    yystate->setFirstVal(&yynewOption);
+
+    yyreserveGlrStack();
+  }
+
+#if ]b4_api_PREFIX[DEBUG
+  void yypdumpstack () {
+    yystateStack.dumpStack();
+  }
+#endif
+  void
+  yyreportSyntaxError (]b4_user_formals_no_comma[)
+  {
+    if (yyerrState != 0)
+      return;
+]b4_parse_error_bmatch(
+[simple],
+[[    yyerror (]b4_lyyerror_args[YY_("syntax error"));]],
+[[    {
+    ]b4_namespace_ref::b4_parser_class[::symbol_kind_type yytoken
+      = yychar == ]b4_namespace_ref::b4_parser_class::token::b4_symbol(-2, id)[
+      ? ]b4_namespace_ref::b4_parser_class::symbol_kind::b4_symbol(-2, kind)[
+      : YYTRANSLATE (yychar);
+    enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+    /* Arguments of yyformat. */
+    ]b4_namespace_ref::b4_parser_class[::symbol_kind_type
yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+    /* Number of reported tokens (one for the "unexpected", one per
+       "expected").  */
+    int yycount = 0;
+
+    /* There are many possibilities here to consider:
+       - If this state is a consistent state with a default action, then
+         the only way this function was invoked is if the default action
+         is an error action.  In that case, don't check for expected
+         tokens because there are none.
+       - The only way there can be no lookahead present (in yychar) is if
+         this state is a consistent state with a default action.  Thus,
+         detecting the absence of a lookahead is sufficient to determine
+         that there is no unexpected or expected token to report.  In that
+         case, just report a simple "syntax error".
+       - Don't assume there isn't a lookahead just because this state is a
+         consistent state with a default action.  There might have been a
+         previous inconsistent state, consistent state with a non-default
+         action, or user semantic action that manipulated yychar.
+       - Of course, the expected token list depends on states to have
+         correct lookahead information, and it depends on the parser not
+         to perform extra reductions after fetching a lookahead from the
+         scanner and before detecting a syntax error.  Thus, state merging
+         (from LALR or IELR) and default reductions corrupt the expected
+         token list.  However, the list is correct for canonical LR with
+         one exception: it will still contain any token that will not be
+         accepted due to an error action in a later state.
+    */
+    if (yytoken !=
]b4_namespace_ref::b4_parser_class::symbol_kind::b4_symbol(-2, kind)[)
+      {
+        int yyn = yypact[firstTopState()->yylrState];
+        yyarg[yycount++] = yytoken;
+        if (!yypact_value_is_default (yyn))
+          {
+            /* Start YYX at -YYN if negative to avoid negative indexes in
+               YYCHECK.  In other words, skip the first -YYN actions for this
+               state because they are default actions.  */
+            int yyxbegin = yyn < 0 ? -yyn : 0;
+            /* Stay within bounds of both yycheck and yytname.  */
+            int yychecklim = YYLAST - yyn + 1;
+            int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+            int yyx;
+            for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+              if (yycheck[yyx + yyn] == yyx && yyx !=
]b4_namespace_ref::b4_parser_class::symbol_kind::b4_symbol(1, kind)[
+                  && !yytable_value_is_error (yytable[yyx + yyn]))
+                {
+                  if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                    {
+                      yycount = 1;
+                      break;
+                    }
+                  yyarg[yycount++] = YY_CAST
(]b4_namespace_ref::b4_parser_class[::symbol_kind_type, yyx);
+                }
+          }
+      }
+
+    /* Internationalized format string. */
+    const char *yyformat = YY_NULLPTR;
+    switch (yycount)
+      {
+#define YYCASE_(N, S)                   \
+        case N:                           \
+          yyformat = S;                   \
+        break
+      default: /* Avoid compiler warnings. */
+        YYCASE_(0, YY_("syntax error"));
+        YYCASE_(1, YY_("syntax error, unexpected %s"));
+        YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+        YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+        YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or
%s or %s"));
+        YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or
%s or %s or %s"));
+#undef YYCASE_
+      }
+
+    std::string yymsg;
+    // Argument number.
+    std::ptrdiff_t yyi = 0;
+    for (char const* yyp = yyformat; *yyp; ++yyp)
+      if (yyp[0] == '%' && yyp[1] == 's' && yyi < yycount)
+        {
+          yymsg += ]b4_namespace_ref::b4_parser_class[::symbol_name
(yyarg[yyi++]);
+          ++yyp;
+        }
+      else
+        yymsg += *yyp;
+     yyerror (]b4_lyyerror_args[yymsg);
+    }
+]])[
+    yynerrs += 1;
+  }
+
+
+  /* Recover from a syntax error on this, assuming that YYTOKENP,
+     yylval, and yylloc are the syntactic category, semantic value,
and location
+     of the lookahead.  */
+  void
+  yyrecoverSyntaxError (]b4_user_formals_no_comma[)
+  {
+    if (yyerrState == 3)
+      /* We just shifted the error token and (perhaps) took some
+         reductions.  Skip tokens until we can proceed.  */
+      while (true)
+        {
+          ]b4_namespace_ref::b4_parser_class[::symbol_kind_type yytoken;
+          int yyj;
+          if (yychar ==
]b4_namespace_ref::b4_parser_class::token::b4_symbol(0, id)[)
+            yyFail (YY_NULLPTR][]b4_lpure_args[);
+          if (yychar !=
]b4_namespace_ref::b4_parser_class::token::b4_symbol(-2, id)[)
+            {]b4_locations_if([[
+              /* We throw away the lookahead, but the error range
+                 of the shifted error token must take it into account.  */
+              yyGLRState *yys = firstTopState();
+              yyGLRStackItem yyerror_range[3];
+              yyerror_range[1].getState().yyloc = yys->yyloc;
+              yyerror_range[2].getState().yyloc = yylloc;
+              YYLLOC_DEFAULT ((yys->yyloc), yyerror_range, 2);]])[
+              yytoken = YYTRANSLATE (yychar);
+              yyparser.yy_destroy_ ("Error: discarding",
+                          yytoken, &yylval]b4_locations_if([, &yylloc])[);
+              yychar =
]b4_namespace_ref::b4_parser_class::token::b4_symbol(-2, id)[;
+            }
+          yytoken = ]b4_yygetToken_call[;
+          yyj = yypact[firstTopState()->yylrState];
+          if (yypact_value_is_default (yyj))
+            return;
+          yyj += yytoken;
+          if (yyj < 0 || YYLAST < yyj || yycheck[yyj] != yytoken)
+            {
+              if (yydefact[firstTopState()->yylrState] != 0)
+                return;
+            }
+          else if (! yytable_value_is_error (yytable[yyj]))
+            return;
+        }
+
+    if (!yystateStack.reduceToOneStack())
+      yyFail (YY_NULLPTR][]b4_lpure_args[);
+
+    /* Now pop stack until we find a state that shifts the error token.  */
+    yyerrState = 3;
+    while (firstTopState() != YY_NULLPTR)
+      {
+        yyGLRState *yys = firstTopState();
+        int yyj = yypact[yys->yylrState];
+        if (! yypact_value_is_default (yyj))
+          {
+            yyj += YYTERROR;
+            if (0 <= yyj && yyj <= YYLAST && yycheck[yyj] == YYTERROR
+                && yyisShiftAction (yytable[yyj]))
+              {
+                /* Shift the error token.  */]b4_locations_if([[
+                /* First adjust its location.*/
+                YYLTYPE yyerrloc;
+                yyerror_range[2].getState().yyloc = yylloc;
+                YYLLOC_DEFAULT (yyerrloc, (yyerror_range), 2);]])[
+                YY_SYMBOL_PRINT ("Shifting", YY_CAST
(]b4_namespace_ref::b4_parser_class[::symbol_kind_type,
yystos[yytable[yyj]]),
+                                 &yylval, &yyerrloc);
+                yyglrShift (yycreateStateSetIndex(0), yytable[yyj],
+                            yys->yyposn, &yylval]b4_locations_if([,
&yyerrloc])[);
+                yys = firstTopState();
+                break;
+              }
+          }]b4_locations_if([[
+        yyerror_range[1].getState().yyloc = yys->yyloc;]])[
+        if (yys->pred() != YY_NULLPTR)
+          yys->destroy ("Error: popping"]b4_user_args[);
+        yystateStack.setFirstTop(yys->pred());
+        yystateStack.pop_back();
+      }
+    if (firstTopState() == YY_NULLPTR)
+      yyFail (YY_NULLPTR][]b4_lpure_args[);
+  }
+
+  YYRESULTTAG
+  yyprocessOneStack (yyStateSetIndex yyk,
+                     size_t yyposn]b4_pure_formals[)
+  {
+    while (yystateStack.topAt(yyk) != YY_NULLPTR)
+      {
+        yyStateNum yystate = topState(yyk)->yylrState;
+        YYDPRINTF ((stderr, "Stack %zu Entering state %d\n",
+                    yyk.get(), yystate));
+
+        YYASSERT (yystate != YYFINAL);
+
+        if (yyisDefaultedState (yystate))
+          {
+            yyRuleNum yyrule = yydefaultAction (yystate);
+            if (yyrule == 0)
+              {
+                YYDPRINTF ((stderr, "Stack %zu dies.\n",
+                            yyk.get()));
+                yystateStack.yytops.yymarkStackDeleted (yyk);
+                return yyok;
+              }
+            YYRESULTTAG yyflag = yyglrReduce (yyk, yyrule,
+
yyimmediate[yyrule]]b4_user_args[);
+            if (yyflag == yyerr)
+              {
+                YYDPRINTF ((stderr,
+                            "Stack %zu dies "
+                            "(predicate failure or explicit user error).\n",
+                            yyk.get()));
+                yystateStack.yytops.yymarkStackDeleted (yyk);
+                return yyok;
+              }
+            if (yyflag != yyok)
+              return yyflag;
+          }
+        else
+          {
+            yystateStack.yytops.setLookaheadNeeds(yyk, true);
+            ]b4_namespace_ref::b4_parser_class[::symbol_kind_type
yytoken = ]b4_yygetToken_call[;
+            const short* yyconflicts;
+            int yyaction = yygetLRActions (yystate, yytoken, &yyconflicts);
+
+            for (; *yyconflicts != 0; ++yyconflicts)
+              {
+                yyStateSetIndex yynewStack = yystateStack.yysplitStack (yyk);
+                YYDPRINTF ((stderr, "Splitting off stack %lu from %zu.\n",
+                            (unsigned long) yynewStack.get(),
+                            yyk.get()));
+                YYRESULTTAG yyflag =
+                  yyglrReduce (yynewStack, *yyconflicts,
+                               yyimmediate[*yyconflicts]]b4_user_args[);
+                if (yyflag == yyok)
+                  YYCHK (yyprocessOneStack (yynewStack,
+                                            yyposn]b4_pure_args[));
+                else if (yyflag == yyerr)
+                  {
+                    YYDPRINTF ((stderr, "Stack %zu dies.\n",
+                                yynewStack.get()));
+                    yystateStack.yytops.yymarkStackDeleted (yynewStack);
+                  }
+                else
+                  return yyflag;
+              }
+
+            if (yyisShiftAction (yyaction))
+              break;
+            else if (yyisErrorAction (yyaction))
+              {
+                YYDPRINTF ((stderr, "Stack %lu dies.\n",
+                            (unsigned long) yyk.get()));
+                yystateStack.yytops.yymarkStackDeleted (yyk);
+                break;
+              }
+            else
+              {
+                YYRESULTTAG yyflag = yyglrReduce (yyk, -yyaction,
+
yyimmediate[-yyaction]]b4_user_args[);
+                if (yyflag == yyerr)
+                  {
+                    YYDPRINTF ((stderr,
+                                "Stack %lu dies "
+                                "(predicate failure or explicit user
error).\n",
+                                (unsigned long) yyk.get()));
+                    yystateStack.yytops.yymarkStackDeleted (yyk);
+                    break;
+                  }
+                else if (yyflag != yyok)
+                  return yyflag;
+              }
+          }
+      }
+    return yyok;
+  }
+
+  /** Perform user action for rule number YYN, with RHS length YYRHSLEN,
+   *  and top stack item YYVSP.  YYVALP points to place to put semantic
+   *  value ($$), and yylocp points to place for location information
+   *  (@@$).  Returns yyok for normal return, yyaccept for YYACCEPT,
+   *  yyerr for YYERROR, yyabort for YYABORT.  */
+  YYRESULTTAG
+  yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
+                YYSTYPE* yyvalp]b4_locuser_formals[)
+  {
+    bool yynormal YY_ATTRIBUTE_UNUSED = !yystateStack.isSplit();
+    int yylow;
+  ]b4_parse_param_use([yyvalp], [yylocp])dnl
+  [  YYUSE (yyrhslen);
+  # undef yyerrok
+  # define yyerrok (yyerrState = 0)
+  # undef YYACCEPT
+  # define YYACCEPT return yyaccept
+  # undef YYABORT
+  # define YYABORT return yyabort
+  # undef YYERROR
+  # define YYERROR return yyerrok, yyerr
+  # undef YYRECOVERING
+  # define YYRECOVERING() (yyerrState != 0)
+  # undef yyclearin
+  # define yyclearin (yychar =
]b4_namespace_ref::b4_parser_class::token::b4_symbol(-2, id)[)
+  # undef YYBACKUP
+  # define YYBACKUP(Token, Value)
         \
+    return yyerror (]b4_yyerror_args[YY_("syntax error: cannot back
up")),     \
+           yyerrok, yyerr
+
+    yylow = 1;
+    if (yyrhslen == 0)
+      *yyvalp = yyval_default;
+    else
+      *yyvalp = yyvsp[YYFILL
(1-yyrhslen)].getState().semanticVal();]b4_locations_if([[
+    /* Default location. */
+    YYLLOC_DEFAULT ((*yylocp), (yyvsp - yyrhslen), yyrhslen);
+    yyerror_range[1].getState().yyloc = *yylocp;
+]])[
+  #if YY_EXCEPTIONS
+    typedef ]b4_namespace_ref[::]b4_parser_class[::syntax_error syntax_error;
+    try
+    {
+  #endif // YY_EXCEPTIONS
+    switch (yyn)
+      {
+  ]b4_user_actions[
+        default: break;
+      }
+  #if YY_EXCEPTIONS
+    }
+    catch (const syntax_error& yyexc)
+      {
+        YYDPRINTF ((stderr, "Caught exception: %s\n",
yyexc.what()));]b4_locations_if([
+        *yylocp = yyexc.location;])[
+        yyerror (]b4_yyerror_args[yyexc.what ());
+        YYERROR;
+      }
+  #endif // YY_EXCEPTIONS
+
+    return yyok;
+  # undef yyerrok
+  # undef YYABORT
+  # undef YYACCEPT
+  # undef YYERROR
+  # undef YYBACKUP
+  # undef yyclearin
+  # undef YYRECOVERING
+  }
+
+  YYRESULTTAG
+  yyresolveStack (]b4_user_formals_no_comma[)
+  {
+    if (yystateStack.isSplit())
+      {
+        int yyn = 0;
+        for (yyGLRState* yys = firstTopState();
+             yys != yystateStack.yysplitPoint;
+             yys = yys->pred())
+          yyn += 1;
+        YYCHK (yyresolveStates (firstTopState(), yyn
+                               ]b4_user_args[));
+      }
+    return yyok;
+  }
+
+  /** Pop the symbols consumed by reduction #YYRULE from the top of stack
+   *  #YYK of *YYSTACKP, and perform the appropriate semantic action on their
+   *  semantic values.  Assumes that all ambiguities in semantic values
+   *  have been previously resolved.  Set *YYVALP to the resulting value,
+   *  and *YYLOCP to the computed location (if any).  Return value is as
+   *  for userAction.  */
+  inline YYRESULTTAG
+  yydoAction (yyStateSetIndex yyk, yyRuleNum yyrule,
+              YYSTYPE* yyvalp]b4_locuser_formals[)
+  {
+    int yynrhs = yyrhsLength (yyrule);
+
+    if (!yystateStack.isSplit())
+      {
+        /* Standard special case: single stack.  */
+        YYASSERT (yyk.get() == 0);
+        yyGLRStackItem* yyrhs = yystateStack.topAt(yyk)->asItem();
+        yystateStack.pop_back(YY_CAST (size_t, yynrhs));
+        yystateStack.setFirstTop(&yystateStack[yystateStack.size() -
1].getState());
+        YY_REDUCE_PRINT ((true, yyrhs, yyk, yyrule]b4_user_args[));
+        return yyuserAction (yyrule, yynrhs, yyrhs,
+                             yyvalp]b4_locuser_args[);
+      }
+    else
+      {
+        yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
+        yyGLRState* yys = yystateStack.topAt(yyk);
+        yyrhsVals[YYMAXRHS +
YYMAXLEFT].getState().setPred(yys);]b4_locations_if([[
+        if (yynrhs == 0)
+          /* Set default location.  */
+          yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].getState().yyloc =
yys->yyloc;]])[
+        for (int yyi = 0; yyi < yynrhs; yyi += 1)
+          {
+            yys = yys->pred();
+            YYASSERT (yys != YY_NULLPTR);
+          }
+        yystateStack.yyupdateSplit (*yys);
+        yystateStack.setTopAt(yyk, yys);
+        YY_REDUCE_PRINT ((false, yyrhsVals + YYMAXRHS + YYMAXLEFT -
1, yyk, yyrule]b4_user_args[));
+        return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS +
YYMAXLEFT - 1,
+                             yyvalp]b4_locuser_args[);
+      }
+  }
+
+  /** Pop items off stack #YYK of *YYSTACKP according to grammar rule YYRULE,
+   *  and push back on the resulting nonterminal symbol.  Perform the
+   *  semantic action associated with YYRULE and store its value with the
+   *  newly pushed state, if YYFORCEEVAL or if *YYSTACKP is currently
+   *  unambiguous.  Otherwise, store the deferred semantic action with
+   *  the new state.  If the new state would have an identical input
+   *  position, LR state, and predecessor to an existing state on the stack,
+   *  it is identified with that existing state, eliminating stack #YYK from
+   *  *YYSTACKP.  In this case, the semantic value is
+   *  added to the options for the existing state's semantic value.
+   */
+  inline YYRESULTTAG
+  yyglrReduce (yyStateSetIndex yyk, yyRuleNum yyrule,
+               bool yyforceEval]b4_user_formals[)
+  {
+    size_t yyposn = topState(yyk)->yyposn;
+
+    if (yyforceEval || !yystateStack.isSplit())
+      {
+        YYSTYPE yysval;]b4_locations_if([[
+        YYLTYPE yyloc;]])[
+
+        YYRESULTTAG yyflag = yydoAction (yyk, yyrule,
&yysval]b4_locuser_args([&yyloc])[);
+        if (yyflag == yyerr && yystateStack.isSplit())
+          {
+            YYDPRINTF ((stderr, "Parse on stack %lu rejected by rule #%d.\n",
+                       (unsigned long) yyk.get(), yyrule - 1));
+          }
+        if (yyflag != yyok)
+          return yyflag;
+        YY_SYMBOL_PRINT ("-> $$ =", YY_CAST
(]b4_namespace_ref::b4_parser_class[::symbol_kind_type, yyr1[yyrule]),
&yysval, &yyloc);
+        yyglrShift (yyk,
+                    yyLRgotoState (topState(yyk)->yylrState,
+                                   yylhsNonterm (yyrule)),
+                    yyposn, &yysval]b4_locations_if([, &yyloc])[);
+      }
+    else
+      {
+        yyGLRState *yys = yystateStack.topAt(yyk);
+        yyGLRState *yys0 = yys;
+        for (int yyn = yyrhsLength (yyrule); 0 < yyn; yyn -= 1)
+          {
+            yys = yys->pred();
+            YYASSERT (yys != YY_NULLPTR);
+          }
+        yystateStack.yyupdateSplit (*yys);
+        yyStateNum yynewLRState = yyLRgotoState (yys->yylrState,
yylhsNonterm (yyrule));
+        YYDPRINTF ((stderr,
+                    "Reduced stack %lu by rule #%d; action deferred.  "
+                    "Now in state %d.\n",
+                    (unsigned long) yyk.get(), yyrule - 1, yynewLRState));
+        for (yyStateSetIndex yyi = yycreateStateSetIndex(0);
yyi.uget() < yystateStack.numTops(); ++yyi)
+          if (yyi != yyk && yystateStack.topAt(yyi) != YY_NULLPTR)
+            {
+              yyGLRState* yysplit = yystateStack.yysplitPoint;
+              yyGLRState* yyp = yystateStack.topAt(yyi);
+              while (yyp != yys && yyp != yysplit
+                     && yyp->yyposn >= yyposn)
+                {
+                  if (yyp->yylrState == yynewLRState
+                      && yyp->pred() == yys)
+                    {
+                      yyaddDeferredAction (yyk, yyp, yys0, yyrule);
+                      yystateStack.yytops.yymarkStackDeleted (yyk);
+                      YYDPRINTF ((stderr, "Merging stack %lu into
stack %lu.\n",
+                                  (unsigned long) yyk.get(),
+                                  (unsigned long) yyi.get()));
+                      return yyok;
+                    }
+                  yyp = yyp->pred();
+                }
+            }
+        yystateStack.setTopAt(yyk, yys);
+        yyglrShiftDefer (yyk, yynewLRState, yyposn, yys0, yyrule);
+      }
+    return yyok;
+  }
+
+  /** Shift stack #YYK of *YYSTACKP, to a new state corresponding to LR
+   *  state YYLRSTATE, at input position YYPOSN, with the (unresolved)
+   *  semantic value of YYRHS under the action for YYRULE.  */
+  inline void
+  yyglrShiftDefer (yyStateSetIndex yyk, yyStateNum yylrState,
+                   size_t yyposn, yyGLRState* yyrhs, yyRuleNum yyrule)
+  {
+    yyGLRState& yynewState = yystateStack.yynewGLRState(
+      yyGLRState(yylrState, yyposn));
+    yynewState.setPred(yystateStack.topAt(yyk));
+    yystateStack.setTopAt(yyk, &yynewState);
+
+    /* Invokes yyreserveStack.  */
+    yyaddDeferredAction (yyk, &yynewState, yyrhs, yyrule);
+  }
+
+  /** Shift to a new state on stack #YYK of *YYSTACKP, corresponding to LR
+   * state YYLRSTATE, at input position YYPOSN, with (resolved) semantic
+   * value *YYVALP and source location *YYLOCP.  */
+  inline void
+  yyglrShift (yyStateSetIndex yyk, yyStateNum yylrState,
+              size_t yyposn,
+              YYSTYPE* yyvalp]b4_locations_if([, YYLTYPE* yylocp])[)
+  {
+    yyGLRState& yynewState = yystateStack.yynewGLRState(
+      yyGLRState(yylrState, yyposn, *yyvalp
+                 ]b4_locations_if([, *yylocp])[));
+    yynewState.setPred(yystateStack.topAt(yyk));
+    yystateStack.setTopAt(yyk, &yynewState);
+    yyreserveGlrStack();
+  }
+
+#if ]b4_api_PREFIX[DEBUG
+  void
+  yypstack (yyStateSetIndex yyk)
+  {
+    yystateStack.yypstates (yystateStack.topAt(yyk));
+  }
+#endif
+
+  yyGLRState* topState(yyStateSetIndex i) {
+    return yystateStack.topAt(i);
+  }
+
+  yyGLRState* firstTopState() {
+    return yystateStack.firstTop();
+  }
+
+ private:
+
+  void popall() {
+    /* If the stack is well-formed, pop the stack until it is empty,
+       destroying its entries as we go.  But free the stack regardless
+       of whether it is well-formed.  */
+    for (yyStateSetIndex k = yycreateStateSetIndex(0); k.uget() <
yystateStack.numTops(); k += 1)
+      if (yystateStack.topAt(k) != YY_NULLPTR)
+        {
+          while (yystateStack.topAt(k) != YY_NULLPTR)
+            {
+              yyGLRState* state = topState(k);]b4_locations_if([[
+                yyerror_range[1].getState().yyloc = state->yyloc;]])[
+              if (state->pred() != YY_NULLPTR)
+                state->destroy ("Cleanup: popping"]b4_user_args[);
+              yystateStack.setTopAt(k, state->pred());
+              yystateStack.pop_back();
+            }
+            break;
+        }
+  }
+
+  /** Resolve the previous YYN states starting at and including state YYS
+   *  on *YYSTACKP. If result != yyok, some states may have been left
+   *  unresolved possibly with empty semantic option chains.  Regardless
+   *  of whether result = yyok, each state has been left with consistent
+   *  data so that destroy can be invoked if necessary.  */
+  YYRESULTTAG
+  yyresolveStates (yyGLRState* yys, int yyn]b4_user_formals[)
+  {
+    if (0 < yyn)
+      {
+        YYASSERT (yys->pred() != YY_NULLPTR);
+        YYCHK (yyresolveStates (yys->pred(), yyn-1]b4_user_args[));
+        if (! yys->yyresolved)
+          YYCHK (yyresolveValue (yys]b4_user_args[));
+      }
+    return yyok;
+  }
+
+  /** Resolve the ambiguity represented in state YYS in *YYSTACKP,
+   *  perform the indicated actions, and set the semantic value of YYS.
+   *  If result != yyok, the chain of semantic options in YYS has been
+   *  cleared instead or it has been left unmodified except that
+   *  redundant options may have been removed.  Regardless of whether
+   *  result = yyok, YYS has been left with consistent data so that
+   *  destroy can be invoked if necessary.  */
+  YYRESULTTAG
+  yyresolveValue (yyGLRState* yys]b4_user_formals[)
+  {
+    yySemanticOption* yybest = yys->firstVal();
+    bool yymerge = false;
+    YYSTYPE yysval;
+    YYRESULTTAG yyflag;]b4_locations_if([
+    YYLTYPE *yylocp = &yys->yyloc;])[
+
+    yySemanticOption* yypPrev = yybest;
+    for (yySemanticOption* yyp = yybest->next();
+         yyp != YY_NULLPTR; )
+      {
+        if (yybest->isIdenticalTo (yyp))
+          {
+            yybest->mergeWith (yyp);
+            yypPrev->setNext(yyp->next());
+          }
+        else
+          {
+            switch (yypreference (yybest, yyp))
+              {
+              case 0:]b4_locations_if([[
+                yyresolveLocations (yys, 1]b4_user_args[);]])[
+                return yystateStack.yyreportAmbiguity (yybest,
yyp]b4_pure_args[);
+                break;
+              case 1:
+                yymerge = true;
+                break;
+              case 2:
+                break;
+              case 3:
+                yybest = yyp;
+                yymerge = false;
+                break;
+              default:
+                /* This cannot happen so it is not worth a YYASSERT (false),
+                   but some compilers complain if the default case is
+                   omitted.  */
+                break;
+              }
+            yypPrev = yyp;
+            yyp = yyp->next();
+          }
+      }
+
+    if (yymerge)
+      {
+        int yyprec = yydprec[yybest->yyrule];
+        yyflag = yyresolveAction (yybest, &yysval]b4_locuser_args[);
+        if (yyflag == yyok)
+          for (yySemanticOption* yyp = yybest->next();
+               yyp != YY_NULLPTR;
+               yyp = yyp->next())
+            {
+              if (yyprec == yydprec[yyp->yyrule])
+                {
+                  YYSTYPE yysval_other;]b4_locations_if([
+                  YYLTYPE yydummy;])[
+                  yyflag = yyresolveAction (yyp,
&yysval_other]b4_locuser_args([&yydummy])[);
+                  if (yyflag != yyok)
+                    {
+                      yyparser.yy_destroy_ ("Cleanup: discarding
incompletely merged value for",
+                                  YY_CAST
(]b4_namespace_ref::b4_parser_class[::symbol_kind_type,
yystos[yys->yylrState]),
+                                  &yysval]b4_locations_if([, yylocp])[);
+                      break;
+                    }
+                  yyuserMerge (yymerger[yyp->yyrule], &yysval, &yysval_other);
+                }
+            }
+      }
+    else
+      yyflag = yyresolveAction (yybest, &yysval]b4_locuser_args([yylocp])[);
+
+    if (yyflag == yyok)
+      {
+        yys->yyresolved = true;
+        yys->semanticVal() = yysval;
+      }
+    else
+      yys->setFirstVal(YY_NULLPTR);
+    return yyflag;
+  }
+
+  /** Resolve the states for the RHS of YYOPT on *YYSTACKP, perform its
+   *  user action, and return the semantic value and location in *YYVALP
+   *  and *YYLOCP.  Regardless of whether result = yyok, all RHS states
+   *  have been destroyed (assuming the user action destroys all RHS
+   *  semantic values if invoked).  */
+  YYRESULTTAG
+  yyresolveAction (yySemanticOption* yyopt, YYSTYPE*
yyvalp]b4_locuser_formals[)
+  {
+    yyGLRState* yyoptState = yyopt->state();
+    yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
+    int yynrhs = yyrhsLength (yyopt->yyrule);
+    YYRESULTTAG yyflag =
+      yyresolveStates (yyoptState, yynrhs]b4_user_args[);
+    if (yyflag != yyok)
+      {
+        for (yyGLRState *yys = yyoptState; yynrhs > 0; yys =
yys->pred(), yynrhs -= 1)
+          yys->destroy ("Cleanup: popping"]b4_user_args[);
+        return yyflag;
+      }
+
+    yyrhsVals[YYMAXRHS +
YYMAXLEFT].getState().setPred(yyopt->state());]b4_locations_if([[
+    if (yynrhs == 0)
+      /* Set default location.  */
+      yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].getState().yyloc =
yyoptState->yyloc;]])[
+    {
+      int yychar_current = yychar;
+      YYSTYPE yylval_current = yylval;]b4_locations_if([
+      YYLTYPE yylloc_current = yylloc;])[
+      yychar = yyopt->yyrawchar;
+      yylval = yyopt->yyval;]b4_locations_if([
+      yylloc = yyopt->yyloc;])[
+      yyflag = yyuserAction (yyopt->yyrule, yynrhs,
+                             yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
yyvalp]b4_locuser_args[);
+      yychar = yychar_current;
+      yylval = yylval_current;]b4_locations_if([
+      yylloc = yylloc_current;])[
+    }
+    return yyflag;
+  }]b4_locations_if([[
+
+  /** Resolve the locations for each of the YYN1 states in *YYSTACKP,
+   *  ending at YYS1.  Has no effect on previously resolved states.
+   *  The first semantic option of a state is always chosen.  */
+  void
+  yyresolveLocations (yyGLRState *yys1, int yyn1]b4_user_formals[)
+  {
+    if (0 < yyn1)
+      {
+        yyresolveLocations (yys1->pred(), yyn1 - 1]b4_user_args[);
+        if (!yys1->yyresolved)
+          {
+            yyGLRStackItem yyrhsloc[1 + YYMAXRHS];
+            int yynrhs;
+            yySemanticOption* yyoption = yys1->firstVal();
+            YYASSERT (yyoption != YY_NULLPTR);
+            yynrhs = yyrhsLength (yyoption->yyrule);
+            if (0 < yynrhs)
+              {
+                yyresolveLocations (yyoption->state(), yynrhs]b4_user_args[);
+                yyGLRState *yys = yyoption->state();
+                for (int yyn = yynrhs; yyn > 0; yyn -= 1)
+                {
+                  yyrhsloc[yyn].getState().yyloc = yys->yyloc;
+                  yys = yys->pred();
+                }
+              }
+            else
+              {
+                /* Both yyresolveAction and yyresolveLocations traverse the GSS
+                   in reverse rightmost order.  It is only necessary to invoke
+                   yyresolveLocations on a subforest for which yyresolveAction
+                   would have been invoked next had an ambiguity not been
+                   detected.  Thus the location of the previous state (but not
+                   necessarily the previous state itself) is guaranteed to be
+                   resolved already.  */
+                yyrhsloc[0].getState().yyloc = yyoption->state()->yyloc;
+              }
+            YYLLOC_DEFAULT ((yys1->yyloc), yyrhsloc, yynrhs);
+          }
+      }
+  }]])[
+
+]b4_parse_param_vars[
+
+};
+#undef yystackp
+#undef YYSTACKEXPANDABLE
+
+
+/** If yychar is empty, fetch the next token.  */
+static inline ]b4_namespace_ref::b4_parser_class[::symbol_kind_type
+yygetToken (int *yycharp][]b4_pure_if([, yyGLRStack*
yystackp])[]b4_user_formals[)
+{
+  ]b4_namespace_ref::b4_parser_class[::symbol_kind_type yytoken;
+]b4_parse_param_use()dnl
+[  if (*yycharp ==
]b4_namespace_ref::b4_parser_class::token::b4_symbol(-2, id)[)
+    {
+      YYDPRINTF ((stderr, "Reading a token\n"));
+#if YY_EXCEPTIONS
+      try
+        {
+#endif // YY_EXCEPTIONS
+          *yycharp = ]b4_lex[;
+#if YY_EXCEPTIONS
+        }
+      catch (const ]b4_namespace_ref[::]b4_parser_class[::syntax_error& yyexc)
+        {
+          YYDPRINTF ((stderr, "Caught exception: %s\n",
yyexc.what()));]b4_locations_if([
+          yylloc = yyexc.location;])[
+          yyerror (]b4_lyyerror_args[yyexc.what ());
+          // Map errors caught in the scanner to the error token, so that error
+          // handling is started.
+          *yycharp =
]b4_namespace_ref::b4_parser_class::token::b4_symbol(1, id)[;
+        }
+#endif // YY_EXCEPTIONS
+    }
+  if (*yycharp <= ]b4_namespace_ref::b4_parser_class::token::b4_symbol(0, id)[)
+    {
+      *yycharp = ]b4_namespace_ref::b4_parser_class::token::b4_symbol(0, id)[;
+      yytoken =
]b4_namespace_ref::b4_parser_class::symbol_kind::b4_symbol(0, kind)[;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (*yycharp);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+  return yytoken;
+}
+
+
+
+static void
+yyuserMerge (int yyn, YYSTYPE* yy0, YYSTYPE* yy1)
+{
+  YYUSE (yy0);
+  YYUSE (yy1);
+
+  switch (yyn)
+    {
+]b4_mergers[
+      default: break;
+    }
+}
+
+                              /* Bison grammar-table manipulation.  */
+
+/** Number of symbols composing the right hand side of rule #RULE.  */
+static inline int
+yyrhsLength (yyRuleNum yyrule)
+{
+  return yyr2[yyrule];
+}
+
+/** The action to take in YYSTATE on seeing YYTOKEN.
+ *  Result R means
+ *    R < 0:  Reduce on rule -R.
+ *    R = 0:  Error.
+ *    R > 0:  Shift to state R.
+ *  Set *YYCONFLICTS to a pointer into yyconfl to a 0-terminated list
+ *  of conflicting reductions.
+ */
+static inline int
+yygetLRActions (yyStateNum yystate,
]b4_namespace_ref::b4_parser_class[::symbol_kind_type yytoken, const
short** yyconflicts)
+{
+  int yyindex = yypact[yystate] + yytoken;
+  if (yytoken ==
]b4_namespace_ref::b4_parser_class[::symbol_kind::]b4_symbol(1,
kind)[)
+    {
+      // This is the error token.
+      *yyconflicts = yyconfl;
+      return 0;
+    }
+  else if (yyisDefaultedState (yystate)
+           || yyindex < 0 || YYLAST < yyindex || yycheck[yyindex] != yytoken)
+    {
+      *yyconflicts = yyconfl;
+      return -yydefact[yystate];
+    }
+  else if (! yytable_value_is_error (yytable[yyindex]))
+    {
+      *yyconflicts = yyconfl + yyconflp[yyindex];
+      return yytable[yyindex];
+    }
+  else
+    {
+      *yyconflicts = yyconfl + yyconflp[yyindex];
+      return 0;
+    }
+}
+
+/** Compute post-reduction state.
+ * \param yystate   the current state
+ * \param yysym     the nonterminal to push on the stack
+ */
+static inline yyStateNum
+yyLRgotoState (yyStateNum yystate,
]b4_namespace_ref::b4_parser_class[::symbol_kind_type yysym)
+{
+  int yyr = yypgoto[yysym - YYNTOKENS] + yystate;
+  if (0 <= yyr && yyr <= YYLAST && yycheck[yyr] == yystate)
+    return yytable[yyr];
+  else
+    return yydefgoto[yysym - YYNTOKENS];
+}
+
+                                /* GLRStacks */
+
+/** Y0 and Y1 represent two possible actions to take in a given
+ *  parsing state; return 0 if no combination is possible,
+ *  1 if user-mergeable, 2 if Y0 is preferred, 3 if Y1 is preferred.  */
+static int
+yypreference (yySemanticOption* y0, yySemanticOption* y1)
+{
+  yyRuleNum r0 = y0->yyrule, r1 = y1->yyrule;
+  int p0 = yydprec[r0], p1 = yydprec[r1];
+
+  if (p0 == p1)
+    {
+      if (yymerger[r0] == 0 || yymerger[r0] != yymerger[r1])
+        return 0;
+      else
+        return 1;
+    }
+  if (p0 == 0 || p1 == 0)
+    return 0;
+  if (p0 < p1)
+    return 3;
+  if (p1 < p0)
+    return 2;
+  return 0;
+}
+
+#define YYCHK1(YYE)                                                          \
+  do {                                                                       \
+    switch (YYE) {                                                           \
+    case yyok:                                                               \
+      break;                                                                 \
+    case yyabort:                                                            \
+      goto yyabortlab;                                                       \
+    case yyaccept:                                                           \
+      goto yyacceptlab;                                                      \
+    case yyerr:                                                              \
+      goto yyuser_error;                                                     \
+    default:                                                                 \
+      goto yybuglab;                                                         \
+    }                                                                        \
+  } while (0)
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)
+{
+  int yyresult;
+  yyGLRStack yystack(YYINITDEPTH]b4_user_args[);
+  yyGLRStack* const yystackp = &yystack;
+  size_t yyposn;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yychar = ]b4_namespace_ref::b4_parser_class::token::b4_symbol(-2, id)[;
+  yylval = yyval_default;]b4_locations_if([
+  yylloc = yyloc_default;])[
+]m4_ifdef([b4_initial_action], [
+b4_dollar_pushdef([yylval], [], [], [yylloc])dnl
+  b4_user_initial_action
+b4_dollar_popdef])[]dnl
+[
+  switch (YYSETJMP (yystack.yyexception_buffer))
+    {
+    case 0: break;
+    case 1: goto yyabortlab;
+    case 2: goto yyexhaustedlab;
+    default: goto yybuglab;
+    }
+  yystack.yyglrShift (yycreateStateSetIndex(0), 0, 0,
&yylval]b4_locations_if([, &yylloc])[);
+  yyposn = 0;
+
+  while (true)
+    {
+      /* For efficiency, we have two loops, the first of which is
+         specialized to deterministic operation (single stack, no
+         potential ambiguity).  */
+      /* Standard mode */
+      while (true)
+        {
+          yyStateNum yystate = yystack.firstTopState()->yylrState;
+          YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+          if (yystate == YYFINAL)
+            goto yyacceptlab;
+          if (yyisDefaultedState (yystate))
+            {
+              yyRuleNum yyrule = yydefaultAction (yystate);
+              if (yyrule == 0)
+                {]b4_locations_if([[
+                  yystack.yyerror_range[1].getState().yyloc = yylloc;]])[
+                  yystack.yyreportSyntaxError (]b4_user_args_no_comma[);
+                  goto yyuser_error;
+                }
+              YYCHK1 (yystack.yyglrReduce (yycreateStateSetIndex(0),
yyrule, true]b4_user_args[));
+            }
+          else
+            {
+              ]b4_namespace_ref::b4_parser_class[::symbol_kind_type
yytoken = ]b4_yygetToken_call;[
+              const short* yyconflicts;
+              int yyaction = yygetLRActions (yystate, yytoken, &yyconflicts);
+              if (*yyconflicts != 0)
+                break;
+              if (yyisShiftAction (yyaction))
+                {
+                  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+                  yychar =
]b4_namespace_ref::b4_parser_class::token::b4_symbol(-2, id)[;
+                  yyposn += 1;
+                  yystack.yyglrShift (yycreateStateSetIndex(0),
yyaction, yyposn, &yylval]b4_locations_if([, &yylloc])[);
+                  if (0 < yystack.yyerrState)
+                    yystack.yyerrState -= 1;
+                }
+              else if (yyisErrorAction (yyaction))
+                {]b4_locations_if([[
+                  yystack.yyerror_range[1].getState().yyloc = yylloc;]])[
+                  /* Don't issue an error message again for exceptions
+                     thrown from the scanner.  */
+                  if (yychar !=
]b4_namespace_ref::b4_parser_class::token::b4_symbol(1, id)[)
+                    yystack.yyreportSyntaxError (]b4_user_args_no_comma[);
+                  goto yyuser_error;
+                }
+              else
+                YYCHK1 (yystack.yyglrReduce
(yycreateStateSetIndex(0), -yyaction, true]b4_user_args[));
+            }
+        }
+
+      while (true)
+        {
+          ]b4_namespace_ref::b4_parser_class[::symbol_kind_type
yytoken_to_shift;
+
+          for (yyStateSetIndex yys = yycreateStateSetIndex(0);
yys.uget() < yystack.yystateStack.numTops(); ++yys)
+            yystackp->yystateStack.yytops.setLookaheadNeeds(yys,
yychar != ]b4_namespace_ref::b4_parser_class::token::b4_symbol(-2,
id)[);
+
+          /* yyprocessOneStack returns one of three things:
+
+              - An error flag.  If the caller is yyprocessOneStack, it
+                immediately returns as well.  When the caller is finally
+                yyparse, it jumps to an error label via YYCHK1.
+
+              - yyok, but yyprocessOneStack has invoked yymarkStackDeleted
+                (yys), which sets the top state of yys to NULL.  Thus,
+                yyparse's following invocation of yyremoveDeletes will remove
+                the stack.
+
+              - yyok, when ready to shift a token.
+
+             Except in the first case, yyparse will invoke yyremoveDeletes and
+             then shift the next token onto all remaining stacks.  This
+             synchronization of the shift (that is, after all preceding
+             reductions on all stacks) helps prevent double destructor calls
+             on yylval in the event of memory exhaustion.  */
+
+          for (yyStateSetIndex yys = yycreateStateSetIndex(0);
yys.uget() < yystack.yystateStack.numTops(); ++yys)
+            YYCHK1 (yystack.yyprocessOneStack (yys, yyposn]b4_lpure_args[));
+          yystack.yystateStack.yytops.yyremoveDeletes ();
+          if (yystack.yystateStack.yytops.size() == 0)
+            {
+              yystack.yystateStack.yytops.yyundeleteLastStack ();
+              if (yystack.yystateStack.yytops.size() == 0)
+                yystack.yyFail (YY_("syntax error")][]b4_lpure_args[);
+              YYCHK1 (yystack.yyresolveStack (]b4_user_args_no_comma[));
+              YYDPRINTF ((stderr, "Returning to deterministic
operation.\n"));]b4_locations_if([[
+              yystack.yyerror_range[1].getState().yyloc = yylloc;]])[
+              yystack.yyreportSyntaxError (]b4_user_args_no_comma[);
+              goto yyuser_error;
+            }
+
+          /* If any yyglrShift call fails, it will fail after shifting.  Thus,
+             a copy of yylval will already be on stack 0 in the event of a
+             failure in the following loop.  Thus, yychar is set to
]b4_symbol(-2, id)[
+             before the loop to make sure the user destructor for yylval isn't
+             called twice.  */
+          yytoken_to_shift = YYTRANSLATE (yychar);
+          yychar =
]b4_namespace_ref::b4_parser_class::token::b4_symbol(-2, id)[;
+          yyposn += 1;
+          for (yyStateSetIndex yys = yycreateStateSetIndex(0);
yys.uget() < yystack.yystateStack.numTops(); ++yys)
+            {
+              yyStateNum yystate = yystack.topState(yys)->yylrState;
+              const short* yyconflicts;
+              int yyaction = yygetLRActions (yystate, yytoken_to_shift,
+                              &yyconflicts);
+              /* Note that yyconflicts were handled by yyprocessOneStack.  */
+              YYDPRINTF ((stderr, "On stack %lu, ", (unsigned long)
yys.get()));
+              YY_SYMBOL_PRINT ("shifting", yytoken_to_shift, &yylval, &yylloc);
+              yystack.yyglrShift (yys, yyaction, yyposn,
+                          &yylval]b4_locations_if([, &yylloc])[);
+              YYDPRINTF ((stderr, "Stack %lu now in state #%d\n",
+                          (unsigned long) yys.get(),
+                          yystack.topState(yys)->yylrState));
+            }
+
+          if (yystack.yystateStack.yytops.size() == 1)
+            {
+              YYCHK1 (yystack.yyresolveStack (]b4_user_args_no_comma[));
+              YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
+              yystack.yystateStack.yycompressStack ();
+              break;
+            }
+        }
+      continue;
+    yyuser_error:
+      yystack.yyrecoverSyntaxError (]b4_user_args_no_comma[);
+      yyposn = yystack.firstTopState()->yyposn;
+    }
+
+ yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+ yybuglab:
+  YYASSERT (false);
+  goto yyabortlab;
+
+ yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+ yyexhaustedlab:
+  yyerror (]b4_lyyerror_args[YY_("memory exhausted"));
+  yyresult = 2;
+  goto yyreturn;
+
+ yyreturn:
+  return yyresult;
+}
+
+
+/* DEBUGGING ONLY */
+#if ]b4_api_PREFIX[DEBUG
+static void
+yypstack (yyGLRStack* yystackp, size_t yyk)
+{
+  yystackp->yypstack(yycreateStateSetIndex(YY_CAST(std::ptrdiff_t, yyk)));
+}
+static void yypdumpstack (struct yyGLRStack* yystackp) {
+  yystackp->yypdumpstack();
+}
+
+#endif
+
+#undef yylval
+#undef yychar
+#undef yynerrs]b4_locations_if([
+#undef yylloc])
+
+m4_if(b4_prefix, [yy], [],
+[[/* Substitute the variable and function names.  */
+#define yyparse ]b4_prefix[parse
+#define yylex   ]b4_prefix[lex
+#define yyerror ]b4_prefix[error
+#define yylval  ]b4_prefix[lval
+#define yychar  ]b4_prefix[char
+#define yydebug ]b4_prefix[debug
+#define yynerrs ]b4_prefix[nerrs]b4_locations_if([[
+#define yylloc  ]b4_prefix[lloc]])])[
+
+
+/*------------------.
+| Report an error.  |
+`------------------*/
+
+static void
+yyerror (]b4_locations_if([[const
]b4_namespace_ref::b4_parser_class[::location_type *yylocationp,
+         ]])[]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param),
+         ])[const std::string& msg)
+{
+]b4_parse_param_use[]dnl
+[  yyparser.error (]b4_locations_if([[*yylocationp, ]])[msg);
+}
+
+
+]b4_namespace_open[
+]dnl In this section, the parse params are the original parse_params.
+m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
+[  /// Build a parser object.
+  ]b4_parser_class::b4_parser_class[
(]b4_parse_param_decl[)]m4_ifset([b4_parse_param], [
+    :])[
+#if ]b4_api_PREFIX[DEBUG
+    ]m4_ifset([b4_parse_param], [  ], [ :])[yycdebug_
(&std::cerr)]m4_ifset([b4_parse_param], [,])[
+#endif]b4_parse_param_cons[
+  {}
+
+  ]b4_parser_class::~b4_parser_class[ ()
+  {}
+
+  ]b4_parser_class[::syntax_error::~syntax_error () YY_NOEXCEPT YY_NOTHROW
+  {}
+
+  int
+  ]b4_parser_class[::operator() ()
+  {
+    return parse ();
+  }
+
+  int
+  ]b4_parser_class[::parse ()
+  {
+    return ::yyparse (*this]b4_user_args[);
+  }
+
+]b4_parse_error_bmatch([custom\|detailed],
+[[  const char *
+  ]b4_parser_class[::symbol_name (symbol_kind_type yysymbol)
+  {
+    static const char *const yy_sname[] =
+    {
+    ]b4_symbol_names[
+    };]b4_has_translations_if([[
+    /* YYTRANSLATABLE[SYMBOL-NUM] -- Whether YY_SNAME[SYMBOL-NUM] is
+       internationalizable.  */
+    static ]b4_int_type_for([b4_translatable])[ yytranslatable[] =
+    {
+    ]b4_translatable[
+    };
+    return (yysymbol < YYNTOKENS && yytranslatable[yysymbol]
+            ? _(yy_sname[yysymbol])
+            : yy_sname[yysymbol]);]], [[
+    return yy_sname[yysymbol];]])[
+  }
+]],
+[simple],
+[[#if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
+  const char *
+  ]b4_parser_class[::symbol_name (symbol_kind_type yysymbol)
+  {
+    return yytname_[yysymbol];
+  }
+#endif // #if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
+]],
+[verbose],
+[[  /* Return YYSTR after stripping away unnecessary quotes and
+     backslashes, so that it's suitable for yyerror.  The heuristic is
+     that double-quoting is unnecessary unless the string contains an
+     apostrophe, a comma, or backslash (other than backslash-backslash).
+     YYSTR is taken from yytname.  */
+  std::string
+  ]b4_parser_class[::yytnamerr_ (const char *yystr)
+  {
+    if (*yystr == '"')
+      {
+        std::string yyr;
+        char const *yyp = yystr;
+
+        for (;;)
+          switch (*++yyp)
+            {
+            case '\'':
+            case ',':
+              goto do_not_strip_quotes;
+
+            case '\\':
+              if (*++yyp != '\\')
+                goto do_not_strip_quotes;
+              else
+                goto append;
+
+            append:
+            default:
+              yyr += *yyp;
+              break;
+
+            case '"':
+              return yyr;
+            }
+      do_not_strip_quotes: ;
+      }
+
+    return yystr;
+  }
+
+  std::string
+  ]b4_parser_class[::symbol_name (symbol_kind_type yysymbol)
+  {
+    return yytnamerr_ (yytname_[yysymbol]);
+  }
+]])[
+
+]b4_parse_error_bmatch([simple\|verbose],
+[[#if ]b4_api_PREFIX[DEBUG]b4_tname_if([[ || 1]])[
+  // YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+  // First, the terminals, then, starting at \a YYNTOKENS, nonterminals.
+  const char*
+  const ]b4_parser_class[::yytname_[] =
+  {
+  ]b4_tname[
+  };
+#endif
+]])[
+
+  void
+  ]b4_parser_class[::yy_destroy_ (const char* yymsg, symbol_kind_type yykind,
+                           const semantic_type* yyvaluep]b4_locations_if([[,
+                           const location_type* yylocationp]])[)
+  {
+    YYUSE (yyvaluep);]b4_locations_if([[
+    YYUSE (yylocationp);]])[
+    if (!yymsg)
+      yymsg = "Deleting";
+    ]b4_namespace_ref::b4_parser_class[& yyparser = *this;
+    YYUSE (yyparser);
+    YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
+
+    YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+    ]b4_symbol_actions([destructor])[
+    YY_IGNORE_MAYBE_UNINITIALIZED_END
+  }
+
+#if ]b4_api_PREFIX[DEBUG
+  /*--------------------.
+  | Print this symbol.  |
+  `--------------------*/
+
+  void
+  ]b4_parser_class[::yy_symbol_value_print_ (symbol_kind_type yykind,
+                           const semantic_type* yyvaluep]b4_locations_if([[,
+                           const location_type* yylocationp]])[) const
+  {]b4_locations_if([[
+    YYUSE (yylocationp);]])[
+    YYUSE (yyvaluep);
+    std::ostream& yyo = debug_stream ();
+    std::ostream& yyoutput = yyo;
+    YYUSE (yyoutput);
+    ]b4_symbol_actions([printer])[
+  }
+
+  void
+  ]b4_parser_class[::yy_symbol_print_ (symbol_kind_type yykind,
+                           const semantic_type* yyvaluep]b4_locations_if([[,
+                           const location_type* yylocationp]])[) const
+  {
+    *yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm")
+               << ' ' <<
]b4_namespace_ref::b4_parser_class[::symbol_name (yykind) << "
("]b4_locations_if([[
+               << *yylocationp << ": "]])[;
+    yy_symbol_value_print_ (yykind, yyvaluep]b4_locations_if([[,
yylocationp]])[);
+    *yycdebug_ << ')';
+  }
+
+  std::ostream&
+  ]b4_parser_class[::debug_stream () const
+  {
+    return *yycdebug_;
+  }
+
+  void
+  ]b4_parser_class[::set_debug_stream (std::ostream& o)
+  {
+    yycdebug_ = &o;
+  }
+
+
+  ]b4_parser_class[::debug_level_type
+  ]b4_parser_class[::debug_level () const
+  {
+    return yydebug;
+  }
+
+  void
+  ]b4_parser_class[::set_debug_level (debug_level_type l)
+  {
+    // Actually, it is yydebug which is really used.
+    yydebug = l;
+  }
+
+#endif
+]m4_popdef([b4_parse_param])dnl
+b4_namespace_close[]dnl
+b4_glr_cc_cleanup[]dnl
+b4_epilogue[]dnl
+b4_output_end
+
+
+m4_popdef([b4_parse_param])
diff --git a/src/reader.c b/src/reader.c
index 059e9341..1526ab4e 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -297,6 +297,7 @@ grammar_rule_check_and_complete (symbol_list *r)
               const bool is_cxx =
                 STREQ (language->language, "c++")
                 || (skeleton && (STREQ (skeleton, "glr.cc")
+                                 || STREQ (skeleton, "glr2.cc")
                                  || STREQ (skeleton, "lalr1.cc")));
               if (is_cxx)
                 {
diff --git a/tests/actions.at b/tests/actions.at
index d90851de..9392da63 100644
--- a/tests/actions.at
+++ b/tests/actions.at
@@ -371,6 +371,7 @@ AT_TEST([glr.c])
 AT_TEST([glr.c], [%define api.pure])
 AT_TEST([lalr1.cc])
 AT_TEST([glr.cc])
+AT_TEST([glr2.cc])

 ## A very different test, based on PostgreSQL's implementation of the
 ## locations.  See
@@ -474,7 +475,7 @@ AT_CLEANUP
 ])

 ## FIXME: test Java and D.
-m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc])
+m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc], [glr2.cc])

 m4_popdef([AT_TEST])

@@ -1055,6 +1056,9 @@ AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines
%skeleton "lalr1.cc"], [ with union])
 AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "glr.cc"])
 AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "glr.cc"], [ with union])

+AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "glr2.cc"])
+AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "glr2.cc"], [ with union])
+


 ## ----------------------------------------- ##
@@ -1852,7 +1856,7 @@ AT_BISON_OPTION_POPDEFS
 AT_CLEANUP
 ])

-m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc])
+m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc], [glr2.cc])
 m4_popdef([AT_TEST])

 ## -------------------------------------------------- ##
diff --git a/tests/c++.at b/tests/c++.at
index 949bdeb6..a5fc7d93 100644
--- a/tests/c++.at
+++ b/tests/c++.at
@@ -1062,6 +1062,7 @@ AT_CLEANUP

 AT_TEST([%skeleton "lalr1.cc"])
 AT_TEST([%skeleton "glr.cc"])
+AT_TEST([%skeleton "glr2.cc"])

 m4_popdef([AT_TEST])

diff --git a/tests/calc.at b/tests/calc.at
index ee75bf27..7047acf3 100644
--- a/tests/calc.at
+++ b/tests/calc.at
@@ -1198,6 +1198,7 @@ AT_BANNER([[GLR C++ Calculator.]])

 # Again, we try also using %skeleton.
 AT_CHECK_CALC([%skeleton "glr.cc"])
+AT_CHECK_CALC([%skeleton "glr2.cc"])

 m4_define([AT_CHECK_CALC_GLR_CC],
 [AT_CHECK_CALC([%language "C++" %glr-parser] $@)])
diff --git a/tests/conflicts.at b/tests/conflicts.at
index 2b6f4315..07e4f7b1 100644
--- a/tests/conflicts.at
+++ b/tests/conflicts.at
@@ -1093,7 +1093,7 @@ AT_CLEANUP
 ])

 ## FIXME: test Java and D.
-m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc])
+m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc], [glr2.cc])

 m4_popdef([AT_TEST])

diff --git a/tests/input.at b/tests/input.at
index cfa065ad..9d9f6a28 100644
--- a/tests/input.at
+++ b/tests/input.at
@@ -2865,6 +2865,7 @@ AT_BISON_CHECK([[-d               input.y]])
 AT_BISON_CHECK([[-d -S glr.c      input.y]])
 AT_BISON_CHECK([[-d -S lalr1.cc   input.y]])
 AT_BISON_CHECK([[-d -S glr.cc     input.y]])
+AT_BISON_CHECK([[-d -S glr2.cc    input.y]])
 AT_BISON_CHECK([[   -S lalr1.java input.y]])
 ])

diff --git a/tests/local.at b/tests/local.at
index 5465bd85..89cbf7da 100644
--- a/tests/local.at
+++ b/tests/local.at
@@ -237,7 +237,7 @@ m4_pushdef([AT_LANG],
 m4_pushdef([AT_C_IF],
 [m4_if(AT_LANG, [c], [$1], [$2])])
 m4_pushdef([AT_GLR_IF],
-[m4_bmatch([$3], [%glr-parser\|%skeleton "glr\..*"], [$1], [$2])])
+[m4_bmatch([$3], [%glr-parser\|%skeleton "glr.*"], [$1], [$2])])
 m4_pushdef([AT_LALR1_CC_IF],
 [AT_CXX_IF([AT_GLR_IF([$2], [$1])], [$2])])
 m4_pushdef([AT_GLR_CC_IF],
diff --git a/tests/regression.at b/tests/regression.at
index 099b39a0..6efeb1cc 100644
--- a/tests/regression.at
+++ b/tests/regression.at
@@ -1557,6 +1557,7 @@ AT_TEST([yacc.c])
 AT_TEST([glr.c])
 AT_TEST([lalr1.cc])
 AT_TEST([glr.cc])
+AT_TEST([glr2.cc])

 m4_popdef([AT_TEST])

diff --git a/tests/scanner.at b/tests/scanner.at
index 9ce13300..5ad18729 100644
--- a/tests/scanner.at
+++ b/tests/scanner.at
@@ -333,7 +333,7 @@ AT_BISON_OPTION_POPDEFS
 AT_CLEANUP
 ])

-m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc],
[lalr1.java], [lalr1.d]],
+m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc],
[glr2.cc], [lalr1.java], [lalr1.d]],
 [AT_TEST([%skeleton "]b4_skel["])
  AT_TEST([%skeleton "]b4_skel[" %define api.token.raw])])

diff --git a/tests/synclines.at b/tests/synclines.at
index 431af776..b2cfac5c 100644
--- a/tests/synclines.at
+++ b/tests/synclines.at
@@ -437,7 +437,7 @@ AT_BISON_OPTION_POPDEFS
 AT_CLEANUP
 ])

-m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc])
+m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc], [glr2.cc])

 m4_popdef([AT_TEST])

@@ -494,7 +494,7 @@ AT_BISON_OPTION_POPDEFS
 AT_CLEANUP
 ])

-m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc])
+m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc], [glr2.cc])

 m4_popdef([AT_TEST])

diff --git a/tests/types.at b/tests/types.at
index d92c4a43..00f48a33 100644
--- a/tests/types.at
+++ b/tests/types.at
@@ -135,7 +135,7 @@ m4_pushdef([AT_TEST],
  _AT_TEST([$1 %defines], [$2], [$3], [$4], [$5], [$6], [$7])
 ])

-m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]],
+m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc], [glr2.cc]],
  [# A built-in type.
   AT_TEST([%skeleton "]b4_skel["
            %define api.value.type {double}],
-- 
2.28.0

-- 
Valentin



reply via email to

[Prev in Thread] Current Thread [Next in Thread]