Split the default %destructor/%printer into two kinds: <*> and <!>.

Discussed starting at
<http://lists.gnu.org/archive/html/bison-patches/2006-09/msg00060.html>.
* NEWS (2.3a+): Mention.
* doc/bison.texinfo (Freeing Discarded Symbols): Document this and the
previous change today related to mid-rules.
(Bison Symbols): Remove %symbol-default and add <*> and <!>.
* src/parser-gram.y (PERCENT_SYMBOL_DEFAULT): Remove.
(TYPE_TAG_ANY): Add as <*>.
(TYPE_TAG_NONE): Add as <!>.
(generic_symlist_item): Remove RHS for %symbol-default and add RHS's
for <*> and <!>.
* src/scan-gram.l (PERCENT_SYMBOL_DEFAULT): Remove.
(TYPE_TAG_ANY, TYPE_TAG_NONE): Add.
* src/symlist.c (symbol_list_default_new): Split into tagged and
tagless versions.
(symbol_list_destructor_set, symbol_list_printer_set): Split
SYMLIST_DEFAULT case into SYMLIST_DEFAULT_TAGGED and
SYMLIST_DEFAULT_TAGLESS.
* src/symlist.h: Update symbol_list_default*_new prototypes.
(symbol_list.content_type): Split enum value SYMLIST_DEFAULT into
SYMLIST_DEFAULT_TAGGED and SYMLIST_DEFAULT_TAGLESS.
* src/symtab.c (default_destructor, default_destructor_location,
default_printer, default_printer_location): Split each into tagged and
tagless versions.
(symbol_destructor_get, symbol_destructor_location_get,
symbol_printer_get, symbol_printer_location_get): Implement tagged
default and tagless default cases.
(default_destructor_set, default_printer_set): Split each into tagged
and tagless versions.
* src/symtab.h: Update prototypes.
* tests/actions.at (Default %printer and %destructor): Rename to...
(Default tagless %printer and %destructor): ... this, and extend.
(Per-type %printer and %destructor): Rename to...
(Default tagged and per-type %printer and %destructor): ... this, and
extend.
(Default %printer and %destructor for user-defined end token): Extend.
(Default %printer and %destructor are not for error or $undefined):
Update.
(Default %printer and %destructor are not for $accept): Update.
(Default %printer and %destructor for mid-rule values): Extend.
* tests/input.at (Default %printer and %destructor redeclared): Extend.
(Unused values with default %destructor): Extend.
This commit is contained in:
Joel E. Denny
2006-10-21 10:03:35 +00:00
parent f91b162944
commit 12e3584054
13 changed files with 870 additions and 602 deletions

View File

@@ -1,3 +1,49 @@
2006-10-21 Joel E. Denny <jdenny@ces.clemson.edu>
Split the default %destructor/%printer into two kinds: <*> and <!>.
Discussed starting at
<http://lists.gnu.org/archive/html/bison-patches/2006-09/msg00060.html>.
* NEWS (2.3a+): Mention.
* doc/bison.texinfo (Freeing Discarded Symbols): Document this and the
previous change today related to mid-rules.
(Bison Symbols): Remove %symbol-default and add <*> and <!>.
* src/parser-gram.y (PERCENT_SYMBOL_DEFAULT): Remove.
(TYPE_TAG_ANY): Add as <*>.
(TYPE_TAG_NONE): Add as <!>.
(generic_symlist_item): Remove RHS for %symbol-default and add RHS's
for <*> and <!>.
* src/scan-gram.l (PERCENT_SYMBOL_DEFAULT): Remove.
(TYPE_TAG_ANY, TYPE_TAG_NONE): Add.
* src/symlist.c (symbol_list_default_new): Split into tagged and
tagless versions.
(symbol_list_destructor_set, symbol_list_printer_set): Split
SYMLIST_DEFAULT case into SYMLIST_DEFAULT_TAGGED and
SYMLIST_DEFAULT_TAGLESS.
* src/symlist.h: Update symbol_list_default*_new prototypes.
(symbol_list.content_type): Split enum value SYMLIST_DEFAULT into
SYMLIST_DEFAULT_TAGGED and SYMLIST_DEFAULT_TAGLESS.
* src/symtab.c (default_destructor, default_destructor_location,
default_printer, default_printer_location): Split each into tagged and
tagless versions.
(symbol_destructor_get, symbol_destructor_location_get,
symbol_printer_get, symbol_printer_location_get): Implement tagged
default and tagless default cases.
(default_destructor_set, default_printer_set): Split each into tagged
and tagless versions.
* src/symtab.h: Update prototypes.
* tests/actions.at (Default %printer and %destructor): Rename to...
(Default tagless %printer and %destructor): ... this, and extend.
(Per-type %printer and %destructor): Rename to...
(Default tagged and per-type %printer and %destructor): ... this, and
extend.
(Default %printer and %destructor for user-defined end token): Extend.
(Default %printer and %destructor are not for error or $undefined):
Update.
(Default %printer and %destructor are not for $accept): Update.
(Default %printer and %destructor for mid-rule values): Extend.
* tests/input.at (Default %printer and %destructor redeclared): Extend.
(Unused values with default %destructor): Extend.
2006-10-21 Joel E. Denny <jdenny@ces.clemson.edu>
Don't apply the default %destructor/%printer to an unreferenced midrule

19
NEWS
View File

@@ -6,6 +6,25 @@ Changes in version 2.3a+ (????-??-??):
* The -g and --graph options now output graphs in Graphviz DOT format,
not VCG format.
* Bison now recognizes two separate kinds of default %destructor's and
%printer's:
1. Place `<*>' in a %destructor/%printer symbol list to define a default
%destructor/%printer for all grammar symbols for which you have formally
declared semantic type tags.
2. Place `<!>' in a %destructor/%printer symbol list to define a default
%destructor/%printer for all grammar symbols without declared semantic
type tags.
Bison no longer supports the `%symbol-default' notation from Bison 2.3a.
`<*>' and `<!>' combined achieve the same effect with one exception: Bison no
longer applies any %destructor to a mid-rule value if that mid-rule value is
not actually ever referenced using either $$ or $n in a semantic action.
See the section `Freeing Discarded Symbols' in the Bison manual for further
details.
* The Yacc prologue alternatives from Bison 2.3a have been rewritten as the
following directives:

View File

@@ -4236,8 +4236,8 @@ For instance, if your locations use a file name, you may use
@subsection Freeing Discarded Symbols
@cindex freeing discarded symbols
@findex %destructor
@findex %symbol-default
@findex <*>
@findex <!>
During error recovery (@pxref{Error Recovery}), symbols already pushed
on the stack and tokens coming from the rest of the file are discarded
until the parser falls on its feet. If the parser runs out of memory,
@@ -4265,21 +4265,26 @@ The Parser Function @code{yyparse}}).
When a symbol is listed among @var{symbols}, its @code{%destructor} is called a
per-symbol @code{%destructor}.
You may also define a per-type @code{%destructor} by listing a semantic type
among @var{symbols}.
tag among @var{symbols}.
In that case, the parser will invoke this @var{code} whenever it discards any
grammar symbol that has that semantic type unless that symbol has its own
grammar symbol that has that semantic type tag unless that symbol has its own
per-symbol @code{%destructor}.
Finally, you may define a default @code{%destructor} by placing
@code{%symbol-default} in the @var{symbols} list of exactly one
@code{%destructor} declaration in your grammar file.
In that case, the parser will invoke the associated @var{code} whenever it
discards any user-defined grammar symbol for which there is no per-type or
per-symbol @code{%destructor}.
Finally, you can define two different kinds of default @code{%destructor}s.
You can place each of @code{<*>} and @code{<!>} in the @var{symbols} list of
exactly one @code{%destructor} declaration in your grammar file.
The parser will invoke the @var{code} associated with one of these whenever it
discards any user-defined grammar symbol that has no per-symbol and no per-type
@code{%destructor}.
The parser uses the @var{code} for @code{<*>} in the case of such a grammar
symbol for which you have formally declared a semantic type tag (@code{%type}
counts as such a declaration, but @code{$<tag>$} does not).
The parser uses the @var{code} for @code{<!>} in the case of such a grammar
symbol that has no declared semantic type tag.
@end deffn
@noindent
For instance:
For example:
@smallexample
%union @{ char *string; @}
@@ -4290,35 +4295,52 @@ For instance:
%union @{ char character; @}
%token <character> CHR
%type <character> chr
%destructor @{ free ($$); @} %symbol-default
%destructor @{ free ($$); printf ("%d", @@$.first_line); @} STRING1 string1
%token TAGLESS
%destructor @{ @} <character>
%destructor @{ free ($$); @} <*>
%destructor @{ free ($$); printf ("%d", @@$.first_line); @} STRING1 string1
%destructor @{ printf ("Discarding tagless symbol.\n"); @} <!>
@end smallexample
@noindent
guarantees that, when the parser discards any user-defined symbol that has a
semantic type tag other than @code{<character>}, it passes its semantic value
to @code{free}.
to @code{free} by default.
However, when the parser discards a @code{STRING1} or a @code{string1}, it also
prints its line number to @code{stdout}.
It performs only the second @code{%destructor} in this case, so it invokes
@code{free} only once.
Finally, the parser merely prints a message whenever it discards any symbol,
such as @code{TAGLESS}, that has no semantic type tag.
Notice that a Bison-generated parser invokes the default @code{%destructor}
only for user-defined as opposed to Bison-defined symbols.
For example, the parser will not invoke it for the special Bison-defined
symbols @code{$accept}, @code{$undefined}, or @code{$end} (@pxref{Table of
Symbols, ,Bison Symbols}), none of which you can reference in your grammar.
It also will not invoke it for the @code{error} token (@pxref{Table of Symbols,
,error}), which is always defined by Bison regardless of whether you reference
it in your grammar.
However, it will invoke it for the end token (token 0) if you redefine it from
@code{$end} to, for example, @code{END}:
A Bison-generated parser invokes the default @code{%destructor}s only for
user-defined as opposed to Bison-defined symbols.
For example, the parser will not invoke either kind of default
@code{%destructor} for the special Bison-defined symbols @code{$accept},
@code{$undefined}, or @code{$end} (@pxref{Table of Symbols, ,Bison Symbols}),
none of which you can reference in your grammar.
It also will not invoke either for the @code{error} token (@pxref{Table of
Symbols, ,error}), which is always defined by Bison regardless of whether you
reference it in your grammar.
However, it may invoke one of them for the end token (token 0) if you
redefine it from @code{$end} to, for example, @code{END}:
@smallexample
%token END 0
@end smallexample
@cindex actions in mid-rule
@cindex mid-rule actions
Finally, Bison will never invoke a @code{%destructor} for an unreferenced
mid-rule semantic value (@pxref{Mid-Rule Actions,,Actions in Mid-Rule}).
That is, Bison does not consider a mid-rule to have a semantic value if you do
not reference @code{$$} in the mid-rule's action or @code{$@var{n}} (where
@var{n} is the RHS symbol position of the mid-rule) in any later action in that
rule.
However, if you do reference either, the Bison-generated parser will invoke the
@code{<!>} @code{%destructor} whenever it discards the mid-rule symbol.
@ignore
@noindent
In the future, it may be possible to redefine the @code{error} token as a
@@ -8544,6 +8566,18 @@ Separates alternate rules for the same result nonterminal.
@xref{Rules, ,Syntax of Grammar Rules}.
@end deffn
@deffn {Directive} <*>
Used to define a default tagged @code{%destructor} or default tagged
@code{%printer}.
@xref{Destructor Decl, , Freeing Discarded Symbols}.
@end deffn
@deffn {Directive} <!>
Used to define a default tagless @code{%destructor} or default tagless
@code{%printer}.
@xref{Destructor Decl, , Freeing Discarded Symbols}.
@end deffn
@deffn {Symbol} $accept
The predefined nonterminal whose only rule is @samp{$accept: @var{start}
$end}, where @var{start} is the start symbol. @xref{Start Decl, , The
@@ -8776,11 +8810,6 @@ Bison declaration to specify the start symbol. @xref{Start Decl, ,The
Start-Symbol}.
@end deffn
@deffn {Directive} %symbol-default
Used to declare a default @code{%destructor} or default @code{%printer}.
@xref{Destructor Decl, , Freeing Discarded Symbols}.
@end deffn
@deffn {Directive} %token
Bison declaration to declare token(s) without specifying precedence.
@xref{Token Decl, ,Token Type Names}.

File diff suppressed because it is too large Load Diff

View File

@@ -48,55 +48,56 @@
PERCENT_TYPE = 262,
PERCENT_DESTRUCTOR = 263,
PERCENT_PRINTER = 264,
PERCENT_SYMBOL_DEFAULT = 265,
PERCENT_LEFT = 266,
PERCENT_RIGHT = 267,
PERCENT_NONASSOC = 268,
PERCENT_PREC = 269,
PERCENT_DPREC = 270,
PERCENT_MERGE = 271,
PERCENT_CODE = 272,
PERCENT_CODE_TOP = 273,
PERCENT_DEBUG = 274,
PERCENT_DEFAULT_PREC = 275,
PERCENT_DEFINE = 276,
PERCENT_DEFINES = 277,
PERCENT_ERROR_VERBOSE = 278,
PERCENT_EXPECT = 279,
PERCENT_EXPECT_RR = 280,
PERCENT_FILE_PREFIX = 281,
PERCENT_GLR_PARSER = 282,
PERCENT_INITIAL_ACTION = 283,
PERCENT_LEX_PARAM = 284,
PERCENT_LOCATIONS = 285,
PERCENT_NAME_PREFIX = 286,
PERCENT_NO_DEFAULT_PREC = 287,
PERCENT_NO_LINES = 288,
PERCENT_NONDETERMINISTIC_PARSER = 289,
PERCENT_OUTPUT = 290,
PERCENT_PARSE_PARAM = 291,
PERCENT_PROVIDES = 292,
PERCENT_PURE_PARSER = 293,
PERCENT_PUSH_PARSER = 294,
PERCENT_REQUIRE = 295,
PERCENT_REQUIRES = 296,
PERCENT_SKELETON = 297,
PERCENT_START = 298,
PERCENT_TOKEN_TABLE = 299,
PERCENT_VERBOSE = 300,
PERCENT_YACC = 301,
BRACED_CODE = 302,
CHAR = 303,
EPILOGUE = 304,
EQUAL = 305,
ID = 306,
ID_COLON = 307,
PERCENT_PERCENT = 308,
PIPE = 309,
PROLOGUE = 310,
SEMICOLON = 311,
TYPE = 312,
PERCENT_UNION = 313
PERCENT_LEFT = 265,
PERCENT_RIGHT = 266,
PERCENT_NONASSOC = 267,
PERCENT_PREC = 268,
PERCENT_DPREC = 269,
PERCENT_MERGE = 270,
PERCENT_CODE = 271,
PERCENT_CODE_TOP = 272,
PERCENT_DEBUG = 273,
PERCENT_DEFAULT_PREC = 274,
PERCENT_DEFINE = 275,
PERCENT_DEFINES = 276,
PERCENT_ERROR_VERBOSE = 277,
PERCENT_EXPECT = 278,
PERCENT_EXPECT_RR = 279,
PERCENT_FILE_PREFIX = 280,
PERCENT_GLR_PARSER = 281,
PERCENT_INITIAL_ACTION = 282,
PERCENT_LEX_PARAM = 283,
PERCENT_LOCATIONS = 284,
PERCENT_NAME_PREFIX = 285,
PERCENT_NO_DEFAULT_PREC = 286,
PERCENT_NO_LINES = 287,
PERCENT_NONDETERMINISTIC_PARSER = 288,
PERCENT_OUTPUT = 289,
PERCENT_PARSE_PARAM = 290,
PERCENT_PROVIDES = 291,
PERCENT_PURE_PARSER = 292,
PERCENT_PUSH_PARSER = 293,
PERCENT_REQUIRE = 294,
PERCENT_REQUIRES = 295,
PERCENT_SKELETON = 296,
PERCENT_START = 297,
PERCENT_TOKEN_TABLE = 298,
PERCENT_VERBOSE = 299,
PERCENT_YACC = 300,
BRACED_CODE = 301,
CHAR = 302,
EPILOGUE = 303,
EQUAL = 304,
ID = 305,
ID_COLON = 306,
PERCENT_PERCENT = 307,
PIPE = 308,
PROLOGUE = 309,
SEMICOLON = 310,
TYPE = 311,
TYPE_TAG_ANY = 312,
TYPE_TAG_NONE = 313,
PERCENT_UNION = 314
};
#endif
/* Tokens. */
@@ -108,55 +109,56 @@
#define PERCENT_TYPE 262
#define PERCENT_DESTRUCTOR 263
#define PERCENT_PRINTER 264
#define PERCENT_SYMBOL_DEFAULT 265
#define PERCENT_LEFT 266
#define PERCENT_RIGHT 267
#define PERCENT_NONASSOC 268
#define PERCENT_PREC 269
#define PERCENT_DPREC 270
#define PERCENT_MERGE 271
#define PERCENT_CODE 272
#define PERCENT_CODE_TOP 273
#define PERCENT_DEBUG 274
#define PERCENT_DEFAULT_PREC 275
#define PERCENT_DEFINE 276
#define PERCENT_DEFINES 277
#define PERCENT_ERROR_VERBOSE 278
#define PERCENT_EXPECT 279
#define PERCENT_EXPECT_RR 280
#define PERCENT_FILE_PREFIX 281
#define PERCENT_GLR_PARSER 282
#define PERCENT_INITIAL_ACTION 283
#define PERCENT_LEX_PARAM 284
#define PERCENT_LOCATIONS 285
#define PERCENT_NAME_PREFIX 286
#define PERCENT_NO_DEFAULT_PREC 287
#define PERCENT_NO_LINES 288
#define PERCENT_NONDETERMINISTIC_PARSER 289
#define PERCENT_OUTPUT 290
#define PERCENT_PARSE_PARAM 291
#define PERCENT_PROVIDES 292
#define PERCENT_PURE_PARSER 293
#define PERCENT_PUSH_PARSER 294
#define PERCENT_REQUIRE 295
#define PERCENT_REQUIRES 296
#define PERCENT_SKELETON 297
#define PERCENT_START 298
#define PERCENT_TOKEN_TABLE 299
#define PERCENT_VERBOSE 300
#define PERCENT_YACC 301
#define BRACED_CODE 302
#define CHAR 303
#define EPILOGUE 304
#define EQUAL 305
#define ID 306
#define ID_COLON 307
#define PERCENT_PERCENT 308
#define PIPE 309
#define PROLOGUE 310
#define SEMICOLON 311
#define TYPE 312
#define PERCENT_UNION 313
#define PERCENT_LEFT 265
#define PERCENT_RIGHT 266
#define PERCENT_NONASSOC 267
#define PERCENT_PREC 268
#define PERCENT_DPREC 269
#define PERCENT_MERGE 270
#define PERCENT_CODE 271
#define PERCENT_CODE_TOP 272
#define PERCENT_DEBUG 273
#define PERCENT_DEFAULT_PREC 274
#define PERCENT_DEFINE 275
#define PERCENT_DEFINES 276
#define PERCENT_ERROR_VERBOSE 277
#define PERCENT_EXPECT 278
#define PERCENT_EXPECT_RR 279
#define PERCENT_FILE_PREFIX 280
#define PERCENT_GLR_PARSER 281
#define PERCENT_INITIAL_ACTION 282
#define PERCENT_LEX_PARAM 283
#define PERCENT_LOCATIONS 284
#define PERCENT_NAME_PREFIX 285
#define PERCENT_NO_DEFAULT_PREC 286
#define PERCENT_NO_LINES 287
#define PERCENT_NONDETERMINISTIC_PARSER 288
#define PERCENT_OUTPUT 289
#define PERCENT_PARSE_PARAM 290
#define PERCENT_PROVIDES 291
#define PERCENT_PURE_PARSER 292
#define PERCENT_PUSH_PARSER 293
#define PERCENT_REQUIRE 294
#define PERCENT_REQUIRES 295
#define PERCENT_SKELETON 296
#define PERCENT_START 297
#define PERCENT_TOKEN_TABLE 298
#define PERCENT_VERBOSE 299
#define PERCENT_YACC 300
#define BRACED_CODE 301
#define CHAR 302
#define EPILOGUE 303
#define EQUAL 304
#define ID 305
#define ID_COLON 306
#define PERCENT_PERCENT 307
#define PIPE 308
#define PROLOGUE 309
#define SEMICOLON 310
#define TYPE 311
#define TYPE_TAG_ANY 312
#define TYPE_TAG_NONE 313
#define PERCENT_UNION 314
@@ -177,7 +179,7 @@ typedef union YYSTYPE
}
/* Line 1535 of yacc.c */
#line 181 "parse-gram.h"
#line 183 "parse-gram.h"
YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */

View File

@@ -116,8 +116,6 @@ static int current_prec = 0;
%token PERCENT_TYPE "%type"
%token PERCENT_DESTRUCTOR "%destructor"
%token PERCENT_PRINTER "%printer"
%token PERCENT_SYMBOL_DEFAULT
"%symbol-default"
%token PERCENT_LEFT "%left"
%token PERCENT_RIGHT "%right"
@@ -177,6 +175,8 @@ static int current_prec = 0;
%token PROLOGUE "%{...%}"
%token SEMICOLON ";"
%token TYPE "type"
%token TYPE_TAG_ANY "<*>"
%token TYPE_TAG_NONE "<!>"
%type <character> CHAR
%printer { fputs (char_name ($$), stderr); } CHAR
@@ -395,7 +395,8 @@ generic_symlist:
generic_symlist_item:
symbol { $$ = symbol_list_sym_new ($1, @1); }
| TYPE { $$ = symbol_list_type_new ($1, @1); }
| "%symbol-default" { $$ = symbol_list_default_new (@1); }
| "<*>" { $$ = symbol_list_default_tagged_new (@1); }
| "<!>" { $$ = symbol_list_default_tagless_new (@1); }
;
/* One token definition. */

View File

@@ -194,7 +194,6 @@ splice (\\[ \f\t\v]*\n)*
"%right" return PERCENT_RIGHT;
"%skeleton" return PERCENT_SKELETON;
"%start" return PERCENT_START;
"%symbol-default" return PERCENT_SYMBOL_DEFAULT;
"%term" return PERCENT_TOKEN;
"%token" return PERCENT_TOKEN;
"%token"[-_]"table" return PERCENT_TOKEN_TABLE;
@@ -210,6 +209,8 @@ splice (\\[ \f\t\v]*\n)*
"=" return EQUAL;
"|" return PIPE;
";" return SEMICOLON;
"<*>" return TYPE_TAG_ANY;
"<!>" return TYPE_TAG_NONE;
{id} {
val->uniqstr = uniqstr_new (yytext);

View File

@@ -74,16 +74,33 @@ symbol_list_type_new (uniqstr type_name, location loc)
}
/*----------------------------------------------------.
| Create a list containing a %symbol-default at LOC. |
`----------------------------------------------------*/
/*----------------------------------------.
| Create a list containing a <*> at LOC. |
`----------------------------------------*/
symbol_list *
symbol_list_default_new (location loc)
symbol_list_default_tagged_new (location loc)
{
symbol_list *res = xmalloc (sizeof *res);
res->content_type = SYMLIST_DEFAULT;
res->content_type = SYMLIST_DEFAULT_TAGGED;
res->location = loc;
res->next = NULL;
return res;
}
/*----------------------------------------.
| Create a list containing a <!> at LOC. |
`----------------------------------------*/
symbol_list *
symbol_list_default_tagless_new (location loc)
{
symbol_list *res = xmalloc (sizeof *res);
res->content_type = SYMLIST_DEFAULT_TAGLESS;
res->location = loc;
res->next = NULL;
@@ -215,8 +232,11 @@ symbol_list_destructor_set (symbol_list *node, const char *destructor,
semantic_type_destructor_set (
semantic_type_get (node->content.type_name), destructor, loc);
break;
case SYMLIST_DEFAULT:
default_destructor_set (destructor, loc);
case SYMLIST_DEFAULT_TAGGED:
default_tagged_destructor_set (destructor, loc);
break;
case SYMLIST_DEFAULT_TAGLESS:
default_tagless_destructor_set (destructor, loc);
break;
}
}
@@ -233,8 +253,11 @@ symbol_list_printer_set (symbol_list *node, const char *printer, location loc)
semantic_type_printer_set (
semantic_type_get (node->content.type_name), printer, loc);
break;
case SYMLIST_DEFAULT:
default_printer_set (printer, loc);
case SYMLIST_DEFAULT_TAGGED:
default_tagged_printer_set (printer, loc);
break;
case SYMLIST_DEFAULT_TAGLESS:
default_tagless_printer_set (printer, loc);
break;
}
}

View File

@@ -29,10 +29,13 @@
typedef struct symbol_list
{
/**
* Whether this node contains a symbol, a semantic type, or a
* \c \%symbol-default.
* Whether this node contains a symbol, a semantic type, a \c <*>, or a
* \c <!>.
*/
enum { SYMLIST_SYMBOL, SYMLIST_TYPE, SYMLIST_DEFAULT } content_type;
enum {
SYMLIST_SYMBOL, SYMLIST_TYPE,
SYMLIST_DEFAULT_TAGGED, SYMLIST_DEFAULT_TAGLESS
} content_type;
union {
/** The symbol or \c NULL iff <tt>node_type = SYMLIST_SYMBOL</tt>. */
symbol *sym;
@@ -76,8 +79,10 @@ symbol_list *symbol_list_sym_new (symbol *sym, location loc);
/** Create a list containing \c type_name at \c loc. */
symbol_list *symbol_list_type_new (uniqstr type_name, location loc);
/** Create a list containing a \c \%symbol-default at \c loc. */
symbol_list *symbol_list_default_new (location loc);
/** Create a list containing a \c <*> at \c loc. */
symbol_list *symbol_list_default_tagged_new (location loc);
/** Create a list containing a \c <!> at \c loc. */
symbol_list *symbol_list_default_tagless_new (location loc);
/** Print this list.

View File

@@ -41,14 +41,19 @@ symbol *accept = NULL;
symbol *startsymbol = NULL;
location startsymbol_location;
/*-----------------------------------.
| Default %destructor and %printer. |
`-----------------------------------*/
/*---------------------------------------.
| Default %destructor's and %printer's. |
`---------------------------------------*/
static const char *default_destructor = NULL;
static location default_destructor_location;
static const char *default_printer = NULL;
static location default_printer_location;
static const char *default_tagged_destructor = NULL;
static location default_tagged_destructor_location;
static const char *default_tagless_destructor = NULL;
static location default_tagless_destructor_location;
static const char *default_tagged_printer = NULL;
static location default_tagged_printer_location;
static const char *default_tagless_printer = NULL;
static location default_tagless_printer_location;
/*---------------------------------.
| Create a new symbol, named TAG. |
@@ -220,10 +225,13 @@ symbol_destructor_get (symbol *sym)
return type->destructor;
}
/* Apply the default %destructor only to user-defined symbols. */
/* Apply default %destructor's only to user-defined symbols. */
if (sym->tag[0] == '$' || sym == errtoken)
return NULL;
return default_destructor;
if (sym->type_name)
return default_tagged_destructor;
return default_tagless_destructor;
}
/*---------------------------------------------------------------.
@@ -240,8 +248,9 @@ symbol_destructor_location_get (symbol *sym)
semantic_type *type = semantic_type_get (sym->type_name);
if (type->destructor)
return type->destructor_location;
return default_tagged_destructor_location;
}
return default_destructor_location;
return default_tagless_destructor_location;
}
/*---------------------------------------------------------------.
@@ -300,7 +309,10 @@ symbol_printer_get (symbol *sym)
/* Apply the default %printer only to user-defined symbols. */
if (sym->tag[0] == '$' || sym == errtoken)
return NULL;
return default_printer;
if (sym->type_name)
return default_tagged_printer;
return default_tagless_printer;
}
/*------------------------------------------------------------.
@@ -317,8 +329,9 @@ symbol_printer_location_get (symbol *sym)
semantic_type *type = semantic_type_get (sym->type_name);
if (type->printer)
return type->printer_location;
return default_tagged_printer_location;
}
return default_printer_location;
return default_tagless_printer_location;
}
@@ -924,30 +937,58 @@ symbols_pack (void)
}
/*-----------------------------------.
| Set default %destructor/%printer. |
`-----------------------------------*/
/*--------------------------------------------------.
| Set default tagged/tagless %destructor/%printer. |
`--------------------------------------------------*/
void
default_destructor_set (const char *destructor, location loc)
default_tagged_destructor_set (const char *destructor, location loc)
{
if (default_destructor != NULL)
if (default_tagged_destructor != NULL)
{
complain_at (loc, _("redeclaration for default %%destructor"));
complain_at (default_destructor_location, _("previous declaration"));
complain_at (loc, _("redeclaration for default tagged %%destructor"));
complain_at (default_tagged_destructor_location,
_("previous declaration"));
}
default_destructor = destructor;
default_destructor_location = loc;
default_tagged_destructor = destructor;
default_tagged_destructor_location = loc;
}
void
default_printer_set (const char *printer, location loc)
default_tagless_destructor_set (const char *destructor, location loc)
{
if (default_printer != NULL)
if (default_tagless_destructor != NULL)
{
complain_at (loc, _("redeclaration for default %%printer"));
complain_at (default_printer_location, _("previous declaration"));
complain_at (loc, _("redeclaration for default tagless %%destructor"));
complain_at (default_tagless_destructor_location,
_("previous declaration"));
}
default_printer = printer;
default_printer_location = loc;
default_tagless_destructor = destructor;
default_tagless_destructor_location = loc;
}
void
default_tagged_printer_set (const char *printer, location loc)
{
if (default_tagged_printer != NULL)
{
complain_at (loc, _("redeclaration for default tagged %%printer"));
complain_at (default_tagged_printer_location,
_("previous declaration"));
}
default_tagged_printer = printer;
default_tagged_printer_location = loc;
}
void
default_tagless_printer_set (const char *printer, location loc)
{
if (default_tagless_printer != NULL)
{
complain_at (loc, _("redeclaration for default tagless %%printer"));
complain_at (default_tagless_printer_location,
_("previous declaration"));
}
default_tagless_printer = printer;
default_tagless_printer_location = loc;
}

View File

@@ -69,8 +69,8 @@ struct symbol
/** Any \c \%destructor declared specifically for this symbol.
Access this field only through <tt>symbol</tt>'s interface functions. For
example, if <tt>symbol::destructor = NULL</tt>, the default
\c \%destructor or a per-type \c \%destructor might be appropriate, and
example, if <tt>symbol::destructor = NULL</tt>, a default \c \%destructor
or a per-type \c \%destructor might be appropriate, and
\c symbol_destructor_get will compute the correct one. */
const char *destructor;
@@ -255,14 +255,18 @@ void symbols_check_defined (void);
void symbols_pack (void);
/*-----------------------------------.
| Default %destructor and %printer. |
`-----------------------------------*/
/*---------------------------------------.
| Default %destructor's and %printer's. |
`---------------------------------------*/
/** Set the default \c \%destructor. */
void default_destructor_set (const char *destructor, location loc);
/** Set the default \c \%destructor for tagged values. */
void default_tagged_destructor_set (const char *destructor, location loc);
/** Set the default \c \%destructor for tagless values. */
void default_tagless_destructor_set (const char *destructor, location loc);
/** Set the default \c \%printer. */
void default_printer_set (const char *printer, location loc);
/** Set the default \c \%printer for tagged values. */
void default_tagged_printer_set (const char *printer, location loc);
/** Set the default \c \%printer for tagless values. */
void default_tagless_printer_set (const char *printer, location loc);
#endif /* !SYMTAB_H_ */

View File

@@ -583,14 +583,14 @@ AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser], [with union])
## --------------------------------- ##
## Default %printer and %destructor. ##
## --------------------------------- ##
## ----------------------------------------- ##
## Default tagless %printer and %destructor. ##
## ----------------------------------------- ##
# Check that the right %printer and %destructor are called, that they're not
# called for $end, and that $$ and @$ work correctly.
AT_SETUP([Default %printer and %destructor])
AT_SETUP([Default tagless %printer and %destructor])
AT_DATA_GRAMMAR([[input.y]],
[[%error-verbose
@@ -610,11 +610,15 @@ AT_DATA_GRAMMAR([[input.y]],
%}
%printer {
fprintf (yyoutput, "Default printer for '%c' @ %d", $$, @$.first_column);
} %symbol-default
fprintf (yyoutput, "<*> printer should not be called.\n");
} <*>
%printer {
fprintf (yyoutput, "<!> printer for '%c' @ %d", $$, @$.first_column);
} <!>
%destructor {
fprintf (stdout, "Default destructor for '%c' @ %d.\n", $$, @$.first_column);
} %symbol-default
fprintf (stdout, "<!> destructor for '%c' @ %d.\n", $$, @$.first_column);
} <!>
%printer {
fprintf (yyoutput, "'b'/'c' printer for '%c' @ %d", $$, @$.first_column);
@@ -623,6 +627,10 @@ AT_DATA_GRAMMAR([[input.y]],
fprintf (stdout, "'b'/'c' destructor for '%c' @ %d.\n", $$, @$.first_column);
} 'b' 'c'
%destructor {
fprintf (yyoutput, "<*> destructor should not be called.\n");
} <*>
%%
start: 'a' 'b' 'c' 'd' 'e' { $$ = 'S'; USE(($1, $2, $3, $4, $5)); } ;
@@ -659,15 +667,15 @@ main (void)
AT_CHECK([bison -o input.c input.y])
AT_COMPILE([input])
AT_PARSER_CHECK([./input], 1,
[[Default destructor for 'd' @ 4.
[[<!> destructor for 'd' @ 4.
'b'/'c' destructor for 'c' @ 3.
'b'/'c' destructor for 'b' @ 2.
Default destructor for 'a' @ 1.
<!> destructor for 'a' @ 1.
]],
[[Starting parse
Entering state 0
Reading a token: Next token is token 'a' (1.1-1.1: Default printer for 'a' @ 1)
Shifting token 'a' (1.1-1.1: Default printer for 'a' @ 1)
Reading a token: Next token is token 'a' (1.1-1.1: <!> printer for 'a' @ 1)
Shifting token 'a' (1.1-1.1: <!> printer for 'a' @ 1)
Entering state 1
Reading a token: Next token is token 'b' (1.2-1.2: 'b'/'c' printer for 'b' @ 2)
Shifting token 'b' (1.2-1.2: 'b'/'c' printer for 'b' @ 2)
@@ -675,18 +683,18 @@ Entering state 3
Reading a token: Next token is token 'c' (1.3-1.3: 'b'/'c' printer for 'c' @ 3)
Shifting token 'c' (1.3-1.3: 'b'/'c' printer for 'c' @ 3)
Entering state 5
Reading a token: Next token is token 'd' (1.4-1.4: Default printer for 'd' @ 4)
Shifting token 'd' (1.4-1.4: Default printer for 'd' @ 4)
Reading a token: Next token is token 'd' (1.4-1.4: <!> printer for 'd' @ 4)
Shifting token 'd' (1.4-1.4: <!> printer for 'd' @ 4)
Entering state 6
Reading a token: Now at end of input.
syntax error, unexpected $end, expecting 'e'
Error: popping token 'd' (1.4-1.4: Default printer for 'd' @ 4)
Error: popping token 'd' (1.4-1.4: <!> printer for 'd' @ 4)
Stack now 0 1 3 5
Error: popping token 'c' (1.3-1.3: 'b'/'c' printer for 'c' @ 3)
Stack now 0 1 3
Error: popping token 'b' (1.2-1.2: 'b'/'c' printer for 'b' @ 2)
Stack now 0 1
Error: popping token 'a' (1.1-1.1: Default printer for 'a' @ 1)
Error: popping token 'a' (1.1-1.1: <!> printer for 'a' @ 1)
Stack now 0
Cleanup: discarding lookahead token $end (1.5-1.5: )
Stack now 0
@@ -696,11 +704,11 @@ AT_CLEANUP
## ----------------------------------- ##
## Per-type %printer and %destructor. ##
## ----------------------------------- ##
## ------------------------------------------------------ ##
## Default tagged and per-type %printer and %destructor. ##
## ------------------------------------------------------ ##
AT_SETUP([Per-type %printer and %destructor])
AT_SETUP([Default tagged and per-type %printer and %destructor])
AT_DATA_GRAMMAR([[input.y]],
[[%error-verbose
@@ -714,16 +722,20 @@ AT_DATA_GRAMMAR([[input.y]],
# define USE(SYM)
%}
%printer {
fprintf (yyoutput, "<!> printer should not be called.\n");
} <!>
%union { int field0; int field1; int field2; }
%type <field0> start 'a' 'g'
%type <field1> 'e'
%type <field2> 'f'
%printer {
fprintf (yyoutput, "%%symbol-default/<field2>/e printer");
} %symbol-default 'e' <field2>
fprintf (yyoutput, "<*>/<field2>/e printer");
} <*> 'e' <field2>
%destructor {
fprintf (stdout, "%%symbol-default/<field2>/e destructor.\n");
} %symbol-default 'e' <field2>
fprintf (stdout, "<*>/<field2>/e destructor.\n");
} <*> 'e' <field2>
%type <field1> 'b'
%printer { fprintf (yyoutput, "<field1> printer"); } <field1>
@@ -737,6 +749,10 @@ AT_DATA_GRAMMAR([[input.y]],
%printer { fprintf (yyoutput, "'d' printer"); } 'd'
%destructor { fprintf (stdout, "'d' destructor.\n"); } 'd'
%destructor {
fprintf (yyoutput, "<!> destructor should not be called.\n");
} <!>
%%
start:
@@ -776,17 +792,17 @@ main (void)
AT_CHECK([bison -o input.c input.y])
AT_COMPILE([input])
AT_PARSER_CHECK([./input], 1,
[[%symbol-default/<field2>/e destructor.
%symbol-default/<field2>/e destructor.
[[<*>/<field2>/e destructor.
<*>/<field2>/e destructor.
'd' destructor.
'c' destructor.
<field1> destructor.
%symbol-default/<field2>/e destructor.
<*>/<field2>/e destructor.
]],
[[Starting parse
Entering state 0
Reading a token: Next token is token 'a' (%symbol-default/<field2>/e printer)
Shifting token 'a' (%symbol-default/<field2>/e printer)
Reading a token: Next token is token 'a' (<*>/<field2>/e printer)
Shifting token 'a' (<*>/<field2>/e printer)
Entering state 1
Reading a token: Next token is token 'b' (<field1> printer)
Shifting token 'b' (<field1> printer)
@@ -797,17 +813,17 @@ Entering state 5
Reading a token: Next token is token 'd' ('d' printer)
Shifting token 'd' ('d' printer)
Entering state 6
Reading a token: Next token is token 'e' (%symbol-default/<field2>/e printer)
Shifting token 'e' (%symbol-default/<field2>/e printer)
Reading a token: Next token is token 'e' (<*>/<field2>/e printer)
Shifting token 'e' (<*>/<field2>/e printer)
Entering state 7
Reading a token: Next token is token 'f' (%symbol-default/<field2>/e printer)
Shifting token 'f' (%symbol-default/<field2>/e printer)
Reading a token: Next token is token 'f' (<*>/<field2>/e printer)
Shifting token 'f' (<*>/<field2>/e printer)
Entering state 8
Reading a token: Now at end of input.
syntax error, unexpected $end, expecting 'g'
Error: popping token 'f' (%symbol-default/<field2>/e printer)
Error: popping token 'f' (<*>/<field2>/e printer)
Stack now 0 1 3 5 6 7
Error: popping token 'e' (%symbol-default/<field2>/e printer)
Error: popping token 'e' (<*>/<field2>/e printer)
Stack now 0 1 3 5 6
Error: popping token 'd' ('d' printer)
Stack now 0 1 3 5
@@ -815,7 +831,7 @@ Error: popping token 'c' ('c' printer)
Stack now 0 1 3
Error: popping token 'b' (<field1> printer)
Stack now 0 1
Error: popping token 'a' (%symbol-default/<field2>/e printer)
Error: popping token 'a' (<*>/<field2>/e printer)
Stack now 0
Cleanup: discarding lookahead token $end ()
Stack now 0
@@ -826,12 +842,19 @@ AT_CLEANUP
## ------------------------------------------------------------- ##
## Default %printer and %destructor for user-defined end token. ##
## Default %printer and %destructor for user-defined end token. ##
## ------------------------------------------------------------- ##
AT_SETUP([Default %printer and %destructor for user-defined end token])
AT_DATA_GRAMMAR([[input.y]],
# _AT_CHECK_DEFAULT_PRINTER_AND_DESTRUCTOR_FOR_END_TOKEN(TYPED)
# -----------------------------------------------------------------------------
m4_define([_AT_CHECK_DEFAULT_PRINTER_AND_DESTRUCTOR_FOR_END_TOKEN],
[m4_if($1, 0,
[m4_pushdef([kind], [!]) m4_pushdef([not_kind], [*])],
[m4_pushdef([kind], [*]) m4_pushdef([not_kind], [!])])
AT_DATA_GRAMMAR([[input]]$1[[.y]],
[[%error-verbose
%debug
%locations
@@ -848,13 +871,26 @@ AT_DATA_GRAMMAR([[input.y]],
# define USE(SYM)
%}
%destructor {
fprintf (yyoutput, "<]]not_kind[[> destructor should not be called.\n");
} <]]not_kind[[>
%token END 0
%printer {
fprintf (yyoutput, "Default printer for '%c' @ %d", $$, @$.first_column);
} %symbol-default
fprintf (yyoutput, "<]]kind[[> for '%c' @ %d", $$, @$.first_column);
} <]]kind[[>
%destructor {
fprintf (stdout, "Default destructor for '%c' @ %d.\n", $$, @$.first_column);
} %symbol-default
fprintf (stdout, "<]]kind[[> for '%c' @ %d.\n", $$, @$.first_column);
} <]]kind[[>
%printer {
fprintf (yyoutput, "<]]not_kind[[> printer should not be called.\n");
} <]]not_kind[[>
]]m4_if($1, 0, [[[
]]],
[[[%union { char tag; }
%type <tag> start END]]])[[
%%
@@ -868,7 +904,7 @@ yylex (void)
static int called;
if (called++)
abort ();
yylval = 'E';
yylval]]m4_if($1, 0,, [[[.tag]]])[[ = 'E';
yylloc.first_line = yylloc.last_line = 1;
yylloc.first_column = yylloc.last_column = 1;
return 0;
@@ -888,26 +924,33 @@ main (void)
}
]])
AT_CHECK([bison -o input.c input.y])
AT_COMPILE([input])
AT_PARSER_CHECK([./input], 0,
[[Default destructor for 'E' @ 1.
Default destructor for 'S' @ 1.
AT_CHECK([bison -o input$1.c input$1.y])
AT_COMPILE([input$1])
AT_PARSER_CHECK([./input$1], 0,
[[<]]kind[[> for 'E' @ 1.
<]]kind[[> for 'S' @ 1.
]],
[[Starting parse
Entering state 0
Reducing stack by rule 1 (line 35):
-> $$ = nterm start (1.1-1.1: Default printer for 'S' @ 1)
Reducing stack by rule 1 (line 46):
-> $$ = nterm start (1.1-1.1: <]]kind[[> for 'S' @ 1)
Stack now 0
Entering state 1
Reading a token: Now at end of input.
Shifting token END (1.1-1.1: Default printer for 'E' @ 1)
Shifting token END (1.1-1.1: <]]kind[[> for 'E' @ 1)
Entering state 2
Stack now 0 1 2
Cleanup: popping token END (1.1-1.1: Default printer for 'E' @ 1)
Cleanup: popping nterm start (1.1-1.1: Default printer for 'S' @ 1)
Cleanup: popping token END (1.1-1.1: <]]kind[[> for 'E' @ 1)
Cleanup: popping nterm start (1.1-1.1: <]]kind[[> for 'S' @ 1)
]])
m4_popdef([kind])
m4_popdef([not_kind])
])
_AT_CHECK_DEFAULT_PRINTER_AND_DESTRUCTOR_FOR_END_TOKEN(0)
_AT_CHECK_DEFAULT_PRINTER_AND_DESTRUCTOR_FOR_END_TOKEN(1)
AT_CLEANUP
@@ -940,10 +983,10 @@ AT_DATA_GRAMMAR([[input.y]],
%printer {
fprintf (yyoutput, "'%c'", $$);
} %symbol-default
} <!> <*>
%destructor {
fprintf (stderr, "DESTROY '%c'\n", $$);
} %symbol-default
} <!> <*>
%%
@@ -1055,11 +1098,11 @@ AT_DATA_GRAMMAR([[input.y]],
%printer {
char chr = $$;
fprintf (yyoutput, "'%c'", chr);
} %symbol-default
} <!> <*>
%destructor {
char chr = $$;
fprintf (stderr, "DESTROY '%c'\n", chr);
} %symbol-default
} <!> <*>
%union { char chr; }
%type <chr> start
@@ -1119,8 +1162,10 @@ AT_DATA_GRAMMAR([[input.y]],
# define YY_LOCATION_PRINT(File, Loc)
%}
%printer { fprintf (yyoutput, "%d", @$); } %symbol-default
%destructor { fprintf (stderr, "DESTROY %d\n", @$); } %symbol-default
%printer { fprintf (yyoutput, "%d", @$); } <!>
%destructor { fprintf (stderr, "DESTROY %d\n", @$); } <!>
%printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
%destructor { fprintf (yyoutput, "<*> destructor should not be called"); } <*>
%%
@@ -1159,27 +1204,27 @@ main (void)
]])
AT_CHECK([bison -o input.c input.y], 0,,
[[input.y:31.3-23: warning: unset value: $$
input.y:28.3-33.37: warning: unused value: $3
[[input.y:33.3-23: warning: unset value: $$
input.y:30.3-35.37: warning: unused value: $3
]])
AT_COMPILE([input])
AT_PARSER_CHECK([./input], 1,,
[[Starting parse
Entering state 0
Reducing stack by rule 1 (line 28):
Reducing stack by rule 1 (line 30):
-> $$ = nterm $@1 (: )
Stack now 0
Entering state 2
Reducing stack by rule 2 (line 29):
Reducing stack by rule 2 (line 31):
-> $$ = nterm @2 (: 2)
Stack now 0 2
Entering state 4
Reducing stack by rule 3 (line 30):
Reducing stack by rule 3 (line 32):
-> $$ = nterm @3 (: 3)
Stack now 0 2 4
Entering state 5
Reducing stack by rule 4 (line 31):
Reducing stack by rule 4 (line 33):
-> $$ = nterm @4 (: 4)
Stack now 0 2 4 5
Entering state 6

View File

@@ -178,33 +178,54 @@ AT_CLEANUP
AT_SETUP([Default %printer and %destructor redeclared])
AT_DATA([[input.y]],
[[%destructor { destroy ($$); } %symbol-default %symbol-default
%printer { destroy ($$); } %symbol-default %symbol-default
[[%destructor { destroy ($$); } <*> <*>
%printer { destroy ($$); } <*> <*>
%destructor { destroy ($$); } %symbol-default
%printer { destroy ($$); } %symbol-default
%destructor { destroy ($$); } <*>
%printer { destroy ($$); } <*>
%destructor { destroy ($$); } <!> <!>
%printer { destroy ($$); } <!> <!>
%destructor { destroy ($$); } <!>
%printer { destroy ($$); } <!>
%%
start: ;
%destructor { destroy ($$); } %symbol-default;
%printer { destroy ($$); } %symbol-default;
%destructor { destroy ($$); } <*>;
%printer { destroy ($$); } <*>;
%destructor { destroy ($$); } <!>;
%printer { destroy ($$); } <!>;
]])
AT_CHECK([bison input.y], [1], [],
[[input.y:1.13-29: redeclaration for default %destructor
[[input.y:1.13-29: redeclaration for default tagged %destructor
input.y:1.13-29: previous declaration
input.y:2.10-26: redeclaration for default %printer
input.y:2.10-26: redeclaration for default tagged %printer
input.y:2.10-26: previous declaration
input.y:4.13-29: redeclaration for default %destructor
input.y:4.13-29: redeclaration for default tagged %destructor
input.y:1.13-29: previous declaration
input.y:5.10-26: redeclaration for default %printer
input.y:5.10-26: redeclaration for default tagged %printer
input.y:2.10-26: previous declaration
input.y:11.13-29: redeclaration for default %destructor
input.y:7.13-29: redeclaration for default tagless %destructor
input.y:7.13-29: previous declaration
input.y:8.10-26: redeclaration for default tagless %printer
input.y:8.10-26: previous declaration
input.y:10.13-29: redeclaration for default tagless %destructor
input.y:7.13-29: previous declaration
input.y:11.10-26: redeclaration for default tagless %printer
input.y:8.10-26: previous declaration
input.y:17.13-29: redeclaration for default tagged %destructor
input.y:4.13-29: previous declaration
input.y:12.10-26: redeclaration for default %printer
input.y:18.10-26: redeclaration for default tagged %printer
input.y:5.10-26: previous declaration
input.y:20.13-29: redeclaration for default tagless %destructor
input.y:10.13-29: previous declaration
input.y:21.10-26: redeclaration for default tagless %printer
input.y:11.10-26: previous declaration
]])
AT_CLEANUP
@@ -260,18 +281,36 @@ AT_CLEANUP
AT_SETUP([Unused values with default %destructor])
AT_DATA([[input.y]],
[[%destructor { destroy ($$); } %symbol-default
[[%destructor { destroy ($$); } <!>
%type <tag> tagged
%%
start: end end { $1; } ;
end: { } ;
start: end end tagged tagged { $<tag>1; $3; } ;
end: { } ;
tagged: { } ;
]])
AT_CHECK([bison input.y], [0], [],
[[input.y:5.8-22: warning: unset value: $$
input.y:5.8-22: warning: unused value: $2
input.y:6.6-8: warning: unset value: $$
[[input.y:6.8-45: warning: unset value: $$
input.y:6.8-45: warning: unused value: $2
input.y:7.6-8: warning: unset value: $$
]])
AT_DATA([[input.y]],
[[%destructor { destroy ($$); } <*>
%type <tag> tagged
%%
start: end end tagged tagged { $<tag>1; $3; } ;
end: { } ;
tagged: { } ;
]])
AT_CHECK([bison input.y], [0], [],
[[input.y:6.8-45: warning: unused value: $4
input.y:8.9-11: warning: unset value: $$
]])
AT_CLEANUP