blob: ac4f7a78507c49250d12dc789e0acf70ec61ff70 [file] [log] [blame]
# C++ skeleton for Bison
# Copyright (C) 2002-2013 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/>.
## --------- ##
## variant. ##
## --------- ##
# b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS])
# ------------------------------------------------
# Run some ACTION ("build", or "destroy") on YYVAL of symbol type
# YYTYPE.
m4_define([b4_symbol_variant],
[m4_pushdef([b4_dollar_dollar],
[$2.$3< $][3 > (m4_shift3($@))])dnl
switch ($1)
{
b4_type_foreach([b4_type_action_])[]dnl
default:
break;
}
m4_popdef([b4_dollar_dollar])dnl
])
# _b4_char_sizeof_counter
# -----------------------
# A counter used by _b4_char_sizeof_dummy to create fresh symbols.
m4_define([_b4_char_sizeof_counter],
[0])
# _b4_char_sizeof_dummy
# ---------------------
# At each call return a new C++ identifier.
m4_define([_b4_char_sizeof_dummy],
[m4_define([_b4_char_sizeof_counter], m4_incr(_b4_char_sizeof_counter))dnl
dummy[]_b4_char_sizeof_counter])
# b4_char_sizeof(SYMBOL-NUMS)
# ---------------------------
# To be mapped on the list of type names to produce:
#
# char dummy1[sizeof(type_name_1)];
# char dummy2[sizeof(type_name_2)];
#
# for defined type names.
m4_define([b4_char_sizeof],
[b4_symbol_if([$1], [has_type],
[
m4_map([ b4_symbol_tag_comment], [$@])dnl
char _b4_char_sizeof_dummy@{sizeof(b4_symbol([$1], [type]))@};
])])
# b4_variant_includes
# -------------------
# The needed includes for variants support.
m4_define([b4_variant_includes],
[b4_parse_assert_if([[#include <typeinfo>]])[
#ifndef YYASSERT
# include <cassert>
# define YYASSERT assert
#endif
]])
# b4_variant_define
# -----------------
# Define "variant".
m4_define([b4_variant_define],
[[ /// A char[S] buffer to store and retrieve objects.
///
/// Sort of a variant, but does not keep track of the nature
/// of the stored data, since that knowledge is available
/// via the current state.
template <size_t S>
struct variant
{
/// Type of *this.
typedef variant<S> self_type;
/// Empty construction.
variant ()]b4_parse_assert_if([
: yytname_ (YY_NULL)])[
{}
/// Construct and fill.
template <typename T>
variant (const T& t)]b4_parse_assert_if([
: yytname_ (typeid (T).name ())])[
{
YYASSERT (sizeof (T) <= S);
new (yyas_<T> ()) T (t);
}
/// Destruction, allowed only if empty.
~variant ()
{]b4_parse_assert_if([
YYASSERT (!yytname_);
])[}
/// Instantiate an empty \a T in here.
template <typename T>
T&
build ()
{]b4_parse_assert_if([
YYASSERT (!yytname_);
YYASSERT (sizeof (T) <= S);
yytname_ = typeid (T).name ();])[
return *new (yyas_<T> ()) T;
}
/// Instantiate a \a T in here from \a t.
template <typename T>
T&
build (const T& t)
{]b4_parse_assert_if([
YYASSERT (!yytname_);
YYASSERT (sizeof (T) <= S);
yytname_ = typeid (T).name ();])[
return *new (yyas_<T> ()) T (t);
}
/// Accessor to a built \a T.
template <typename T>
T&
as ()
{]b4_parse_assert_if([
YYASSERT (yytname_ == typeid (T).name ());
YYASSERT (sizeof (T) <= S);])[
return *yyas_<T> ();
}
/// Const accessor to a built \a T (for %printer).
template <typename T>
const T&
as () const
{]b4_parse_assert_if([
YYASSERT (yytname_ == typeid (T).name ());
YYASSERT (sizeof (T) <= S);])[
return *yyas_<T> ();
}
/// Swap the content with \a other, of same type.
///
/// Both variants must be built beforehand, because swapping the actual
/// data requires reading it (with as()), and this is not possible on
/// unconstructed variants: it would require some dynamic testing, which
/// should not be the variant's responsability.
/// Swapping between built and (possibly) non-built is done with
/// variant::move ().
template <typename T>
void
swap (self_type& other)
{]b4_parse_assert_if([
YYASSERT (yytname_);
YYASSERT (yytname_ == other.yytname_);])[
std::swap (as<T> (), other.as<T> ());
}
/// Move the content of \a other to this.
///
/// Destroys \a other.
template <typename T>
void
move (self_type& other)
{]b4_parse_assert_if([
YYASSERT (!yytname_);])[
build<T> ();
swap<T> (other);
other.destroy<T> ();
}
/// Copy the content of \a other to this.
template <typename T>
void
copy (const self_type& other)
{
build<T> (other.as<T> ());
}
/// Destroy the stored \a T.
template <typename T>
void
destroy ()
{
as<T> ().~T ();]b4_parse_assert_if([
yytname_ = YY_NULL;])[
}
private:
/// Prohibit blind copies.
self_type& operator=(const self_type&);
variant (const self_type&);
/// Accessor to raw memory as \a T.
template <typename T>
T*
yyas_ ()
{
void *yyp = yybuffer_.yyraw;
return static_cast<T*> (yyp);
}
/// Const accessor to raw memory as \a T.
template <typename T>
const T*
yyas_ () const
{
const void *yyp = yybuffer_.yyraw;
return static_cast<const T*> (yyp);
}
union
{
/// Strongest alignment constraints.
long double yyalign_me;
/// A buffer large enough to store any of the semantic values.
char yyraw[S];
} yybuffer_;]b4_parse_assert_if([
/// Whether the content is built: if defined, the name of the stored type.
const char *yytname_;])[
};
]])
## -------------------------- ##
## Adjustments for variants. ##
## -------------------------- ##
# b4_value_type_declare
# ---------------------
# Declare semantic_type.
m4_define([b4_value_type_declare],
[[ /// An auxiliary type to compute the largest semantic type.
union union_type
{]b4_type_foreach([b4_char_sizeof])[};
/// Symbol semantic values.
typedef variant<sizeof(union_type)> semantic_type;][]dnl
])
# How the semantic value is extracted when using variants.
# b4_symbol_value(VAL, [TYPE])
# ----------------------------
m4_define([b4_symbol_value],
[m4_ifval([$2],
[$1.as< $2 > ()],
[$1])])
# b4_symbol_value_template(VAL, [TYPE])
# -------------------------------------
# Same as b4_symbol_value, but used in a template method.
m4_define([b4_symbol_value_template],
[m4_ifval([$2],
[$1.template as< $2 > ()],
[$1])])
## ------------- ##
## make_SYMBOL. ##
## ------------- ##
# b4_symbol_constructor_declare_(SYMBOL-NUMBER)
# ---------------------------------------------
# Declare the overloaded version of make_symbol for the (common) type of
# these SYMBOL-NUMBERS. Use at class-level.
m4_define([b4_symbol_constructor_declare_],
[b4_symbol_if([$1], [is_token], [b4_symbol_if([$1], [has_id],
[ static inline
symbol_type
make_[]b4_symbol_([$1], [id]) (dnl
b4_join(b4_symbol_if([$1], [has_type],
[const b4_symbol([$1], [type])& v]),
b4_locations_if([const location_type& l])));
])])])
# b4_symbol_constructor_declare
# -----------------------------
# Declare symbol constructors for all the value types.
# Use at class-level.
m4_define([b4_symbol_constructor_declare],
[ // Symbol constructors declarations.
b4_symbol_foreach([b4_symbol_constructor_declare_])])
# b4_symbol_constructor_define_(SYMBOL-NUMBER)
# --------------------------------------------
# Define symbol constructor for this SYMBOL-NUMBER.
m4_define([b4_symbol_constructor_define_],
[b4_symbol_if([$1], [is_token], [b4_symbol_if([$1], [has_id],
[ b4_parser_class_name::symbol_type
b4_parser_class_name::make_[]b4_symbol_([$1], [id]) (dnl
b4_join(b4_symbol_if([$1], [has_type],
[const b4_symbol([$1], [type])& v]),
b4_locations_if([const location_type& l])))
{
return symbol_type (b4_join([token::b4_symbol([$1], [id])],
b4_symbol_if([$1], [has_type], [v]),
b4_locations_if([l])));
}
])])])
# b4_basic_symbol_constructor_declare
# -----------------------------------
# Generate a constructor declaration for basic_symbol from given type.
m4_define([b4_basic_symbol_constructor_declare],
[[
basic_symbol (]b4_join(
[typename Base::kind_type t],
b4_symbol_if([$1], [has_type], const b4_symbol([$1], [type])[ v]),
b4_locations_if([const location_type& l]))[);
]])
# b4_basic_symbol_constructor_define
# ----------------------------------
# Generate a constructor implementation for basic_symbol from given type.
m4_define([b4_basic_symbol_constructor_define],
[[
template <typename Base>
]b4_parser_class_name[::basic_symbol<Base>::basic_symbol (]b4_join(
[typename Base::kind_type t],
b4_symbol_if([$1], [has_type], const b4_symbol([$1], [type])[ v]),
b4_locations_if([const location_type& l]))[)
: Base (t)
, value (]b4_symbol_if([$1], [has_type], [v])[)]b4_locations_if([
, location (l)])[
{}
]])
# b4_symbol_constructor_define
# ----------------------------
# Define the overloaded versions of make_symbol for all the value types.
m4_define([b4_symbol_constructor_define],
[ // Implementation of make_symbol for each symbol type.
b4_symbol_foreach([b4_symbol_constructor_define_])])