support $<tag>$ in printers and destructors

* src/scan-code.l (SC_SYMBOL_ACTION): Accept $<tag>$, 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++.
This commit is contained in:
Akim Demaille
2012-07-26 16:52:35 +02:00
parent 65a99eca25
commit 4982f078bf
6 changed files with 182 additions and 15 deletions

10
NEWS
View File

@@ -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)", $<ival>$, $<fval>$); } <*> <>;
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

View File

@@ -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 $<TYPE-NAME>$ 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])

View File

@@ -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.,

View File

@@ -264,8 +264,12 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$"
<SC_SYMBOL_ACTION>
{
"$$" {
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;
}
"@$" {

View File

@@ -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., $<type>$) 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 $<type>$ 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 <stdio.h>
typedef struct sem_type
{
int ival;
float fval;
} sem_type;
# define YYSTYPE sem_type
#ifdef __cplusplus
# include <iostream>
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 <ival> INT
%type <fval> float
%printer { report (yyo, $$, $<fval>$); } <ival>;
%printer { report (yyo, $<ival>$, $$ ); } <fval>;
%printer { report (yyo, $<ival>$, $<fval>$); } <>;
]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
// {
// $<ival>$ = 42;
// $<fval>$ = 4.2;
// }
%%
float: UNTYPED INT
{
$$ = $<fval>1 + $<fval>2;
$<ival>$ = $<ival>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. ##
## ----------------------------------------------- ##

View File

@@ -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"