summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkim Demaille <demaille@gostai.com>2008-12-31 15:36:19 +0100
committerAkim Demaille <demaille@gostai.com>2011-06-30 10:51:57 +0200
commitff654ad228fe39fbd7cb7c2b466cf9f85550c8c4 (patch)
tree2519e4d2f136e4296bf3dbbbc3587cf701a29687
parent6e39af70c8ffab8490391ff5c9bdc38cf36b4c12 (diff)
downloadbison-ff654ad228fe39fbd7cb7c2b466cf9f85550c8c4.tar.gz
FIXME: Support make_symbol with glr.cc.
* data/glr.c: Save and restore b4_symbol_value and b4_symbol_value_template when called from glr.cc. * data/glr.cc (cassert): Include it when needed. (b4_variant_define): Call it when needed. * data/glr.c (YYLEX): Don't redefine if defined, so that the definition from glr.cc can be used. (yyuserAction): Initialize *yyvalp. (yyglrShift): Build and initialize yysval. (b4_glr_cc_if): New. Use it. (b4_rhs_data): Provide a new definition for C++ that does not forbid changes in the RHS. * data/glr.cc (b4_location_constructors): Define so that we can use location and position constructors. (yylex_wrapper, YYLEX): New, to bounce a symbol_type based yylex onto a traditional yyvalp/yylocp one. (b4_yytranslate_define, b4_public_types_define): Invoke them. (token_number_type, yyeof_): New. * data/yacc.c, data/glr.c (b4_lex_params): Provide the formal argument names.
-rw-r--r--data/glr.c62
-rw-r--r--data/glr.cc59
-rw-r--r--data/yacc.c4
-rw-r--r--examples/variant.yy5
4 files changed, 111 insertions, 19 deletions
diff --git a/data/glr.c b/data/glr.c
index f22a8f10..d089ea5b 100644
--- a/data/glr.c
+++ b/data/glr.c
@@ -17,9 +17,28 @@
# 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_glr_cc_if([IF-TRUE], [IF-FALSE])
+# -----------------------------------
+m4_define([b4_glr_cc_if],
+ [m4_if(b4_skeleton, ["glr.cc"], $@)])
+
+# When glr.c is used from glr.cc, it has provided the version of
+# b4_symbol_value and b4_symbol_value_template that are needed. c.m4
+# provides other definitions. So save and restore the C++
+# definitions.
+
+b4_glr_cc_if([
+ m4_pushdef([b4_symbol_value])
+ m4_pushdef([b4_symbol_value_template])
+])
m4_include(b4_pkgdatadir/[c.m4])
+b4_glr_cc_if([
+ m4_popdef([b4_symbol_value_template])
+ m4_popdef([b4_symbol_value])
+])
+
## ---------------- ##
## Default values. ##
## ---------------- ##
@@ -54,11 +73,11 @@ m4_define([b4_user_formals],
# b4_lex_param
# ------------
-# Accumule in b4_lex_param all the yylex arguments.
+# Accumulate in b4_lex_param all the yylex arguments.
# Yes, this is quite ugly...
-m4_define([b4_lex_param],
-m4_dquote(b4_pure_if([[[[YYSTYPE *]], [[&yylval]]][]dnl
-b4_locations_if([, [[YYLTYPE *], [&yylloc]]])])dnl
+#m4_define([b4_lex_param],
+#m4_dquote(b4_pure_if([[[[YYSTYPE *yylvalp]], [[&yylval]]][]dnl
+#b4_locations_if([, [[YYLTYPE *yyllocp], [&yylloc]]])])dnl
m4_ifdef([b4_lex_param], [, ]b4_lex_param)))
@@ -119,6 +138,12 @@ m4_define([b4_lhs_value],
m4_define([b4_rhs_data],
[((yyGLRStackItem const *)yyvsp)@{YYFILL (b4_subtract([$2], [$1]))@}.yystate])
+# We temporarily allow changes in the stack as we often transfer
+# ownership bw lhs and rhs, e.g. std::swap($$, $1).
+b4_glr_cc_if([
+ m4_define([b4_rhs_data],
+ [yyvsp@{YYFILL (b4_subtract([$2], [$1]))@}.yystate])
+])
# b4_rhs_value(RULE-LENGTH, NUM, [TYPE])
# --------------------------------------
@@ -479,7 +504,12 @@ dnl We probably ought to introduce a type for confl.
/* YYLEX -- calling `yylex' with the right arguments. */
-#define YYLEX ]b4_c_function_call([yylex], [int], b4_lex_param)[
+#ifndef YYLEX
+# define YYLEX ]b4_c_function_call([yylex], [int],
+ b4_pure_if([[[[YYSTYPE *yylvalp]], [[&yylval]]][]dnl
+b4_locations_if([, [[YYLTYPE *yyllocp], [&yylloc]]])])dnl
+m4_ifdef([b4_lex_param], [, ]b4_lex_param))[
+#endif
]b4_pure_if(
[
@@ -680,7 +710,7 @@ typedef short int yyItemNum;
typedef struct yyGLRState yyGLRState;
typedef struct yyGLRStateSet yyGLRStateSet;
typedef struct yySemanticOption yySemanticOption;
-typedef union yyGLRStackItem yyGLRStackItem;
+typedef ]b4_glr_cc_if([struct], [union])[ yyGLRStackItem yyGLRStackItem;
typedef struct yyGLRStack yyGLRStack;
struct yyGLRState {
@@ -695,7 +725,7 @@ struct yyGLRState {
yyGLRState* yypred;
/** Source position of the last token produced by my symbol */
size_t yyposn;
- union {
+ ]b4_glr_cc_if([struct], [union])[ {
/** First in a chain of alternative reductions producing the
* non-terminal corresponding to this state, threaded through
* yynext. */
@@ -735,7 +765,7 @@ struct yySemanticOption {
/** Type of the items in the GLR stack. The yyisState field
* indicates which item of the union is valid. */
-union yyGLRStackItem {
+]b4_glr_cc_if([struct], [union])[ yyGLRStackItem {
yyGLRState yystate;
yySemanticOption yyoption;
};
@@ -872,11 +902,15 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
return yyerror (]b4_yyerror_args[YY_("syntax error: cannot back up")), \
yyerrok, yyerr
- yylow = 1;
+ yylow = 1;]b4_variant_if([
+ /* Variants are always initialized to an empty instance of the
+ correct type. The default $$=$1 action is NOT applied when using
+ variants. */
+ b4_symbol_variant([[yyr1@{yyn@}]], [(*yyvalp)], [build])], [[
if (yyrhslen == 0)
*yyvalp = yyval_default;
else
- *yyvalp = yyvsp[YYFILL (1-yyrhslen)].yystate.yysemantics.yysval;
+ *yyvalp = yyvsp[YYFILL (1-yyrhslen)].yystate.yysemantics.yysval;]])[
YYLLOC_DEFAULT ((*yylocp), (yyvsp - yyrhslen), yyrhslen);
]b4_locations_if([[ yystackp->yyerror_range[1].yystate.yyloc = *yylocp;
]])[
@@ -1282,9 +1316,13 @@ yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
yynewState->yylrState = yylrState;
yynewState->yyposn = yyposn;
yynewState->yyresolved = yytrue;
- yynewState->yypred = yystackp->yytops.yystates[yyk];
+ yynewState->yypred = yystackp->yytops.yystates[yyk];]b4_variant_if([[
+ new (&yynewState->yysemantics.yysval) YYSTYPE;
+ ]b4_symbol_variant([[yystos[yylrState]]], [[yynewState->yysemantics.yysval]],
+ [build], [*yyvalp])[
+ std::swap(yynewState->yyloc, *yylocp);]], [[
yynewState->yysemantics.yysval = *yyvalp;
- yynewState->yyloc = *yylocp;
+ yynewState->yyloc = *yylocp;]])[
yystackp->yytops.yystates[yyk] = yynewState;
YY_RESERVE_GLRSTACK (yystackp);
diff --git a/data/glr.cc b/data/glr.cc
index e8f495bb..0faf823f 100644
--- a/data/glr.cc
+++ b/data/glr.cc
@@ -44,7 +44,8 @@
# filename member).
# We require a pure interface using locations.
-m4_define([b4_percent_define(locations)], [])
+m4_define([b4_locations_flag], [1])
+m4_define([b4_location_constructors])
m4_define([b4_pure_flag], [1])
# The header is mandatory.
@@ -54,6 +55,7 @@ b4_defines_if([],
m4_include(b4_pkgdatadir/[c++.m4])
b4_percent_define_ifdef([[location_type]], [],
[m4_include(b4_pkgdatadir/[location.cc])])
+b4_variant_if([m4_include(b4_pkgdatadir/[variant.hh])])
m4_define([b4_parser_class_name],
[b4_percent_define_get([[parser_class_name]])])
@@ -61,6 +63,16 @@ m4_define([b4_parser_class_name],
# Save the parse parameters.
m4_define([b4_parse_param_orig], m4_defn([b4_parse_param]))
+# b4_lex_wrapper_param
+# --------------------
+# Accumulate in b4_lex_param all the yylex arguments.
+# Yes, this is quite ugly...
+m4_define([b4_lex_wrapper_param],
+[b4_pure_if([[[[YYSTYPE *yylvalp]], [[yylvalp]]][]dnl
+b4_locations_if([, [[YYLTYPE *yyllocp], [yyllocp]]])])dnl
+m4_ifdef([b4_lex_param], [, ]b4_lex_param)])
+
+
# b4_yy_symbol_print_generate
# ---------------------------
@@ -96,8 +108,19 @@ b4_c_ansi_function_decl([yyerror],
[static void],
[[b4_namespace_ref::b4_parser_class_name::location_type *yylocationp], [yylocationp]],
b4_parse_param,
- [[const char* msg], [msg]])])
-
+ [[const char* msg], [msg]])
+
+b4_lex_symbol_if([
+// A wrapper around a symbol_type returning yylex, to an old style yylex.
+b4_c_ansi_function_decl([yylex_wrapper],
+ [static int],
+ b4_lex_wrapper_param)
+# define YYLEX ]b4_c_function_call([yylex_wrapper], [int],
+[[[YYSTYPE*]], [[&yylval]]][]dnl
+b4_locations_if([, [[YYLTYPE*], [&yylloc]]])dnl
+m4_ifdef([b4_lex_param], [, ]b4_lex_param))[
+])
+])
# Define yyerror.
m4_append([b4_epilogue],
@@ -116,6 +139,20 @@ m4_append([b4_epilogue],
[ yyparser.error (*yylocationp, msg);
}
+]b4_lex_symbol_if([[
+// A wrapper around a symbol_type returning yylex, to an old style yylex.
+]b4_c_ansi_function_def([yylex_wrapper],
+ [static int],
+ b4_lex_wrapper_param)[
+{
+ ]b4_namespace_ref::b4_parser_class_name[::symbol_type s = ]dnl
+b4_c_function_call([yylex],
+ [],
+ m4_ifdef([b4_lex_param], b4_lex_param))[;
+ std::swap (*yylvalp, s.value);
+ std::swap (*yyllocp, s.location);
+ return s.token ();
+}]])[
]b4_namespace_open[
]dnl In this section, the parse param are the original parse_params.
@@ -139,6 +176,9 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
return ::yyparse (*this]b4_user_args[);
}
+]b4_lex_symbol_if([], [b4_yytranslate_define
+b4_public_types_define])[
+
#if YYDEBUG
/*--------------------.
| Print this symbol. |
@@ -226,6 +266,7 @@ b4_copyright([Skeleton interface for Bison GLR parsers in C++],
]b4_percent_code_get([[requires]])[
#include <stdexcept>
+]b4_parse_assert_if([#include <cassert>])[
#include <string>
#include <iostream>
]b4_percent_define_ifdef([[location_type]], [],
@@ -312,6 +353,15 @@ b4_copyright([Skeleton interface for Bison GLR parsers in C++],
std::ostream* yycdebug_;
#endif
+ typedef ]b4_int_type_for([b4_translate])[ token_number_type;
+ enum
+ {
+ yyeof_ = 0,
+ };
+
+ /// Convert a scanner token number \a t to a symbol number.
+ static inline token_number_type yytranslate_ (]b4_lex_symbol_if([token_type], [int])[ t);
+
/// \brief Reclaim the memory associated to a symbol.
/// \param yymsg Why this token is reclaimed.
/// \param yytype The symbol type.
@@ -325,6 +375,9 @@ b4_copyright([Skeleton interface for Bison GLR parsers in C++],
]b4_parse_param_vars[
};
+]b4_lex_symbol_if([b4_yytranslate_define
+b4_public_types_define])[
+
]dnl Redirections for glr.c.
b4_percent_define_flag_if([[global_tokens_and_yystype]],
[b4_token_defines(b4_tokens)])
diff --git a/data/yacc.c b/data/yacc.c
index 6bacbf84..60b9b630 100644
--- a/data/yacc.c
+++ b/data/yacc.c
@@ -93,8 +93,8 @@ m4_ifset([b4_parse_param], [b4_c_args(b4_parse_param), ])])
# Accumulate in b4_lex_param all the yylex arguments.
# b4_lex_param arrives quoted twice, but we want to keep only one level.
m4_define([b4_lex_param],
-m4_dquote(b4_pure_if([[[[YYSTYPE *]], [[&yylval]]][]dnl
-b4_locations_if([, [[YYLTYPE *], [&yylloc]]])m4_ifdef([b4_lex_param], [, ])])dnl
+m4_dquote(b4_pure_if([[[[YYSTYPE *yylval]], [[&yylval]]][]dnl
+b4_locations_if([, [[YYLTYPE *yylloc], [&yylloc]]])m4_ifdef([b4_lex_param], [, ])])dnl
m4_ifdef([b4_lex_param], b4_lex_param)))
diff --git a/examples/variant.yy b/examples/variant.yy
index 8471e6e8..85109a92 100644
--- a/examples/variant.yy
+++ b/examples/variant.yy
@@ -1,5 +1,5 @@
%debug
-%skeleton "lalr1.cc"
+%skeleton "glr.cc"
%defines
%define assert
%define variant
@@ -30,9 +30,10 @@ typedef std::list<std::string> strings_type;
std::ostream&
operator<< (std::ostream& o, const strings_type& s)
{
+ o << "{";
std::copy (s.begin (), s.end (),
std::ostream_iterator<strings_type::value_type> (o, "\n"));
- return o;
+ return o << "}";
}
}