]) # b4_variant_if
+# b4_lex_symbol_if([IF-YYLEX-RETURNS-A-COMPLETE-SYMBOL], [IF-NOT])
+# ----------------------------------------------------------------
+m4_define([b4_lex_symbol_if],
+[b4_percent_define_ifdef([[lex_symbol]], [$1], [$2])])
+
+
# b4_assert_if([IF-ASSERTIONS-ARE-USED], [IF-NOT])
# ------------------------------------------------
m4_define([b4_assert_if],
[m4_indir([b4_symbol($1, $2)])])
+# b4_symbol_if(NUM, FIELD, IF-TRUE, IF-FALSE)
+# -------------------------------------------
+# If FIELD about symbol #NUM is 1 expand IF-TRUE, if is 0, expand IF-FALSE.
+# Otherwise an error.
+m4_define([b4_symbol_if],
+[m4_case(b4_symbol([$1], [$2]),
+ [1], [$3],
+ [0], [$4],
+ [m4_fatal([$0: field $2 of $1 is not a Boolean:] b4_symbol([$1], [$2]))])])
+
+
# b4_symbol_actions(FILENAME, LINENO,
# SYMBOL-TAG, SYMBOL-NUM,
# SYMBOL-ACTION, SYMBOL-TYPENAME)
# b4_type_action_(NUMS)
# ---------------------
# Run actions for the symbol NUMS that all have the same type-name.
+# Skip NUMS that have no type-name.
m4_define([b4_type_action_],
+[b4_symbol_if([$1], [has_type_name],
[m4_map([b4_symbol_case_], [$@])[]dnl
b4_dollar_dollar([b4_symbol([$1], [number])],
[b4_symbol([$1], [tag])],
[b4_symbol([$1], [type_name])]);
break;
+])])
+
+
+# b4_symbol_constructor_declaration_(SYMBOL-NUMBERS)
+# ----------------------------------------------------
+# Declare the overloaded version of make_symbol for the (common) type of
+# these SYMBOL-NUMBERS. Use at class-level.
+m4_define([b4_symbol_constructor_declaration_],
+[ template <token_type>
+ static inline symbol_type
+ make_symbol (b4_symbol_if([$1], [has_type_name],
+ [const b4_symbol([$1], [type_name])& v, ])dnl
+const location_type& l);
+
+])
+
+# b4_symbol_constructor_declarations
+# ----------------------------------
+# Declare the overloaded versions of make_symbol for all the value types.
+# Use at class-level.
+m4_define([b4_symbol_constructor_declarations],
+[b4_variant_if([
+ // Declaration of make_symbol for each value type.
+m4_map([b4_symbol_constructor_declaration_], m4_defn([b4_type_names]))])])
+
+
+
+# b4_symbol_constructor_specialization_(SYMBOL-NUMBER)
+# ----------------------------------------------------
+# Declare the specialization of make_symbol for this each SYMBOL-NUMBER.
+# Specializations cannot be declared at class-level, this must be done
+# at namespace-level.
+m4_define([b4_symbol_constructor_specialization_],
+[b4_symbol_if([$1], [is_token], [b4_symbol_if([$1], [tag_is_id],
+[ template <>
+ inline
+ b4_parser_class_name::symbol_type
+ b4_parser_class_name::make_symbol <b4_parser_class_name::token::b4_symbol([$1], [tag])> (dnl
+b4_symbol_if([$1], [has_type_name],
+ [const b4_symbol([$1], [type_name])& v, ])dnl
+const b4_parser_class_name::location_type& l);
+])])])
+
+# b4_symbol_constructor_specializations
+# -------------------------------------
+# Declare specializations of make_symbol.
+m4_define([b4_symbol_constructor_specializations],
+[b4_variant_if([
+ // Specializations of make_symbol for each symbol type.
+m4_map([b4_symbol_constructor_specialization_],
+ m4_defn([b4_symbol_numbers]))])dnl
])
+
+# b4_symbol_constructor_definition_(SYMBOL-NUMBER)
+# ------------------------------------------------
+# Define make_symbol for this SYMBOL-NUMBER.
+m4_define([b4_symbol_constructor_definition_],
+[b4_symbol_if([$1], [is_token], [b4_symbol_if([$1], [tag_is_id],
+[ template <>
+ b4_parser_class_name::symbol_type
+ b4_parser_class_name::make_symbol <b4_parser_class_name::token::b4_symbol([$1], [tag])> (dnl
+b4_symbol_if([$1], [has_type_name],
+ [const b4_symbol([$1], [type_name])& v, ])dnl
+const location_type& l)
+ {
+ return symbol_type (yytranslate_ (token::b4_symbol([$1], [tag])),dnl
+ b4_symbol_if([$1], [has_type_name], [v, ])l);
+ }
+
+])])])
+
+
+# b4_symbol_constructor_declarations
+# ----------------------------------
+# Define the overloaded versions of make_symbol for all the value types.
+m4_define([b4_symbol_constructor_definitions],
+[b4_variant_if(
+[ // Implementation of make_symbol for each symbol type.
+m4_map([b4_symbol_constructor_definition_], m4_defn([b4_symbol_numbers]))])])
+
+
# b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS])
# ------------------------------------------------
# Run some ACTION ("build", or "destroy") on YYVAL of symbol type
{]b4_assert_if([
/// Whether something is contained.
bool built;
-
- /// Initially uninitialized.
- variant ()
- : built(false)
- {}])[
+])[
+ /// Empty construction.
+ inline
+ variant ()]b4_assert_if([
+ : built(false)])[
+ {}
/// Instantiate a \a T in here.
template <typename T>
return *new (buffer) T(t);
}
+ /// Construct and fill.
+ template <typename T>
+ inline
+ variant (const T& t)]b4_assert_if([
+ : built(true)])[
+ {
+ new (buffer) T(t);
+ }
+
/// Accessor to a built \a T.
template <typename T>
inline T&
inline symbol_base_type ();
/// Constructor.
+ inline symbol_base_type (const location_type& l);
inline symbol_base_type (const semantic_type& v, const location_type& l);
/// Return this with its exact type.
inline void yy_destroy_ (const char* yymsg,
symbol_base_type<Exact>& yysym) const;
+ public:
/// Element of the stack: a state and its attributes.
struct symbol_type : symbol_base_type<symbol_type>
{
inline symbol_type (int t,
const semantic_type& v, const location_type& l);
+ inline symbol_type (int t,
+ const location_type& l);
+
/// The symbol type.
int type;
inline int type_get_ () const;
};
+]b4_symbol_constructor_declarations[
+
+ private:
/// Element of the stack: a state and its attributes.
struct stack_symbol_type : symbol_base_type<stack_symbol_type>
{
]b4_parse_param_vars[
};
-
+]b4_symbol_constructor_specializations[
]b4_namespace_close[
]b4_percent_define_flag_if([[global_tokens_and_yystype]],
#endif /* !YYDEBUG */
-#define yyerrok (yyerrstatus_ = 0)
-#define yyclearin (yychar = yyempty_)
+#define yyerrok (yyerrstatus_ = 0)
+#define yyclearin (yyempty = true)
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
#define YYRECOVERING() (!!yyerrstatus_)
]b4_namespace_open[
{
}
+ template <typename Exact>
+ ]b4_parser_class_name[::symbol_base_type<Exact>::symbol_base_type (const location_type& l)
+ : value()
+ , location(l)
+ {
+ }
+
template <typename Exact>
]b4_parser_class_name[::symbol_base_type<Exact>::symbol_base_type (const semantic_type& v, const location_type& l)
: value(v)
{
}
+ ]b4_parser_class_name[::symbol_type::symbol_type (int t,
+ const location_type& l)
+ : super_type (l)
+ , type (t)
+ {
+ }
+
]b4_parser_class_name[::symbol_type::symbol_type (int t,
const semantic_type& v, const location_type& l)
: super_type (v, l)
return type;
}
+]b4_symbol_constructor_definitions[
+
// stack_symbol_type.
]b4_parser_class_name[::stack_symbol_type::stack_symbol_type ()
: super_type ()
int
]b4_parser_class_name[::parse ()
{
- /// Coded type of the lookahead.
- int yychar = yyempty_;
+ /// Whether yyla contains a lookahead.
+ bool yyempty = true;
/* State. */
int yyn;
goto yydefault;
/* Read a lookahead token. */
- if (yychar == yyempty_)
+ if (yyempty)
{
- YYCDEBUG << "Reading a token: ";
- yychar = ]b4_c_function_call([yylex], [int],
+ YYCDEBUG << "Reading a token: ";
+]b4_lex_symbol_if(
+[ yyla = yylex();],
+[ yyla.type = yytranslate_ (b4_c_function_call([yylex], [int],
[[YYSTYPE*], [&yyla.value]][]dnl
b4_locations_if([, [[location*], [&yyla.location]]])dnl
-m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
- }
-
-
- /* Convert token to internal form. */
- if (yychar <= yyeof_)
- {
- yychar = yyla.type = yyeof_;
- YYCDEBUG << "Now at end of input." << std::endl;
- }
- else
- {
- yyla.type = yytranslate_ (yychar);
- YY_SYMBOL_PRINT ("Next token is", yyla);
+m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[
+ yyempty = false;
}
+ YY_SYMBOL_PRINT ("Next token is", yyla);
/* If the proper action on seeing token YYLA.TYPE is to reduce or
to detect an error, take that action. */
}
/* Discard the token being shifted. */
- yychar = yyempty_;
+ yyempty = true;
/* Count tokens shifted since error; after three, turn off error
status. */
if (yyerrstatus_ == 3)
{
/* If just tried and failed to reuse lookahead token after an
- error, discard it. */
-
- if (yychar <= yyeof_)
- {
- /* Return failure if at end of input. */
- if (yychar == yyeof_)
- YYABORT;
- }
- else
- {
- yy_destroy_ ("Error: discarding", yyla);
- yychar = yyempty_;
+ error, discard it. */
+
+ /* Return failure if at end of input. */
+ if (yyla.type == yyeof_)
+ YYABORT;
+ else
+ {
+ yy_destroy_ ("Error: discarding", yyla);
+ yyempty = true;
}
}
goto yyreturn;
yyreturn:
- if (yychar != yyempty_)
+ if (!yyempty)
yy_destroy_ ("Cleanup: discarding lookahead", yyla);
/* Do not reclaim the symbols of the rule which action triggered
// Generate an error message.
std::string
]b4_parser_class_name[::yysyntax_error_ (int yystate, int]dnl
-b4_error_verbose_if([ tok])[)
+b4_error_verbose_if([ yytoken])[)
{
- std::string res;
+ std::string yyres;
YYUSE (yystate);
#if YYERROR_VERBOSE
int yyn = yypact_[yystate];
/* Stay within bounds of both yycheck and yytname. */
int yychecklim = yylast_ - yyn + 1;
int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
- int count = 0;
- for (int x = yyxbegin; x < yyxend; ++x)
- if (yycheck_[x + yyn] == x && x != yyterror_)
- ++count;
-
- // FIXME: This method of building the message is not compatible
- // with internationalization. It should work like yacc.c does it.
- // That is, first build a string that looks like this:
- // "syntax error, unexpected %s or %s or %s"
- // Then, invoke YY_ on this string.
- // Finally, use the string as a format to output
- // yytname_[tok], etc.
- // Until this gets fixed, this message appears in English only.
- res = "syntax error, unexpected ";
- res += yytnamerr_ (yytname_[tok]);
- if (count < 5)
- {
- count = 0;
- for (int x = yyxbegin; x < yyxend; ++x)
- if (yycheck_[x + yyn] == x && x != yyterror_)
- {
- res += (!count++) ? ", expecting " : " or ";
- res += yytnamerr_ (yytname_[x]);
- }
- }
+
+ // Number of "expected" tokens.
+ size_t yycount = 0;
+ // Its maximum.
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ // Arguments of yyformat.
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ yyarg[yycount++] = yytname_[yytoken];
+ for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck_[yyx + yyn] == yyx && yyx != yyterror_)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ break;
+ }
+ else
+ yyarg[yycount++] = yytname_[yyx];
+ }
+
+ char const* yyformat = 0;
+ switch (yycount)
+ {
+#define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ 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_
+ }
+ // Argument number.
+ size_t yyi = 0;
+ for (char const* yyp = yyformat; *yyp; ++yyp)
+ if (yyp[0] == '%' && yyp[1] == 's' && yyi < yycount)
+ {
+ yyres += yytnamerr_ (yyarg[yyi++]);
+ ++yyp;
+ }
+ else
+ yyres += *yyp;
}
else
#endif
- res = YY_("syntax error");
- return res;
+ yyres = YY_("syntax error");
+ return yyres;
}
const unsigned int user_token_number_max_ = ]b4_user_token_number_max[;
const token_number_type undef_token_ = ]b4_undef_token_number[;
- if (static_cast<unsigned int> (t) <= user_token_number_max_)
+ if (t <= yyeof_)
+ return yyeof_;
+ else if (static_cast<unsigned int> (t) <= user_token_number_max_)
return translate_table[t];
else
return undef_token_;