* 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++.
*** 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
$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])
@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}.
@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.,
<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;
}
"@$" {
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. ##
## ----------------------------------------------- ##
]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"