From 4982f078bfd98d50b9c97d2bcddb7a89d20ff3df Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Thu, 26 Jul 2012 16:52:35 +0200 Subject: [PATCH] support $$ in printers and destructors * src/scan-code.l (SC_SYMBOL_ACTION): Accept $$, not just $$. * data/c.m4 (b4_dollar_dollar_): New. (b4_symbol_actions): Let b4_dollar_dollar use b4_dollar_dollar_. * NEWS, doc/bison.texi: Document it. * tests/actions.at: Check this for C and C++. --- NEWS | 10 ++++ data/c.m4 | 17 +++++- doc/bison.texi | 19 +++---- src/scan-code.l | 8 ++- tests/actions.at | 137 +++++++++++++++++++++++++++++++++++++++++++++++ tests/calc.at | 6 +-- 6 files changed, 182 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index b97956cc..56961cc2 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,16 @@ GNU Bison NEWS *** glr.cc: set_debug_level and debug_level work as expected. +** Type names in printers and destructors + + For consistency with rule actions, it is now possible to qualify $$ by a + type-name in printers and destructors. For instance: + + %printer { fprintf (yyo, "(%d, %f)", $$, $$); } <*> <>; + + will display two values for each typed and untyped symbol (provided + that YYSTYPE supports it). + * Noteworthy changes in release 2.6 (2012-07-19) [stable] ** Future Changes diff --git a/data/c.m4 b/data/c.m4 index 08296c65..3954613b 100644 --- a/data/c.m4 +++ b/data/c.m4 @@ -417,13 +417,28 @@ m4_define([b4_case], $2 break;]) +# b4_dollar_dollar_(NAME, FIELD, DEFAULT-FIELD) +# --------------------------------------------- +# If FIELD (or DEFAULT-FIELD) is non-null, read it in pointer NAME, +# otherwise just dereference. +m4_define([b4_dollar_dollar_], +[m4_if([$2], [[]], + [m4_ifval([$3], [($1->$3)], + [(*$1)])], + [($1->$2)])]) + + # b4_symbol_actions(FILENAME, LINENO, # SYMBOL-TAG, SYMBOL-NUM, # SYMBOL-ACTION, SYMBOL-TYPENAME) # ------------------------------------------------- +# Issue the code for a symbol action (e.g., %printer). +# +# Define b4_dollar_dollar([TYPE-NAME]), and b4_at_dollar, which are +# invoked where $$ and @$ were specified by the user. m4_define([b4_symbol_actions], [m4_pushdef([b4_dollar_dollar], - [m4_ifval([$6], [(yyvaluep->$6)], [(*yyvaluep)])])dnl + [b4_dollar_dollar_([yyvaluep], m4_dquote($][1), [$6])])dnl m4_pushdef([b4_at_dollar], [(*yylocationp)])dnl case $4: /* $3 */ b4_syncline([$2], [$1]) diff --git a/doc/bison.texi b/doc/bison.texi index 6156b41f..e50bd171 100644 --- a/doc/bison.texi +++ b/doc/bison.texi @@ -4592,11 +4592,11 @@ symbol is automatically discarded. @deffn {Directive} %destructor @{ @var{code} @} @var{symbols} @findex %destructor Invoke the braced @var{code} whenever the parser discards one of the -@var{symbols}. -Within @var{code}, @code{$$} designates the semantic value associated -with the discarded symbol, and @code{@@$} designates its location. -The additional parser parameters are also available (@pxref{Parser Function, , -The Parser Function @code{yyparse}}). +@var{symbols}. Within @var{code}, @code{$$} (or @code{$<@var{tag}>$}) +designates the semantic value associated with the discarded symbol, and +@code{@@$} designates its location. The additional parser parameters are +also available (@pxref{Parser Function, , The Parser Function +@code{yyparse}}). When a symbol is listed among @var{symbols}, its @code{%destructor} is called a per-symbol @code{%destructor}. @@ -4734,10 +4734,11 @@ Decl, , Freeing Discarded Symbols}). @c This is the same text as for %destructor. Invoke the braced @var{code} whenever the parser displays one of the @var{symbols}. Within @var{code}, @code{yyoutput} denotes the output stream -(a @code{FILE*} in C, and an @code{std::ostream&} in C++), -@code{$$} designates the semantic value associated with the symbol, and -@code{@@$} its location. The additional parser parameters are also -available (@pxref{Parser Function, , The Parser Function @code{yyparse}}). +(a @code{FILE*} in C, and an @code{std::ostream&} in C++), @code{$$} (or +@code{$<@var{tag}>$}) designates the semantic value associated with the +symbol, and @code{@@$} its location. The additional parser parameters are +also available (@pxref{Parser Function, , The Parser Function +@code{yyparse}}). The @var{symbols} are defined as for @code{%destructor} (@pxref{Destructor Decl, , Freeing Discarded Symbols}.): they can be per-type (e.g., diff --git a/src/scan-code.l b/src/scan-code.l index 2fab6d9d..e30bf9db 100644 --- a/src/scan-code.l +++ b/src/scan-code.l @@ -264,8 +264,12 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$" { - "$$" { - obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar["); + "$"("<"{tag}">")?"$" { + const char *type_name = NULL; + fetch_type_name (yytext + 1, &type_name, *loc)[-1] = 0; + obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar("); + obstack_quote (&obstack_for_string, type_name); + obstack_sgrow (&obstack_for_string, ")["); self->is_value_used = true; } "@$" { diff --git a/tests/actions.at b/tests/actions.at index e8e8cd97..dd909b00 100644 --- a/tests/actions.at +++ b/tests/actions.at @@ -1230,6 +1230,143 @@ AT_CHECK_ACTION_LOCATIONS([[%destructor]]) AT_CHECK_ACTION_LOCATIONS([[%printer]]) +## ------------------------- ## +## Qualified $$ in actions. ## +## ------------------------- ## + +# Check that we can used qualified $$ (v.g., $$) not only in +# rule actions, but also where $$ is valid: %printer and %destructor. +# +# FIXME: Not actually checking %desctructor, but it's the same code as +# %printer... +# +# To do that, use a semantic value that has two fields (sem_type), +# declare symbols to have only one of these types (INT, float), and +# use $$ to get the other one. Including for symbols that are +# not typed (UNTYPED). + +m4_pushdef([AT_TEST], +[AT_SETUP([[Qualified $$ in actions: $1]]) + +AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1"]) + +AT_DATA_GRAMMAR([[input.y]], +[[%skeleton "$1" +%defines // FIXME: Mandated by lalr1.cc in Bison 2.6. +%locations // FIXME: Mandated by lalr1.cc in Bison 2.6. +%debug +%code requires +{ +# include + + typedef struct sem_type + { + int ival; + float fval; + } sem_type; + +# define YYSTYPE sem_type + +#ifdef __cplusplus +# include + static void + report (std::ostream& yyo, int ival, float fval) + { + yyo << "ival: " << ival << ", fval: " << fval; + } +#else + static void + report (FILE* yyo, int ival, float fval) + { + fprintf (yyo, "ival: %d, fval: %1.1f", ival, fval); + } +#endif +} + +%code +{ + ]AT_YYERROR_DECLARE[ + ]AT_YYLEX_DECLARE[ +} + +%token UNTYPED +%token INT +%type float +%printer { report (yyo, $$, $$); } ; +%printer { report (yyo, $$, $$ ); } ; +%printer { report (yyo, $$, $$); } <>; + +]AT_SKEL_CC_IF([[ +/* The lalr1.cc skeleton, for backward compatibility, defines + a constructor for position that initializes the filename. The + glr.cc skeleton does not (and in fact cannot: location/position + are stored in a union, from which objects with constructors are + excluded in C++). */ +%initial-action { + @$.initialize (); +} +]])[ + +// %initial-action +// { +// $$ = 42; +// $$ = 4.2; +// } + +%% +float: UNTYPED INT +{ + $$ = $1 + $2; + $$ = $1 + $][2; +}; +%% +]AT_YYERROR_DEFINE[ +]AT_YYLEX_DEFINE(AT_SKEL_CC_IF([[{yy::parser::token::UNTYPED, + yy::parser::token::INT, + EOF}]], + [[{UNTYPED, INT, EOF}]]), + [AT_VAL.ival = toknum * 10; AT_VAL.fval = toknum / 10.0;])[ +int +main (void) +{]AT_SKEL_CC_IF([[ + yy::parser p; + p.set_debug_level(1); + return p.parse ();]], [[ + yydebug = 1; + return yyparse ();]])[ +} +]]) + +AT_FULL_COMPILE([[input]]) +AT_PARSER_CHECK([./input], 0, [], [stderr]) +# Don't be too picky on the traces, GLR is not exactly the same. Keep +# only the lines from the printer. +# +# Don't care about locations. FIXME: remove their removal when Bison +# supports C++ without locations. +AT_CHECK([[sed -ne 's/([-0-9.]*: /(/;/ival:/p' stderr]], 0, +[[Reading a token: Next token is token UNTYPED (ival: 10, fval: 0.1) +Shifting token UNTYPED (ival: 10, fval: 0.1) +Reading a token: Next token is token INT (ival: 20, fval: 0.2) +Shifting token INT (ival: 20, fval: 0.2) + $][1 = token UNTYPED (ival: 10, fval: 0.1) + $][2 = token INT (ival: 20, fval: 0.2) +-> $$ = nterm float (ival: 30, fval: 0.3) +Cleanup: popping nterm float (ival: 30, fval: 0.3) +]]) + +AT_BISON_OPTION_POPDEFS + +AT_CLEANUP +]) + +AT_TEST([yacc.c]) +AT_TEST([glr.c]) +AT_TEST([lalr1.cc]) +AT_TEST([glr.cc]) + +m4_popdef([AT_TEST]) + ## ----------------------------------------------- ## ## Fix user actions without a trailing semicolon. ## ## ----------------------------------------------- ## diff --git a/tests/calc.at b/tests/calc.at index e4cb07f1..31ee44e2 100644 --- a/tests/calc.at +++ b/tests/calc.at @@ -288,16 +288,16 @@ static int power (int base, int exponent); ]AT_YYLEX_DECLARE_EXTERN[ } -]AT_SKEL_CC_IF([AT_LOCATION_TYPE_IF([], [ +]AT_SKEL_CC_IF([AT_LOCATION_TYPE_IF([], [[ /* The lalr1.cc skeleton, for backward compatibility, defines a constructor for position that initializes the filename. The glr.cc skeleton does not (and in fact cannot: location/position are stored in a union, from which objects with constructors are - excluded in C++. */ + excluded in C++). */ %initial-action { @$.initialize (); } -])])[ +]])])[ /* Bison Declarations */ %token CALC_EOF 0 "end of input" -- 2.45.2