diff options
author | Akim Demaille <demaille@gostai.com> | 2008-12-31 15:36:19 +0100 |
---|---|---|
committer | Akim Demaille <demaille@gostai.com> | 2011-06-30 10:51:57 +0200 |
commit | ff654ad228fe39fbd7cb7c2b466cf9f85550c8c4 (patch) | |
tree | 2519e4d2f136e4296bf3dbbbc3587cf701a29687 | |
parent | 6e39af70c8ffab8490391ff5c9bdc38cf36b4c12 (diff) | |
download | bison-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.c | 62 | ||||
-rw-r--r-- | data/glr.cc | 59 | ||||
-rw-r--r-- | data/yacc.c | 4 | ||||
-rw-r--r-- | examples/variant.yy | 5 |
4 files changed, 111 insertions, 19 deletions
@@ -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 << "}"; } } |