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.
This commit is contained in:
Joel E. Denny
2006-09-04 19:29:29 +00:00
parent 3508ce361b
commit 3be03b13e5
13 changed files with 821 additions and 651 deletions

View File

@@ -1,3 +1,30 @@
2006-09-04 Joel E. Denny <jdenny@ces.clemson.edu>
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 <jdenny@ces.clemson.edu> 2006-08-23 Joel E. Denny <jdenny@ces.clemson.edu>
Whether the default %destructor/%printer applies to a particular symbol Whether the default %destructor/%printer applies to a particular symbol

2
NEWS
View File

@@ -21,7 +21,7 @@ Changes in version 2.3+:
%token <string> STRING2 %token <string> STRING2
%type <string> string1 %type <string> string1
%type <string> string2 %type <string> string2
%destructor { free ($$); } %destructor { free ($$); } %symbol-default
%destructor { free ($$); printf ("%d", @$.first_line); } STRING1 string1 %destructor { free ($$); printf ("%d", @$.first_line); } STRING1 string1
guarantees that, when the parser discards any user-defined symbol, it passes guarantees that, when the parser discards any user-defined symbol, it passes

View File

@@ -3986,6 +3986,7 @@ For instance, if your locations use a file name, you may use
@subsection Freeing Discarded Symbols @subsection Freeing Discarded Symbols
@cindex freeing discarded symbols @cindex freeing discarded symbols
@findex %destructor @findex %destructor
@findex %symbol-default
During error recovery (@pxref{Error Recovery}), symbols already pushed During error recovery (@pxref{Error Recovery}), symbols already pushed
on the stack and tokens coming from the rest of the file are discarded on the stack and tokens coming from the rest of the file are discarded
@@ -4012,8 +4013,9 @@ The additional parser parameters are also available (@pxref{Parser Function, ,
The Parser Function @code{yyparse}}). The Parser Function @code{yyparse}}).
@end deffn @end deffn
@deffn {Directive} %destructor @{ @var{code} @} @deffn {Directive} %destructor @{ @var{code} @} %symbol-default
@cindex default %destructor @cindex default %destructor
@findex %symbol-default
Invoke the braced @var{code} whenever the parser discards any user-defined Invoke the braced @var{code} whenever the parser discards any user-defined
grammar symbol for which the user has not specifically declared any grammar symbol for which the user has not specifically declared any
@code{%destructor}. @code{%destructor}.
@@ -4030,7 +4032,7 @@ For instance:
%token <string> STRING2 %token <string> STRING2
%type <string> string1 %type <string> string1
%type <string> string2 %type <string> string2
%destructor @{ free ($$); @} %destructor @{ free ($$); @} %symbol-default
%destructor @{ free ($$); printf ("%d", @@$.first_line); @} STRING1 string1 %destructor @{ free ($$); printf ("%d", @@$.first_line); @} STRING1 string1
@end smallexample @end smallexample
@@ -8505,6 +8507,11 @@ Bison declaration to specify the start symbol. @xref{Start Decl, ,The
Start-Symbol}. Start-Symbol}.
@end deffn @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 @deffn {Directive} %token
Bison declaration to declare token(s) without specifying precedence. Bison declaration to declare token(s) without specifying precedence.
@xref{Token Decl, ,Token Type Names}. @xref{Token Decl, ,Token Type Names}.

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -116,6 +116,8 @@ static int current_prec = 0;
%token PERCENT_TYPE "%type" %token PERCENT_TYPE "%type"
%token PERCENT_DESTRUCTOR "%destructor" %token PERCENT_DESTRUCTOR "%destructor"
%token PERCENT_PRINTER "%printer" %token PERCENT_PRINTER "%printer"
%token PERCENT_SYMBOL_DEFAULT
"%symbol-default"
%token PERCENT_LEFT "%left" %token PERCENT_LEFT "%left"
%token PERCENT_RIGHT "%right" %token PERCENT_RIGHT "%right"
@@ -199,7 +201,7 @@ static int current_prec = 0;
%printer { fprintf (stderr, "%s:", $$->tag); } id_colon %printer { fprintf (stderr, "%s:", $$->tag); } id_colon
%type <assoc> precedence_declarator %type <assoc> precedence_declarator
%type <list> symbols.1 %type <list> symbols.1 generic_symlist generic_symlist_item
%% %%
input: input:
@@ -262,30 +264,22 @@ grammar_declaration:
{ {
grammar_start_symbol_set ($2, @2); grammar_start_symbol_set ($2, @2);
} }
| "%destructor" "{...}" | "%destructor" "{...}" generic_symlist
{
default_destructor_set (translate_symbol_action ($2, @2), @2);
}
| "%destructor" "{...}" symbols.1
{ {
symbol_list *list; symbol_list *list;
const char *action = translate_symbol_action ($2, @2); const char *action = translate_symbol_action ($2, @2);
for (list = $3; list; list = list->next) 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); symbol_list_free ($3);
} }
| "%printer" "{...}" symbols.1 | "%printer" "{...}" generic_symlist
{ {
symbol_list *list; symbol_list *list;
const char *action = translate_symbol_action ($2, @2); const char *action = translate_symbol_action ($2, @2);
for (list = $3; list; list = list->next) 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); symbol_list_free ($3);
} }
| "%printer" "{...}"
{
default_printer_set (translate_symbol_action ($2, @2), @2);
}
| "%default-prec" | "%default-prec"
{ {
default_prec = true; default_prec = true;
@@ -352,7 +346,7 @@ symbol_declaration:
tag_seen = true; tag_seen = true;
symbol_list *list; symbol_list *list;
for (list = $3; list; list = list->next) 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); symbol_list_free ($3);
} }
; ;
@@ -364,8 +358,8 @@ precedence_declaration:
++current_prec; ++current_prec;
for (list = $3; list; list = list->next) for (list = $3; list; list = list->next)
{ {
symbol_type_set (list->sym, current_type, @2); symbol_type_set (list->content.sym, current_type, @2);
symbol_precedence_set (list->sym, current_prec, $1, @1); symbol_precedence_set (list->content.sym, current_prec, $1, @1);
} }
symbol_list_free ($3); symbol_list_free ($3);
current_type = NULL; current_type = NULL;
@@ -383,10 +377,23 @@ type.opt:
| TYPE { current_type = $1; tag_seen = true; } | TYPE { current_type = $1; tag_seen = true; }
; ;
/* One or more nonterminals to be %typed. */ /* One or more symbols to be %typed. */
symbols.1: symbols.1:
symbol { $$ = symbol_list_new ($1, @1); } symbol
| symbols.1 symbol { $$ = symbol_list_prepend ($1, $2, @2); } { $$ = 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. */ /* One token definition. */

View File

@@ -196,7 +196,7 @@ static symbol_list *grammar_end = NULL;
static void static void
grammar_symbol_append (symbol *sym, location loc) 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) if (grammar_end)
grammar_end->next = p; grammar_end->next = p;
@@ -252,7 +252,7 @@ grammar_current_rule_begin (symbol *lhs, location loc)
static bool static bool
symbol_should_be_used (symbol_list const *s) 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)); || (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 Don't worry about the default action if $$ is untyped, since $$'s
value can't be used. */ 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 $$ is being set in default way, report if any type mismatch. */
if (first_rhs) if (first_rhs)
{ {
char const *lhs_type = r->sym->type_name; char const *lhs_type = r->content.sym->type_name;
const char *rhs_type = const char *rhs_type =
first_rhs->type_name ? first_rhs->type_name : ""; first_rhs->type_name ? first_rhs->type_name : "";
if (!UNIQSTR_EQ (lhs_type, rhs_type)) if (!UNIQSTR_EQ (lhs_type, rhs_type))
@@ -295,7 +295,7 @@ grammar_rule_check (const symbol_list *r)
{ {
symbol_list const *l = r; symbol_list const *l = r;
int n = 0; int n = 0;
for (; l && l->sym; l = l->next, ++n) for (; l && l->content.sym; l = l->next, ++n)
if (! (l->used if (! (l->used
|| !symbol_should_be_used (l) || !symbol_should_be_used (l)
/* The default action, $$ = $1, `uses' both. */ /* The default action, $$ = $1, `uses' both. */
@@ -341,7 +341,7 @@ grammar_midrule_action (void)
action. Create the MIDRULE. */ action. Create the MIDRULE. */
location dummy_location = current_rule->action_location; location dummy_location = current_rule->action_location;
symbol *dummy = dummy_symbol_get (dummy_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 /* Make a new rule, whose body is empty, before the current one, so
that the action just read can belong to it. */ that the action just read can belong to it. */
@@ -362,7 +362,7 @@ grammar_midrule_action (void)
grammar = midrule; grammar = midrule;
/* End the dummy's rule. */ /* 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; midrule->next->next = current_rule;
previous_rule_end = midrule->next; previous_rule_end = midrule->next;
@@ -461,11 +461,11 @@ packgram (void)
{ {
int rule_length = 0; int rule_length = 0;
symbol *ruleprec = p->ruleprec; 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); p->merger_declaration_location);
rules[ruleno].user_number = ruleno; rules[ruleno].user_number = ruleno;
rules[ruleno].number = ruleno; rules[ruleno].number = ruleno;
rules[ruleno].lhs = p->sym; rules[ruleno].lhs = p->content.sym;
rules[ruleno].rhs = ritem + itemno; rules[ruleno].rhs = ritem + itemno;
rules[ruleno].prec = NULL; rules[ruleno].prec = NULL;
rules[ruleno].dprec = p->dprec; rules[ruleno].dprec = p->dprec;
@@ -487,7 +487,7 @@ packgram (void)
if (p != grammar) if (p != grammar)
grammar_rule_check (p); 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; ++rule_length;
@@ -498,11 +498,12 @@ packgram (void)
/* item_number = symbol_number. /* item_number = symbol_number.
But the former needs to contain more: negative rule numbers. */ 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 /* A rule gets by default the precedence and associativity
of its last token. */ of its last token. */
if (p->sym->class == token_sym && default_prec) if (p->content.sym->class == token_sym && default_prec)
rules[ruleno].prec = p->sym; rules[ruleno].prec = p->content.sym;
} }
/* If this rule has a %prec, /* If this rule has a %prec,
@@ -605,16 +606,17 @@ check_and_convert_grammar (void)
{ {
symbol_list *node; symbol_list *node;
for (node = grammar; for (node = grammar;
node != NULL && symbol_is_dummy (node->sym); node != NULL && symbol_is_dummy (node->content.sym);
node = node->next) node = node->next)
{ {
for (node = node->next; for (node = node->next;
node != NULL && node->sym != NULL; node != NULL && node->content.sym != NULL;
node = node->next) node = node->next)
; ;
} }
assert (node != NULL); 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 /* Insert the initial rule, whose line is that of the first rule
@@ -622,11 +624,11 @@ check_and_convert_grammar (void)
accept: %start EOF. */ 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->location = grammar->location;
p->next = symbol_list_new (startsymbol, empty_location); p->next = symbol_list_sym_new (startsymbol, empty_location);
p->next->next = symbol_list_new (endtoken, empty_location); p->next->next = symbol_list_sym_new (endtoken, empty_location);
p->next->next->next = symbol_list_new (NULL, empty_location); p->next->next->next = symbol_list_sym_new (NULL, empty_location);
p->next->next->next->next = grammar; p->next->next->next->next = grammar;
nrules += 1; nrules += 1;
nritems += 3; nritems += 3;

View File

@@ -282,10 +282,10 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
_("$$ for the midrule at $%d of `%s'" _("$$ for the midrule at $%d of `%s'"
" has no declared type"), " has no declared type"),
rule->midrule_parent_rhs_index, rule->midrule_parent_rhs_index,
effective_rule->sym->tag); effective_rule->content.sym->tag);
else else
complain_at (dollar_loc, _("$$ of `%s' has no declared type"), complain_at (dollar_loc, _("$$ of `%s' has no declared type"),
rule->sym->tag); rule->content.sym->tag);
} }
else else
untyped_var_seen = true; untyped_var_seen = true;
@@ -313,7 +313,7 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
{ {
if (union_seen | tag_seen) if (union_seen | tag_seen)
complain_at (dollar_loc, _("$%d of `%s' has no declared type"), complain_at (dollar_loc, _("$%d of `%s' has no declared type"),
n, effective_rule->sym->tag); n, effective_rule->content.sym->tag);
else else
untyped_var_seen = true; untyped_var_seen = true;
type_name = ""; type_name = "";

View File

@@ -193,6 +193,7 @@ splice (\\[ \f\t\v]*\n)*
"%skeleton" return PERCENT_SKELETON; "%skeleton" return PERCENT_SKELETON;
"%start" return PERCENT_START; "%start" return PERCENT_START;
"%start-header" return PERCENT_START_HEADER; "%start-header" return PERCENT_START_HEADER;
"%symbol-default" return PERCENT_SYMBOL_DEFAULT;
"%term" return PERCENT_TOKEN; "%term" return PERCENT_TOKEN;
"%token" return PERCENT_TOKEN; "%token" return PERCENT_TOKEN;
"%token"[-_]"table" return PERCENT_TOKEN_TABLE; "%token"[-_]"table" return PERCENT_TOKEN_TABLE;

View File

@@ -31,11 +31,12 @@
`--------------------------------------*/ `--------------------------------------*/
symbol_list * symbol_list *
symbol_list_new (symbol *sym, location loc) symbol_list_sym_new (symbol *sym, location loc)
{ {
symbol_list *res = xmalloc (sizeof *res); symbol_list *res = xmalloc (sizeof *res);
res->sym = sym; res->content_type = SYMLIST_SYMBOL;
res->content.sym = sym;
res->location = loc; res->location = loc;
res->midrule = NULL; res->midrule = NULL;
@@ -55,39 +56,73 @@ symbol_list_new (symbol *sym, location loc)
} }
/*------------------. /*--------------------------------------------.
| 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 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"); fprintf (stderr, l->used ? " used" : " unused");
if (l && l->sym) if (l && l->content.sym)
fprintf (f, ", "); fprintf (f, ", ");
} }
} }
/*---------------------------------. /*---------------------------.
| Prepend SYM at LOC to the LIST. | | Prepend NODE to the LIST. |
`---------------------------------*/ `---------------------------*/
symbol_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); node->next = list;
res->next = list; return node;
return res;
} }
/*-------------------------------------------------. /*-----------------------------------------------.
| Free the LIST, but not the symbols it contains. | | Free the LIST, but not the items it contains. |
`-------------------------------------------------*/ `-----------------------------------------------*/
void void
symbol_list_free (symbol_list *list) symbol_list_free (symbol_list *list)
@@ -104,15 +139,17 @@ int
symbol_list_length (symbol_list const *l) symbol_list_length (symbol_list const *l)
{ {
int res = 0; 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; ++res;
return res; return res;
} }
/*--------------------------------. /*------------------------------.
| Get symbol N in symbol list L. | | Get item N in symbol list L. |
`--------------------------------*/ `------------------------------*/
symbol_list * symbol_list *
symbol_list_n_get (symbol_list *l, int n) 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) for (i = 0; i < n; ++i)
{ {
l = l->next; l = l->next;
if (l == NULL || l->sym == NULL) if (l == NULL
|| (l->content_type == SYMLIST_SYMBOL && l->content.sym == NULL))
return NULL; return NULL;
} }
@@ -147,13 +185,14 @@ symbol_list_n_type_name_get (symbol_list *l, location loc, int n)
complain_at (loc, _("invalid $ value: $%d"), n); complain_at (loc, _("invalid $ value: $%d"), n);
return NULL; 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 void
symbol_list_n_used_set (symbol_list *l, int n, bool used) symbol_list_n_used_set (symbol_list *l, int n, bool used)
@@ -162,3 +201,38 @@ symbol_list_n_used_set (symbol_list *l, int n, bool used)
if (l) if (l)
l->used = used; 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;
}
}

View File

@@ -28,8 +28,17 @@
/* A list of symbols, used during the parsing to store the rules. */ /* A list of symbols, used during the parsing to store the rules. */
typedef struct symbol_list 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; location location;
/* If this symbol is the generated lhs for a midrule but this is the rule in /* 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; } symbol_list;
/* Create a list containing SYM at LOC. */ /** Create a list containing \c sym at \c loc. */
symbol_list *symbol_list_new (symbol *sym, location loc); symbol_list *symbol_list_sym_new (symbol *sym, location loc);
/* Print it. */ /** Create a list containing \c type_name at \c loc. */
void symbol_list_print (const symbol_list *l, FILE *f); symbol_list *symbol_list_type_new (uniqstr type_name, location loc);
/* Prepend SYM at LOC to the LIST. */ /** Create a list containing a \c \%symbol-default at \c loc. */
symbol_list *symbol_list_prepend (symbol_list *l, symbol_list *symbol_list_default_new (location loc);
symbol *sym,
location loc);
/* Free the LIST, but not the symbols it contains. */ /** Print this list.
void symbol_list_free (symbol_list *l);
/* 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); 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); symbol_list *symbol_list_n_get (symbol_list *l, int n);
/* Get the data type (alternative in the union) of the value for /* Get the data type (alternative in the union) of the value for
symbol N in rule RULE. */ symbol N in rule RULE. */
uniqstr symbol_list_n_type_name_get (symbol_list *l, location loc, int n); 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); 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_ */ #endif /* !SYMLIST_H_ */

View File

@@ -606,10 +606,10 @@ AT_DATA_GRAMMAR([[input.y]],
%printer { %printer {
fprintf (yyoutput, "Default printer for '%c' @ %d", $$, @$.first_column); fprintf (yyoutput, "Default printer for '%c' @ %d", $$, @$.first_column);
} } %symbol-default
%destructor { %destructor {
fprintf (stdout, "Default destructor for '%c' @ %d.\n", $$, @$.first_column); fprintf (stdout, "Default destructor for '%c' @ %d.\n", $$, @$.first_column);
} } %symbol-default
%printer { %printer {
fprintf (yyoutput, "'b'/'c' printer for '%c' @ %d", $$, @$.first_column); fprintf (yyoutput, "'b'/'c' printer for '%c' @ %d", $$, @$.first_column);
@@ -715,10 +715,10 @@ AT_DATA_GRAMMAR([[input.y]],
%token END 0 %token END 0
%printer { %printer {
fprintf (yyoutput, "Default printer for '%c' @ %d", $$, @$.first_column); fprintf (yyoutput, "Default printer for '%c' @ %d", $$, @$.first_column);
} } %symbol-default
%destructor { %destructor {
fprintf (stdout, "Default destructor for '%c' @ %d.\n", $$, @$.first_column); fprintf (stdout, "Default destructor for '%c' @ %d.\n", $$, @$.first_column);
} } %symbol-default
%% %%
@@ -800,10 +800,10 @@ AT_DATA_GRAMMAR([[input.y]],
%printer { %printer {
fprintf (yyoutput, "'%c'", $$); fprintf (yyoutput, "'%c'", $$);
} } %symbol-default
%destructor { %destructor {
fprintf (stderr, "DESTROY '%c'\n", $$); fprintf (stderr, "DESTROY '%c'\n", $$);
} } %symbol-default
%% %%
@@ -911,11 +911,11 @@ AT_DATA_GRAMMAR([[input.y]],
%printer { %printer {
char chr = $$; char chr = $$;
fprintf (yyoutput, "'%c'", chr); fprintf (yyoutput, "'%c'", chr);
} } %symbol-default
%destructor { %destructor {
char chr = $$; char chr = $$;
fprintf (stderr, "DESTROY '%c'\n", chr); fprintf (stderr, "DESTROY '%c'\n", chr);
} } %symbol-default
%union { char chr; } %union { char chr; }
%type <chr> start %type <chr> start

View File

@@ -175,18 +175,18 @@ AT_CLEANUP
AT_SETUP([Default %printer and %destructor redeclared]) AT_SETUP([Default %printer and %destructor redeclared])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%destructor { destroy ($$); } [[%destructor { destroy ($$); } %symbol-default
%printer { destroy ($$); } %printer { destroy ($$); } %symbol-default
%destructor { destroy ($$); } %destructor { destroy ($$); } %symbol-default
%printer { destroy ($$); } %printer { destroy ($$); } %symbol-default
%% %%
start: ; start: ;
%destructor { destroy ($$); }; %destructor { destroy ($$); } %symbol-default;
%printer { destroy ($$); }; %printer { destroy ($$); } %symbol-default;
]]) ]])
AT_CHECK([bison input.y], [1], [], AT_CHECK([bison input.y], [1], [],
@@ -210,7 +210,7 @@ AT_CLEANUP
AT_SETUP([Unused values with default %destructor]) AT_SETUP([Unused values with default %destructor])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%destructor { destroy ($$); } [[%destructor { destroy ($$); } %symbol-default
%% %%
@@ -533,7 +533,7 @@ input.y:4.10-5.0: missing `'' at end of line
input.y:14.11-15.0: missing `'' at end of line input.y:14.11-15.0: missing `'' at end of line
input.y:16.11-17.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: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 AT_CLEANUP