mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-16 15:53:03 +00:00
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:
10
NEWS
10
NEWS
@@ -10,6 +10,16 @@ GNU Bison NEWS
|
|||||||
|
|
||||||
*** glr.cc: set_debug_level and debug_level work as expected.
|
*** 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]
|
* Noteworthy changes in release 2.6 (2012-07-19) [stable]
|
||||||
|
|
||||||
** Future Changes
|
** Future Changes
|
||||||
|
|||||||
17
data/c.m4
17
data/c.m4
@@ -417,13 +417,28 @@ m4_define([b4_case],
|
|||||||
$2
|
$2
|
||||||
break;])
|
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,
|
# b4_symbol_actions(FILENAME, LINENO,
|
||||||
# SYMBOL-TAG, SYMBOL-NUM,
|
# SYMBOL-TAG, SYMBOL-NUM,
|
||||||
# SYMBOL-ACTION, SYMBOL-TYPENAME)
|
# 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_define([b4_symbol_actions],
|
||||||
[m4_pushdef([b4_dollar_dollar],
|
[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
|
m4_pushdef([b4_at_dollar], [(*yylocationp)])dnl
|
||||||
case $4: /* $3 */
|
case $4: /* $3 */
|
||||||
b4_syncline([$2], [$1])
|
b4_syncline([$2], [$1])
|
||||||
|
|||||||
@@ -4592,11 +4592,11 @@ symbol is automatically discarded.
|
|||||||
@deffn {Directive} %destructor @{ @var{code} @} @var{symbols}
|
@deffn {Directive} %destructor @{ @var{code} @} @var{symbols}
|
||||||
@findex %destructor
|
@findex %destructor
|
||||||
Invoke the braced @var{code} whenever the parser discards one of the
|
Invoke the braced @var{code} whenever the parser discards one of the
|
||||||
@var{symbols}.
|
@var{symbols}. Within @var{code}, @code{$$} (or @code{$<@var{tag}>$})
|
||||||
Within @var{code}, @code{$$} designates the semantic value associated
|
designates the semantic value associated with the discarded symbol, and
|
||||||
with the discarded symbol, and @code{@@$} designates its location.
|
@code{@@$} designates its location. The additional parser parameters are
|
||||||
The additional parser parameters are also available (@pxref{Parser Function, ,
|
also available (@pxref{Parser Function, , The Parser Function
|
||||||
The Parser Function @code{yyparse}}).
|
@code{yyparse}}).
|
||||||
|
|
||||||
When a symbol is listed among @var{symbols}, its @code{%destructor} is called a
|
When a symbol is listed among @var{symbols}, its @code{%destructor} is called a
|
||||||
per-symbol @code{%destructor}.
|
per-symbol @code{%destructor}.
|
||||||
@@ -4734,10 +4734,11 @@ Decl, , Freeing Discarded Symbols}).
|
|||||||
@c This is the same text as for %destructor.
|
@c This is the same text as for %destructor.
|
||||||
Invoke the braced @var{code} whenever the parser displays one of the
|
Invoke the braced @var{code} whenever the parser displays one of the
|
||||||
@var{symbols}. Within @var{code}, @code{yyoutput} denotes the output stream
|
@var{symbols}. Within @var{code}, @code{yyoutput} denotes the output stream
|
||||||
(a @code{FILE*} in C, and an @code{std::ostream&} in C++),
|
(a @code{FILE*} in C, and an @code{std::ostream&} in C++), @code{$$} (or
|
||||||
@code{$$} designates the semantic value associated with the symbol, and
|
@code{$<@var{tag}>$}) designates the semantic value associated with the
|
||||||
@code{@@$} its location. The additional parser parameters are also
|
symbol, and @code{@@$} its location. The additional parser parameters are
|
||||||
available (@pxref{Parser Function, , The Parser Function @code{yyparse}}).
|
also available (@pxref{Parser Function, , The Parser Function
|
||||||
|
@code{yyparse}}).
|
||||||
|
|
||||||
The @var{symbols} are defined as for @code{%destructor} (@pxref{Destructor
|
The @var{symbols} are defined as for @code{%destructor} (@pxref{Destructor
|
||||||
Decl, , Freeing Discarded Symbols}.): they can be per-type (e.g.,
|
Decl, , Freeing Discarded Symbols}.): they can be per-type (e.g.,
|
||||||
|
|||||||
@@ -264,8 +264,12 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$"
|
|||||||
|
|
||||||
<SC_SYMBOL_ACTION>
|
<SC_SYMBOL_ACTION>
|
||||||
{
|
{
|
||||||
"$$" {
|
"$"("<"{tag}">")?"$" {
|
||||||
obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
|
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;
|
self->is_value_used = true;
|
||||||
}
|
}
|
||||||
"@$" {
|
"@$" {
|
||||||
|
|||||||
137
tests/actions.at
137
tests/actions.at
@@ -1230,6 +1230,143 @@ AT_CHECK_ACTION_LOCATIONS([[%destructor]])
|
|||||||
AT_CHECK_ACTION_LOCATIONS([[%printer]])
|
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. ##
|
## Fix user actions without a trailing semicolon. ##
|
||||||
## ----------------------------------------------- ##
|
## ----------------------------------------------- ##
|
||||||
|
|||||||
@@ -288,16 +288,16 @@ static int power (int base, int exponent);
|
|||||||
]AT_YYLEX_DECLARE_EXTERN[
|
]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
|
/* The lalr1.cc skeleton, for backward compatibility, defines
|
||||||
a constructor for position that initializes the filename. The
|
a constructor for position that initializes the filename. The
|
||||||
glr.cc skeleton does not (and in fact cannot: location/position
|
glr.cc skeleton does not (and in fact cannot: location/position
|
||||||
are stored in a union, from which objects with constructors are
|
are stored in a union, from which objects with constructors are
|
||||||
excluded in C++. */
|
excluded in C++). */
|
||||||
%initial-action {
|
%initial-action {
|
||||||
@$.initialize ();
|
@$.initialize ();
|
||||||
}
|
}
|
||||||
])])[
|
]])])[
|
||||||
|
|
||||||
/* Bison Declarations */
|
/* Bison Declarations */
|
||||||
%token CALC_EOF 0 "end of input"
|
%token CALC_EOF 0 "end of input"
|
||||||
|
|||||||
Reference in New Issue
Block a user