[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: FYI: default %printer/%destructor
From: |
Joel E. Denny |
Subject: |
Re: FYI: default %printer/%destructor |
Date: |
Mon, 4 Sep 2006 15:29:32 -0400 (EDT) |
On Sun, 3 Sep 2006, Joel E. Denny wrote:
> I'm beginning to think the declaration is a bit ugly though. How about
> something like this instead:
>
> %destructor { free ($$); } %symbol-default
> %printer { fprintf (yyoutput, "%s", $$); } %symbol-default
>
> I think that's clearer than just an empty list.
I committed the following to implement %symbol-default. It shouldn't be
tough to revert if people find it objectionable.
Joel
Index: ChangeLog
===================================================================
RCS file: /sources/bison/bison/ChangeLog,v
retrieving revision 1.1555
diff -p -u -r1.1555 ChangeLog
--- ChangeLog 24 Aug 2006 01:26:07 -0000 1.1555
+++ ChangeLog 4 Sep 2006 19:25:47 -0000
@@ -1,3 +1,30 @@
+2006-09-04 Joel E. Denny <address@hidden>
+
+ Require default %destructor/%printer to be declared using
+ %symbol-default instead of an empty symbol list, and start working on
+ new per-type %destructor/%printer. Discussed at
+ <http://lists.gnu.org/archive/html/bison-patches/2006-09/msg00007.html>.
+ * NEWS (2.3+): Add %symbol-default to example.
+ * bison.texinfo (Freeing Discarded Symbols): Likewise.
+ (Bison Symbols): Add entry for %symbol-default.
+ * src/parse-gram.y (PERCENT_SYMBOL_DEFAULT): New token.
+ (generic_symlist, generic_symlist_item): New nonterminals for creating
+ a list in which each item is a symbol, semantic type, or
+ %symbol-default.
+ (grammar_declaration): Use generic_symlist in %destructor and %printer
+ declarations instead of symbols.1 or an empty list.
+ (symbol_declaration, precedence_declaration, symbols.1): Update actions
+ for changes to symbol_list.
+ * src/reader.c: Update for changes to symbol_list.
+ * src/scan-code.l: Likewise.
+ * src/scan-gram.l: Scan new PERCENT_SYMBOL_DEFAULT token.
+ * src/symlist.c, src/symlist.h: Extend such that a list node may
+ represent a semantic type or a %symbol-default in addition to just an
+ ordinary symbol. Add switched functions for setting %destructor's and
+ %printer's.
+ * tests/actions.at, tests/input.at: Add %symbol-default to all default
+ %destructor/%printer declarations.
+
2006-08-23 Joel E. Denny <address@hidden>
Whether the default %destructor/%printer applies to a particular symbol
Index: NEWS
===================================================================
RCS file: /sources/bison/bison/NEWS,v
retrieving revision 1.157
diff -p -u -r1.157 NEWS
--- NEWS 24 Aug 2006 01:26:07 -0000 1.157
+++ NEWS 4 Sep 2006 19:25:47 -0000
@@ -21,7 +21,7 @@ Changes in version 2.3+:
%token <string> STRING2
%type <string> string1
%type <string> string2
- %destructor { free ($$); }
+ %destructor { free ($$); } %symbol-default
%destructor { free ($$); printf ("%d", @$.first_line); } STRING1 string1
guarantees that, when the parser discards any user-defined symbol, it passes
Index: doc/bison.texinfo
===================================================================
RCS file: /sources/bison/bison/doc/bison.texinfo,v
retrieving revision 1.201
diff -p -u -r1.201 bison.texinfo
--- doc/bison.texinfo 24 Aug 2006 01:26:07 -0000 1.201
+++ doc/bison.texinfo 4 Sep 2006 19:25:47 -0000
@@ -3986,6 +3986,7 @@ For instance, if your locations use a fi
@subsection Freeing Discarded Symbols
@cindex freeing discarded symbols
@findex %destructor
address@hidden %symbol-default
During error recovery (@pxref{Error Recovery}), symbols already pushed
on the stack and tokens coming from the rest of the file are discarded
@@ -4012,8 +4013,9 @@ The additional parser parameters are als
The Parser Function @code{yyparse}}).
@end deffn
address@hidden {Directive} %destructor @{ @var{code} @}
address@hidden {Directive} %destructor @{ @var{code} @} %symbol-default
@cindex default %destructor
address@hidden %symbol-default
Invoke the braced @var{code} whenever the parser discards any user-defined
grammar symbol for which the user has not specifically declared any
@code{%destructor}.
@@ -4030,7 +4032,7 @@ For instance:
%token <string> STRING2
%type <string> string1
%type <string> string2
-%destructor @{ free ($$); @}
+%destructor @{ free ($$); @} %symbol-default
%destructor @{ free ($$); printf ("%d", @@$.first_line); @} STRING1 string1
@end smallexample
@@ -8505,6 +8507,11 @@ Bison declaration to specify the start s
Start-Symbol}.
@end deffn
address@hidden {Directive} %symbol-default
+Used to declare a default @code{%destructor} or default @code{%printer}.
address@hidden Decl, , Freeing Discarded Symbols}.
address@hidden deffn
+
@deffn {Directive} %token
Bison declaration to declare token(s) without specifying precedence.
@xref{Token Decl, ,Token Type Names}.
Index: src/parse-gram.y
===================================================================
RCS file: /sources/bison/bison/src/parse-gram.y,v
retrieving revision 1.89
diff -p -u -r1.89 parse-gram.y
--- src/parse-gram.y 13 Aug 2006 03:18:15 -0000 1.89
+++ src/parse-gram.y 4 Sep 2006 19:25:47 -0000
@@ -116,6 +116,8 @@ 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"
@@ -199,7 +201,7 @@ static int current_prec = 0;
%printer { fprintf (stderr, "%s:", $$->tag); } id_colon
%type <assoc> precedence_declarator
-%type <list> symbols.1
+%type <list> symbols.1 generic_symlist generic_symlist_item
%%
input:
@@ -262,30 +264,22 @@ grammar_declaration:
{
grammar_start_symbol_set ($2, @2);
}
-| "%destructor" "{...}"
- {
- default_destructor_set (translate_symbol_action ($2, @2), @2);
- }
-| "%destructor" "{...}" symbols.1
+| "%destructor" "{...}" generic_symlist
{
symbol_list *list;
const char *action = translate_symbol_action ($2, @2);
for (list = $3; list; list = list->next)
- symbol_destructor_set (list->sym, action, @2);
+ symbol_list_destructor_set (list, action, @2);
symbol_list_free ($3);
}
-| "%printer" "{...}" symbols.1
+| "%printer" "{...}" generic_symlist
{
symbol_list *list;
const char *action = translate_symbol_action ($2, @2);
for (list = $3; list; list = list->next)
- symbol_printer_set (list->sym, action, @2);
+ symbol_list_printer_set (list, action, @2);
symbol_list_free ($3);
}
-| "%printer" "{...}"
- {
- default_printer_set (translate_symbol_action ($2, @2), @2);
- }
| "%default-prec"
{
default_prec = true;
@@ -352,7 +346,7 @@ symbol_declaration:
tag_seen = true;
symbol_list *list;
for (list = $3; list; list = list->next)
- symbol_type_set (list->sym, $2, @2);
+ symbol_type_set (list->content.sym, $2, @2);
symbol_list_free ($3);
}
;
@@ -364,8 +358,8 @@ precedence_declaration:
++current_prec;
for (list = $3; list; list = list->next)
{
- symbol_type_set (list->sym, current_type, @2);
- symbol_precedence_set (list->sym, current_prec, $1, @1);
+ symbol_type_set (list->content.sym, current_type, @2);
+ symbol_precedence_set (list->content.sym, current_prec, $1, @1);
}
symbol_list_free ($3);
current_type = NULL;
@@ -383,10 +377,23 @@ type.opt:
| TYPE { current_type = $1; tag_seen = true; }
;
-/* One or more nonterminals to be %typed. */
+/* One or more symbols to be %typed. */
symbols.1:
- symbol { $$ = symbol_list_new ($1, @1); }
-| symbols.1 symbol { $$ = symbol_list_prepend ($1, $2, @2); }
+ symbol
+ { $$ = symbol_list_sym_new ($1, @1); }
+| symbols.1 symbol
+ { $$ = symbol_list_prepend ($1, symbol_list_sym_new ($2, @2)); }
+;
+
+generic_symlist:
+ generic_symlist_item { $$ = $1; }
+| generic_symlist generic_symlist_item { $$ = symbol_list_prepend ($1, $2); }
+;
+
+generic_symlist_item:
+ symbol { $$ = symbol_list_sym_new ($1, @1); }
+| TYPE { $$ = symbol_list_type_new ($1, @1); }
+| "%symbol-default" { $$ = symbol_list_default_new (@1); }
;
/* One token definition. */
Index: src/reader.c
===================================================================
RCS file: /sources/bison/bison/src/reader.c,v
retrieving revision 1.270
diff -p -u -r1.270 reader.c
--- src/reader.c 20 Aug 2006 03:10:18 -0000 1.270
+++ src/reader.c 4 Sep 2006 19:25:47 -0000
@@ -196,7 +196,7 @@ static symbol_list *grammar_end = NULL;
static void
grammar_symbol_append (symbol *sym, location loc)
{
- symbol_list *p = symbol_list_new (sym, loc);
+ symbol_list *p = symbol_list_sym_new (sym, loc);
if (grammar_end)
grammar_end->next = p;
@@ -252,7 +252,7 @@ grammar_current_rule_begin (symbol *lhs,
static bool
symbol_should_be_used (symbol_list const *s)
{
- return (symbol_destructor_get (s->sym)
+ return (symbol_destructor_get (s->content.sym)
|| (s->midrule && s->midrule->used));
}
@@ -271,13 +271,13 @@ grammar_rule_check (const symbol_list *r
Don't worry about the default action if $$ is untyped, since $$'s
value can't be used. */
- if (!r->action && r->sym->type_name)
+ if (!r->action && r->content.sym->type_name)
{
- symbol *first_rhs = r->next->sym;
+ symbol *first_rhs = r->next->content.sym;
/* If $$ is being set in default way, report if any type mismatch. */
if (first_rhs)
{
- char const *lhs_type = r->sym->type_name;
+ char const *lhs_type = r->content.sym->type_name;
const char *rhs_type =
first_rhs->type_name ? first_rhs->type_name : "";
if (!UNIQSTR_EQ (lhs_type, rhs_type))
@@ -295,7 +295,7 @@ grammar_rule_check (const symbol_list *r
{
symbol_list const *l = r;
int n = 0;
- for (; l && l->sym; l = l->next, ++n)
+ for (; l && l->content.sym; l = l->next, ++n)
if (! (l->used
|| !symbol_should_be_used (l)
/* The default action, $$ = $1, `uses' both. */
@@ -341,7 +341,7 @@ grammar_midrule_action (void)
action. Create the MIDRULE. */
location dummy_location = current_rule->action_location;
symbol *dummy = dummy_symbol_get (dummy_location);
- symbol_list *midrule = symbol_list_new (dummy, dummy_location);
+ symbol_list *midrule = symbol_list_sym_new (dummy, dummy_location);
/* Make a new rule, whose body is empty, before the current one, so
that the action just read can belong to it. */
@@ -362,7 +362,7 @@ grammar_midrule_action (void)
grammar = midrule;
/* End the dummy's rule. */
- midrule->next = symbol_list_new (NULL, dummy_location);
+ midrule->next = symbol_list_sym_new (NULL, dummy_location);
midrule->next->next = current_rule;
previous_rule_end = midrule->next;
@@ -461,11 +461,11 @@ packgram (void)
{
int rule_length = 0;
symbol *ruleprec = p->ruleprec;
- record_merge_function_type (p->merger, p->sym->type_name,
+ record_merge_function_type (p->merger, p->content.sym->type_name,
p->merger_declaration_location);
rules[ruleno].user_number = ruleno;
rules[ruleno].number = ruleno;
- rules[ruleno].lhs = p->sym;
+ rules[ruleno].lhs = p->content.sym;
rules[ruleno].rhs = ritem + itemno;
rules[ruleno].prec = NULL;
rules[ruleno].dprec = p->dprec;
@@ -487,7 +487,7 @@ packgram (void)
if (p != grammar)
grammar_rule_check (p);
- for (p = p->next; p && p->sym; p = p->next)
+ for (p = p->next; p && p->content.sym; p = p->next)
{
++rule_length;
@@ -498,11 +498,12 @@ packgram (void)
/* item_number = symbol_number.
But the former needs to contain more: negative rule numbers. */
- ritem[itemno++] = symbol_number_as_item_number (p->sym->number);
+ ritem[itemno++] =
+ symbol_number_as_item_number (p->content.sym->number);
/* A rule gets by default the precedence and associativity
of its last token. */
- if (p->sym->class == token_sym && default_prec)
- rules[ruleno].prec = p->sym;
+ if (p->content.sym->class == token_sym && default_prec)
+ rules[ruleno].prec = p->content.sym;
}
/* If this rule has a %prec,
@@ -605,16 +606,17 @@ check_and_convert_grammar (void)
{
symbol_list *node;
for (node = grammar;
- node != NULL && symbol_is_dummy (node->sym);
+ node != NULL && symbol_is_dummy (node->content.sym);
node = node->next)
{
for (node = node->next;
- node != NULL && node->sym != NULL;
+ node != NULL && node->content.sym != NULL;
node = node->next)
;
}
assert (node != NULL);
- grammar_start_symbol_set (node->sym, node->sym->location);
+ grammar_start_symbol_set (node->content.sym,
+ node->content.sym->location);
}
/* Insert the initial rule, whose line is that of the first rule
@@ -622,11 +624,11 @@ check_and_convert_grammar (void)
accept: %start EOF. */
{
- symbol_list *p = symbol_list_new (accept, empty_location);
+ symbol_list *p = symbol_list_sym_new (accept, empty_location);
p->location = grammar->location;
- p->next = symbol_list_new (startsymbol, empty_location);
- p->next->next = symbol_list_new (endtoken, empty_location);
- p->next->next->next = symbol_list_new (NULL, empty_location);
+ p->next = symbol_list_sym_new (startsymbol, empty_location);
+ p->next->next = symbol_list_sym_new (endtoken, empty_location);
+ p->next->next->next = symbol_list_sym_new (NULL, empty_location);
p->next->next->next->next = grammar;
nrules += 1;
nritems += 3;
Index: src/scan-code.l
===================================================================
RCS file: /sources/bison/bison/src/scan-code.l,v
retrieving revision 1.11
diff -p -u -r1.11 scan-code.l
--- src/scan-code.l 10 Aug 2006 04:53:04 -0000 1.11
+++ src/scan-code.l 4 Sep 2006 19:25:47 -0000
@@ -282,10 +282,10 @@ handle_action_dollar (symbol_list *rule,
_("$$ for the midrule at $%d of `%s'"
" has no declared type"),
rule->midrule_parent_rhs_index,
- effective_rule->sym->tag);
+ effective_rule->content.sym->tag);
else
complain_at (dollar_loc, _("$$ of `%s' has no declared type"),
- rule->sym->tag);
+ rule->content.sym->tag);
}
else
untyped_var_seen = true;
@@ -313,7 +313,7 @@ handle_action_dollar (symbol_list *rule,
{
if (union_seen | tag_seen)
complain_at (dollar_loc, _("$%d of `%s' has no declared type"),
- n, effective_rule->sym->tag);
+ n, effective_rule->content.sym->tag);
else
untyped_var_seen = true;
type_name = "";
Index: src/scan-gram.l
===================================================================
RCS file: /sources/bison/bison/src/scan-gram.l,v
retrieving revision 1.101
diff -p -u -r1.101 scan-gram.l
--- src/scan-gram.l 14 Aug 2006 22:40:33 -0000 1.101
+++ src/scan-gram.l 4 Sep 2006 19:25:47 -0000
@@ -193,6 +193,7 @@ splice (\\[ \f\t\v]*\n)*
"%skeleton" return PERCENT_SKELETON;
"%start" return PERCENT_START;
"%start-header" return PERCENT_START_HEADER;
+ "%symbol-default" return PERCENT_SYMBOL_DEFAULT;
"%term" return PERCENT_TOKEN;
"%token" return PERCENT_TOKEN;
"%token"[-_]"table" return PERCENT_TOKEN_TABLE;
Index: src/symlist.c
===================================================================
RCS file: /sources/bison/bison/src/symlist.c,v
retrieving revision 1.19
diff -p -u -r1.19 symlist.c
--- src/symlist.c 9 Jul 2006 19:55:15 -0000 1.19
+++ src/symlist.c 4 Sep 2006 19:25:47 -0000
@@ -31,11 +31,12 @@
`--------------------------------------*/
symbol_list *
-symbol_list_new (symbol *sym, location loc)
+symbol_list_sym_new (symbol *sym, location loc)
{
symbol_list *res = xmalloc (sizeof *res);
- res->sym = sym;
+ res->content_type = SYMLIST_SYMBOL;
+ res->content.sym = sym;
res->location = loc;
res->midrule = NULL;
@@ -55,39 +56,73 @@ symbol_list_new (symbol *sym, location l
}
-/*------------------.
-| Print this list. |
-`------------------*/
+/*--------------------------------------------.
+| Create a list containing TYPE_NAME at LOC. |
+`--------------------------------------------*/
+
+symbol_list *
+symbol_list_type_new (uniqstr type_name, location loc)
+{
+ symbol_list *res = xmalloc (sizeof *res);
+
+ res->content_type = SYMLIST_TYPE;
+ res->content.type_name = type_name;
+ res->location = loc;
+ res->next = NULL;
+
+ return res;
+}
+
+
+/*----------------------------------------------------.
+| Create a list containing a %symbol-default at LOC. |
+`----------------------------------------------------*/
+
+symbol_list *
+symbol_list_default_new (location loc)
+{
+ symbol_list *res = xmalloc (sizeof *res);
+
+ res->content_type = SYMLIST_DEFAULT;
+ res->location = loc;
+ res->next = NULL;
+
+ return res;
+}
+
+
+/*-----------------------------------------------------------------------.
+| Print this list, for which every content_type must be SYMLIST_SYMBOL. |
+`-----------------------------------------------------------------------*/
void
-symbol_list_print (const symbol_list *l, FILE *f)
+symbol_list_syms_print (const symbol_list *l, FILE *f)
{
- for (/* Nothing. */; l && l->sym; l = l->next)
+ for (/* Nothing. */; l && l->content.sym; l = l->next)
{
- symbol_print (l->sym, f);
+ symbol_print (l->content.sym, f);
fprintf (stderr, l->used ? " used" : " unused");
- if (l && l->sym)
+ if (l && l->content.sym)
fprintf (f, ", ");
}
}
-/*---------------------------------.
-| Prepend SYM at LOC to the LIST. |
-`---------------------------------*/
+/*---------------------------.
+| Prepend NODE to the LIST. |
+`---------------------------*/
symbol_list *
-symbol_list_prepend (symbol_list *list, symbol *sym, location loc)
+symbol_list_prepend (symbol_list *list, symbol_list *node)
{
- symbol_list *res = symbol_list_new (sym, loc);
- res->next = list;
- return res;
+ node->next = list;
+ return node;
}
-/*-------------------------------------------------.
-| Free the LIST, but not the symbols it contains. |
-`-------------------------------------------------*/
+/*-----------------------------------------------.
+| Free the LIST, but not the items it contains. |
+`-----------------------------------------------*/
void
symbol_list_free (symbol_list *list)
@@ -104,15 +139,17 @@ int
symbol_list_length (symbol_list const *l)
{
int res = 0;
- for (/* Nothing. */; l && l->sym; l = l->next)
+ for (/* Nothing. */;
+ l && !(l->content_type == SYMLIST_SYMBOL && l->content.sym == NULL);
+ l = l->next)
++res;
return res;
}
-/*--------------------------------.
-| Get symbol N in symbol list L. |
-`--------------------------------*/
+/*------------------------------.
+| Get item N in symbol list L. |
+`------------------------------*/
symbol_list *
symbol_list_n_get (symbol_list *l, int n)
@@ -125,7 +162,8 @@ symbol_list_n_get (symbol_list *l, int n
for (i = 0; i < n; ++i)
{
l = l->next;
- if (l == NULL || l->sym == NULL)
+ if (l == NULL
+ || (l->content_type == SYMLIST_SYMBOL && l->content.sym == NULL))
return NULL;
}
@@ -147,13 +185,14 @@ symbol_list_n_type_name_get (symbol_list
complain_at (loc, _("invalid $ value: $%d"), n);
return NULL;
}
- return l->sym->type_name;
+ assert (l->content_type == SYMLIST_SYMBOL);
+ return l->content.sym->type_name;
}
-/*----------------------------------------.
-| The symbol N in symbol list L is USED. |
-`----------------------------------------*/
+/*--------------------------------------.
+| The item N in symbol list L is USED. |
+`--------------------------------------*/
void
symbol_list_n_used_set (symbol_list *l, int n, bool used)
@@ -162,3 +201,38 @@ symbol_list_n_used_set (symbol_list *l,
if (l)
l->used = used;
}
+
+void
+symbol_list_destructor_set (symbol_list *node, const char *destructor,
+ location loc)
+{
+ switch (node->content_type)
+ {
+ case SYMLIST_SYMBOL:
+ symbol_destructor_set (node->content.sym, destructor, loc);
+ break;
+ case SYMLIST_TYPE:
+ /* FIXME: */
+ break;
+ case SYMLIST_DEFAULT:
+ default_destructor_set (destructor, loc);
+ break;
+ }
+}
+
+void
+symbol_list_printer_set (symbol_list *node, const char *printer, location loc)
+{
+ switch (node->content_type)
+ {
+ case SYMLIST_SYMBOL:
+ symbol_printer_set (node->content.sym, printer, loc);
+ break;
+ case SYMLIST_TYPE:
+ /* FIXME: */
+ break;
+ case SYMLIST_DEFAULT:
+ default_printer_set (printer, loc);
+ break;
+ }
+}
Index: src/symlist.h
===================================================================
RCS file: /sources/bison/bison/src/symlist.h,v
retrieving revision 1.17
diff -p -u -r1.17 symlist.h
--- src/symlist.h 9 Jul 2006 19:55:15 -0000 1.17
+++ src/symlist.h 4 Sep 2006 19:25:47 -0000
@@ -28,8 +28,17 @@
/* A list of symbols, used during the parsing to store the rules. */
typedef struct symbol_list
{
- /* The symbol. */
- symbol *sym;
+ /**
+ * Whether this node contains a symbol, a semantic type, or a
+ * \c \%symbol-default.
+ */
+ enum { SYMLIST_SYMBOL, SYMLIST_TYPE, SYMLIST_DEFAULT } content_type;
+ union {
+ /** The symbol or \c NULL iff <tt>node_type = SYMLIST_SYMBOL</tt>. */
+ symbol *sym;
+ /** The semantic type iff <tt>node_type = SYMLIST_TYPE</tt>. */
+ uniqstr type_name;
+ } content;
location location;
/* If this symbol is the generated lhs for a midrule but this is the rule in
@@ -61,31 +70,46 @@ typedef struct symbol_list
} symbol_list;
-/* Create a list containing SYM at LOC. */
-symbol_list *symbol_list_new (symbol *sym, location loc);
+/** Create a list containing \c sym at \c loc. */
+symbol_list *symbol_list_sym_new (symbol *sym, location loc);
-/* Print it. */
-void symbol_list_print (const symbol_list *l, FILE *f);
+/** Create a list containing \c type_name at \c loc. */
+symbol_list *symbol_list_type_new (uniqstr type_name, location loc);
-/* Prepend SYM at LOC to the LIST. */
-symbol_list *symbol_list_prepend (symbol_list *l,
- symbol *sym,
- location loc);
+/** Create a list containing a \c \%symbol-default at \c loc. */
+symbol_list *symbol_list_default_new (location loc);
-/* Free the LIST, but not the symbols it contains. */
-void symbol_list_free (symbol_list *l);
+/** Print this list.
-/* Return its length. */
+ \pre For every node \c n in the list, <tt>n->content_type =
+ SYMLIST_SYMBOL</tt>. */
+void symbol_list_syms_print (const symbol_list *l, FILE *f);
+
+/** Prepend \c node to \c list. */
+symbol_list *symbol_list_prepend (symbol_list *list, symbol_list *node);
+
+/** Free \c list, but not the items it contains. */
+void symbol_list_free (symbol_list *list);
+
+/** Return the length of \c l. */
int symbol_list_length (symbol_list const *l);
-/* Get symbol N in symbol list L. */
+/** Get item \c n in symbol list \c l. */
symbol_list *symbol_list_n_get (symbol_list *l, int n);
/* Get the data type (alternative in the union) of the value for
symbol N in rule RULE. */
uniqstr symbol_list_n_type_name_get (symbol_list *l, location loc, int n);
-/* The symbol N in symbol list L is USED. */
+/** The item \c n in symbol list \c l is \c used. */
void symbol_list_n_used_set (symbol_list *l, int n, bool used);
+/** Set the \c \%destructor for \c node as \c destructor at \c loc. */
+void symbol_list_destructor_set (symbol_list *node, const char *destructor,
+ location loc);
+
+/** Set the \c \%printer for \c node as \c printer at \c loc. */
+void symbol_list_printer_set (symbol_list *node, const char *printer,
+ location loc);
+
#endif /* !SYMLIST_H_ */
Index: tests/actions.at
===================================================================
RCS file: /sources/bison/bison/tests/actions.at,v
retrieving revision 1.64
diff -p -u -r1.64 actions.at
--- tests/actions.at 24 Aug 2006 01:26:07 -0000 1.64
+++ tests/actions.at 4 Sep 2006 19:25:47 -0000
@@ -606,10 +606,10 @@ AT_DATA_GRAMMAR([[input.y]],
%printer {
fprintf (yyoutput, "Default printer for '%c' @ %d", $$, @$.first_column);
-}
+} %symbol-default
%destructor {
fprintf (stdout, "Default destructor for '%c' @ %d.\n", $$, @$.first_column);
-}
+} %symbol-default
%printer {
fprintf (yyoutput, "'b'/'c' printer for '%c' @ %d", $$, @$.first_column);
@@ -715,10 +715,10 @@ AT_DATA_GRAMMAR([[input.y]],
%token END 0
%printer {
fprintf (yyoutput, "Default printer for '%c' @ %d", $$, @$.first_column);
-}
+} %symbol-default
%destructor {
fprintf (stdout, "Default destructor for '%c' @ %d.\n", $$, @$.first_column);
-}
+} %symbol-default
%%
@@ -800,10 +800,10 @@ AT_DATA_GRAMMAR([[input.y]],
%printer {
fprintf (yyoutput, "'%c'", $$);
-}
+} %symbol-default
%destructor {
fprintf (stderr, "DESTROY '%c'\n", $$);
-}
+} %symbol-default
%%
@@ -911,11 +911,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
Index: tests/input.at
===================================================================
RCS file: /sources/bison/bison/tests/input.at,v
retrieving revision 1.54
diff -p -u -r1.54 input.at
--- tests/input.at 20 Aug 2006 03:10:18 -0000 1.54
+++ tests/input.at 4 Sep 2006 19:25:47 -0000
@@ -175,18 +175,18 @@ AT_CLEANUP
AT_SETUP([Default %printer and %destructor redeclared])
AT_DATA([[input.y]],
-[[%destructor { destroy ($$); }
-%printer { destroy ($$); }
+[[%destructor { destroy ($$); } %symbol-default
+%printer { destroy ($$); } %symbol-default
-%destructor { destroy ($$); }
-%printer { destroy ($$); }
+%destructor { destroy ($$); } %symbol-default
+%printer { destroy ($$); } %symbol-default
%%
start: ;
-%destructor { destroy ($$); };
-%printer { destroy ($$); };
+%destructor { destroy ($$); } %symbol-default;
+%printer { destroy ($$); } %symbol-default;
]])
AT_CHECK([bison input.y], [1], [],
@@ -210,7 +210,7 @@ AT_CLEANUP
AT_SETUP([Unused values with default %destructor])
AT_DATA([[input.y]],
-[[%destructor { destroy ($$); }
+[[%destructor { destroy ($$); } %symbol-default
%%
@@ -533,7 +533,7 @@ input.y:4.10-5.0: missing `'' at end of
input.y:14.11-15.0: missing `'' at end of line
input.y:16.11-17.0: missing `"' at end of line
input.y:19.13-20.0: missing `}' at end of file
-input.y:20.1: syntax error, unexpected end of file, expecting ;
+input.y:20.1: syntax error, unexpected end of file
]])
AT_CLEANUP