]> git.saurik.com Git - bison.git/commitdiff
support $<tag>$ in printers and destructors
authorAkim Demaille <akim@lrde.epita.fr>
Thu, 26 Jul 2012 14:52:35 +0000 (16:52 +0200)
committerAkim Demaille <akim@lrde.epita.fr>
Thu, 26 Jul 2012 16:30:43 +0000 (18:30 +0200)
* 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++.

NEWS
data/c.m4
doc/bison.texi
src/scan-code.l
tests/actions.at
tests/calc.at

diff --git a/NEWS b/NEWS
index b97956cccf16b923dd3ab87b04b703f1bba58f4c..56961cc26ccabf7f2f8090e5856a3f120893ea76 100644 (file)
--- 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)", $<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
index 08296c657cf13d3617f95080393eb5a38d7a8fc1..3954613bfb7c5e992678356315c110c156fcaf2a 100644 (file)
--- 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 $<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])
index 6156b41f59c6155af5481d75db5d3102b09305d8..e50bd1717117cea21ff64a7c3a24a4e8fc34acb0 100644 (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.,
index 2fab6d9d1d248e2a3a122fc425a8bbc871375005..e30bf9db6b6837135d2ff5e5fc535347df0cc63a 100644 (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;
   }
   "@$" {
index e8e8cd972093632d23b02b2db499f4817dc8b065..dd909b00d7496534390b078c5afd739a63094136 100644 (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.  ##
 ## ----------------------------------------------- ##
index e4cb07f19c3365605d7b4956f0e96156d3b5c993..31ee44e29e19afac266e6d72c914b9b10f8ff62a 100644 (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"