]) # b4_variant_if
+# b4_assert_if([IF-ASSERTIONS-ARE-USED], [IF-NOT])
+# ----------------------------------------------------
+m4_define([b4_assert_if],
+[b4_percent_define_ifdef([[assert]], [$1], [$2])])
+
+
# b4_rhs_value(RULE-LENGTH, NUM, [TYPE])
# --------------------------------------
# Expansion of $<TYPE>NUM, where the current rule has RULE-LENGTH
# Expansion of @NUM, where the current rule has RULE-LENGTH symbols
# on RHS.
m4_define([b4_rhs_location],
-[(yystack_@{($1) - ($2)@}.location)])
+[yystack_@{($1) - ($2)@}.location])
# b4_symbol_actions(FILENAME, LINENO,
])])
-# b4_symbol_variant(YYTYPE, YYVAL, ACTION)
-# ----------------------------------------
+# 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>()])dnl
+ [$2.$3<$][3>(m4_shift3($@))])dnl
switch ($1)
{
m4_map([b4_symbol_action_], m4_defn([b4_type_names]))
]b4_percent_code_get([[requires]])[
+]b4_assert_if([#include <cassert>])[
#include <string>
#include <iostream>
#include "stack.hh"
/// via the current state.
template <size_t S>
struct variant
- {
+ {]b4_assert_if([
+ /// Whether something is contained.
+ bool built;
+
+ /// Initially uninitialized.
+ variant ()
+ : built(false)
+ {}])[
+
/// Instantiate a \a T in here.
template <typename T>
inline T&
build()
- {
+ {]b4_assert_if([
+ assert(!built);
+ built = true;])[
return *new (buffer) T;
}
- /// Destroy the stored \a T.
- template <typename T>
- inline void
- destroy()
- {
- reinterpret_cast<T&>(buffer).~T();
- }
-
/// Accessor to a built \a T.
template <typename T>
inline T&
as()
- {
+ {]b4_assert_if([
+ assert(built);])[
return reinterpret_cast<T&>(buffer);
}
template <typename T>
inline const T&
as() const
- {
+ {]b4_assert_if([
+ assert(built);])[
return reinterpret_cast<const T&>(buffer);
}
+ /// Swap the content with \a other.
+ template <typename T>
+ inline void
+ swap(variant<S>& other)
+ {
+ std::swap(as<T>(), other.as<T>());
+ }
+
+ /// Assign the content of \a other to this.
+ /// Destroys \a other.
+ template <typename T>
+ inline void
+ build(variant<S>& other)
+ {
+ build<T>();
+ swap<T>(other);
+ other.destroy<T>();
+ }
+
+ /// Destroy the stored \a T.
+ template <typename T>
+ inline void
+ destroy()
+ {
+ as<T>().~T();]b4_assert_if([
+ built = false;])[
+ }
+
/// A buffer large enough to store any of the semantic values.
char buffer[S];
};
/// \brief Reclaim the memory associated to a symbol.
/// \param yymsg Why this token is reclaimed.
+ /// If null, nothing is printed at all.
/// \param yytype The symbol type.
/// \param yyvalue Its semantic value.
/// \param yylocation Its location.
# define YYCDEBUG if (yydebug_) (*yycdebug_)
# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug_) \
+ do { \
+ if (yydebug_) \
{ \
*yycdebug_ << Title << ' '; \
yy_symbol_print_ ((Type), (Value), (Location)); \
*yycdebug_ << std::endl; \
} \
-} while (false)
+ } while (false)
# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug_) \
- yy_reduce_print_ (Rule); \
-} while (false)
+ do { \
+ if (yydebug_) \
+ yy_reduce_print_ (Rule); \
+ } while (false)
# define YY_STACK_PRINT() \
-do { \
- if (yydebug_) \
- yystack_print_ (); \
-} while (false)
+ do { \
+ if (yydebug_) \
+ yystack_print_ (); \
+ } while (false)
#else /* !YYDEBUG */
# define YYCDEBUG if (false) std::cerr
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_REDUCE_PRINT(Rule)
-# define YY_STACK_PRINT()
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) static_cast<void>(0)
+# define YY_REDUCE_PRINT(Rule) static_cast<void>(0)
+# define YY_STACK_PRINT() static_cast<void>(0)
#endif /* !YYDEBUG */
YYUSE (yyvalue);
YYUSE (yylocation);
- YY_SYMBOL_PRINT (yymsg, yytype, yyvalue, yylocation);
+ if (yymsg)
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvalue, yylocation);
+ // User destructor.
switch (yytype)
{
]m4_map([b4_symbol_actions], m4_defn([b4_symbol_destructors]))[
default:
break;
- }
+ }]b4_variant_if([
+
+ // Type destructor.
+ b4_symbol_variant([[yytype]], [[yyvalue]], [[destroy]])])[
}
]b4_parser_class_name[::data_type::data_type ()
]b4_parser_class_name[::yypush_ (state_type s,
semantic_type& v, const location_type& l)
{
- yystack_.push (data_type (s, v, l));
+]b4_variant_if(
+[[ yystack_.push (data_type (s, semantic_type(), l));
+ ]b4_symbol_variant([[yystos_[s]]], [[yystack_[0].value]], [build], [v])],
+[ yystack_.push (data_type (s, v, l));])[
}
void
break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1_[yyn], yyval, yyloc);
-
-]b4_variant_if([
+]b4_variant_if([[
// Destroy the lhs symbols.
for (int i = 0; i < yylen; ++i)
- {
- b4_symbol_variant([[yystos_[yystack_@{i@}.state]]],
- [[yystack_@{i@}.value]],
- [[destroy]])
- }])dnl
-[
+ // Destroy a variant which value may have be swapped with yyval.
+ // The value of yyval (hence maybe one of these lhs symbols)
+ // depends on what does the default contruction for this type.
+ // In the case of pointers for instance, nothing is done, so the
+ // value is junk. Therefore do not try to report the content in
+ // the debug trace, it's junk. Hence yymsg = 0. Besides, that
+ // keeps exactly the same traces as with the other Bison
+ // skeletons.
+ yydestruct_ (0,
+ yystos_[yystack_[i].state],
+ yystack_[i].value, yystack_[i].location);]])[
+
yypop_ (yylen);
yylen = 0;
YY_STACK_PRINT ();
if (yychar <= yyeof_)
{
- /* Return failure if at end of input. */
- if (yychar == yyeof_)
- YYABORT;
+ /* Return failure if at end of input. */
+ if (yychar == yyeof_)
+ YYABORT;
}
else
{