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> 2006-10-21 Joel E. Denny <jdenny@ces.clemson.edu>
Don't apply the default %destructor/%printer to an unreferenced midrule 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, * The -g and --graph options now output graphs in Graphviz DOT format,
not VCG 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 * The Yacc prologue alternatives from Bison 2.3a have been rewritten as the
following directives: following directives:

View File

@@ -4236,8 +4236,8 @@ 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 @findex <*>
@findex <!>
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
until the parser falls on its feet. If the parser runs out of memory, 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 When a symbol is listed among @var{symbols}, its @code{%destructor} is called a
per-symbol @code{%destructor}. per-symbol @code{%destructor}.
You may also define a per-type @code{%destructor} by listing a semantic type 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 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}. per-symbol @code{%destructor}.
Finally, you may define a default @code{%destructor} by placing Finally, you can define two different kinds of default @code{%destructor}s.
@code{%symbol-default} in the @var{symbols} list of exactly one You can place each of @code{<*>} and @code{<!>} in the @var{symbols} list of
@code{%destructor} declaration in your grammar file. exactly one @code{%destructor} declaration in your grammar file.
In that case, the parser will invoke the associated @var{code} whenever it The parser will invoke the @var{code} associated with one of these whenever it
discards any user-defined grammar symbol for which there is no per-type or discards any user-defined grammar symbol that has no per-symbol and no per-type
per-symbol @code{%destructor}. @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 @end deffn
@noindent @noindent
For instance: For example:
@smallexample @smallexample
%union @{ char *string; @} %union @{ char *string; @}
@@ -4290,35 +4295,52 @@ For instance:
%union @{ char character; @} %union @{ char character; @}
%token <character> CHR %token <character> CHR
%type <character> chr %type <character> chr
%destructor @{ free ($$); @} %symbol-default %token TAGLESS
%destructor @{ free ($$); printf ("%d", @@$.first_line); @} STRING1 string1
%destructor @{ @} <character> %destructor @{ @} <character>
%destructor @{ free ($$); @} <*>
%destructor @{ free ($$); printf ("%d", @@$.first_line); @} STRING1 string1
%destructor @{ printf ("Discarding tagless symbol.\n"); @} <!>
@end smallexample @end smallexample
@noindent @noindent
guarantees that, when the parser discards any user-defined symbol that has a 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 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 However, when the parser discards a @code{STRING1} or a @code{string1}, it also
prints its line number to @code{stdout}. prints its line number to @code{stdout}.
It performs only the second @code{%destructor} in this case, so it invokes It performs only the second @code{%destructor} in this case, so it invokes
@code{free} only once. @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} A Bison-generated parser invokes the default @code{%destructor}s only for
only for user-defined as opposed to Bison-defined symbols. user-defined as opposed to Bison-defined symbols.
For example, the parser will not invoke it for the special Bison-defined For example, the parser will not invoke either kind of default
symbols @code{$accept}, @code{$undefined}, or @code{$end} (@pxref{Table of @code{%destructor} for the special Bison-defined symbols @code{$accept},
Symbols, ,Bison Symbols}), none of which you can reference in your grammar. @code{$undefined}, or @code{$end} (@pxref{Table of Symbols, ,Bison Symbols}),
It also will not invoke it for the @code{error} token (@pxref{Table of Symbols, none of which you can reference in your grammar.
,error}), which is always defined by Bison regardless of whether you reference It also will not invoke either for the @code{error} token (@pxref{Table of
it in your grammar. Symbols, ,error}), which is always defined by Bison regardless of whether you
However, it will invoke it for the end token (token 0) if you redefine it from reference it in your grammar.
@code{$end} to, for example, @code{END}: 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 @smallexample
%token END 0 %token END 0
@end smallexample @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 @ignore
@noindent @noindent
In the future, it may be possible to redefine the @code{error} token as a 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}. @xref{Rules, ,Syntax of Grammar Rules}.
@end deffn @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 @deffn {Symbol} $accept
The predefined nonterminal whose only rule is @samp{$accept: @var{start} The predefined nonterminal whose only rule is @samp{$accept: @var{start}
$end}, where @var{start} is the start symbol. @xref{Start Decl, , The $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}. 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,55 +48,56 @@
PERCENT_TYPE = 262, PERCENT_TYPE = 262,
PERCENT_DESTRUCTOR = 263, PERCENT_DESTRUCTOR = 263,
PERCENT_PRINTER = 264, PERCENT_PRINTER = 264,
PERCENT_SYMBOL_DEFAULT = 265, PERCENT_LEFT = 265,
PERCENT_LEFT = 266, PERCENT_RIGHT = 266,
PERCENT_RIGHT = 267, PERCENT_NONASSOC = 267,
PERCENT_NONASSOC = 268, PERCENT_PREC = 268,
PERCENT_PREC = 269, PERCENT_DPREC = 269,
PERCENT_DPREC = 270, PERCENT_MERGE = 270,
PERCENT_MERGE = 271, PERCENT_CODE = 271,
PERCENT_CODE = 272, PERCENT_CODE_TOP = 272,
PERCENT_CODE_TOP = 273, PERCENT_DEBUG = 273,
PERCENT_DEBUG = 274, PERCENT_DEFAULT_PREC = 274,
PERCENT_DEFAULT_PREC = 275, PERCENT_DEFINE = 275,
PERCENT_DEFINE = 276, PERCENT_DEFINES = 276,
PERCENT_DEFINES = 277, PERCENT_ERROR_VERBOSE = 277,
PERCENT_ERROR_VERBOSE = 278, PERCENT_EXPECT = 278,
PERCENT_EXPECT = 279, PERCENT_EXPECT_RR = 279,
PERCENT_EXPECT_RR = 280, PERCENT_FILE_PREFIX = 280,
PERCENT_FILE_PREFIX = 281, PERCENT_GLR_PARSER = 281,
PERCENT_GLR_PARSER = 282, PERCENT_INITIAL_ACTION = 282,
PERCENT_INITIAL_ACTION = 283, PERCENT_LEX_PARAM = 283,
PERCENT_LEX_PARAM = 284, PERCENT_LOCATIONS = 284,
PERCENT_LOCATIONS = 285, PERCENT_NAME_PREFIX = 285,
PERCENT_NAME_PREFIX = 286, PERCENT_NO_DEFAULT_PREC = 286,
PERCENT_NO_DEFAULT_PREC = 287, PERCENT_NO_LINES = 287,
PERCENT_NO_LINES = 288, PERCENT_NONDETERMINISTIC_PARSER = 288,
PERCENT_NONDETERMINISTIC_PARSER = 289, PERCENT_OUTPUT = 289,
PERCENT_OUTPUT = 290, PERCENT_PARSE_PARAM = 290,
PERCENT_PARSE_PARAM = 291, PERCENT_PROVIDES = 291,
PERCENT_PROVIDES = 292, PERCENT_PURE_PARSER = 292,
PERCENT_PURE_PARSER = 293, PERCENT_PUSH_PARSER = 293,
PERCENT_PUSH_PARSER = 294, PERCENT_REQUIRE = 294,
PERCENT_REQUIRE = 295, PERCENT_REQUIRES = 295,
PERCENT_REQUIRES = 296, PERCENT_SKELETON = 296,
PERCENT_SKELETON = 297, PERCENT_START = 297,
PERCENT_START = 298, PERCENT_TOKEN_TABLE = 298,
PERCENT_TOKEN_TABLE = 299, PERCENT_VERBOSE = 299,
PERCENT_VERBOSE = 300, PERCENT_YACC = 300,
PERCENT_YACC = 301, BRACED_CODE = 301,
BRACED_CODE = 302, CHAR = 302,
CHAR = 303, EPILOGUE = 303,
EPILOGUE = 304, EQUAL = 304,
EQUAL = 305, ID = 305,
ID = 306, ID_COLON = 306,
ID_COLON = 307, PERCENT_PERCENT = 307,
PERCENT_PERCENT = 308, PIPE = 308,
PIPE = 309, PROLOGUE = 309,
PROLOGUE = 310, SEMICOLON = 310,
SEMICOLON = 311, TYPE = 311,
TYPE = 312, TYPE_TAG_ANY = 312,
PERCENT_UNION = 313 TYPE_TAG_NONE = 313,
PERCENT_UNION = 314
}; };
#endif #endif
/* Tokens. */ /* Tokens. */
@@ -108,55 +109,56 @@
#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_SYMBOL_DEFAULT 265 #define PERCENT_LEFT 265
#define PERCENT_LEFT 266 #define PERCENT_RIGHT 266
#define PERCENT_RIGHT 267 #define PERCENT_NONASSOC 267
#define PERCENT_NONASSOC 268 #define PERCENT_PREC 268
#define PERCENT_PREC 269 #define PERCENT_DPREC 269
#define PERCENT_DPREC 270 #define PERCENT_MERGE 270
#define PERCENT_MERGE 271 #define PERCENT_CODE 271
#define PERCENT_CODE 272 #define PERCENT_CODE_TOP 272
#define PERCENT_CODE_TOP 273 #define PERCENT_DEBUG 273
#define PERCENT_DEBUG 274 #define PERCENT_DEFAULT_PREC 274
#define PERCENT_DEFAULT_PREC 275 #define PERCENT_DEFINE 275
#define PERCENT_DEFINE 276 #define PERCENT_DEFINES 276
#define PERCENT_DEFINES 277 #define PERCENT_ERROR_VERBOSE 277
#define PERCENT_ERROR_VERBOSE 278 #define PERCENT_EXPECT 278
#define PERCENT_EXPECT 279 #define PERCENT_EXPECT_RR 279
#define PERCENT_EXPECT_RR 280 #define PERCENT_FILE_PREFIX 280
#define PERCENT_FILE_PREFIX 281 #define PERCENT_GLR_PARSER 281
#define PERCENT_GLR_PARSER 282 #define PERCENT_INITIAL_ACTION 282
#define PERCENT_INITIAL_ACTION 283 #define PERCENT_LEX_PARAM 283
#define PERCENT_LEX_PARAM 284 #define PERCENT_LOCATIONS 284
#define PERCENT_LOCATIONS 285 #define PERCENT_NAME_PREFIX 285
#define PERCENT_NAME_PREFIX 286 #define PERCENT_NO_DEFAULT_PREC 286
#define PERCENT_NO_DEFAULT_PREC 287 #define PERCENT_NO_LINES 287
#define PERCENT_NO_LINES 288 #define PERCENT_NONDETERMINISTIC_PARSER 288
#define PERCENT_NONDETERMINISTIC_PARSER 289 #define PERCENT_OUTPUT 289
#define PERCENT_OUTPUT 290 #define PERCENT_PARSE_PARAM 290
#define PERCENT_PARSE_PARAM 291 #define PERCENT_PROVIDES 291
#define PERCENT_PROVIDES 292 #define PERCENT_PURE_PARSER 292
#define PERCENT_PURE_PARSER 293 #define PERCENT_PUSH_PARSER 293
#define PERCENT_PUSH_PARSER 294 #define PERCENT_REQUIRE 294
#define PERCENT_REQUIRE 295 #define PERCENT_REQUIRES 295
#define PERCENT_REQUIRES 296 #define PERCENT_SKELETON 296
#define PERCENT_SKELETON 297 #define PERCENT_START 297
#define PERCENT_START 298 #define PERCENT_TOKEN_TABLE 298
#define PERCENT_TOKEN_TABLE 299 #define PERCENT_VERBOSE 299
#define PERCENT_VERBOSE 300 #define PERCENT_YACC 300
#define PERCENT_YACC 301 #define BRACED_CODE 301
#define BRACED_CODE 302 #define CHAR 302
#define CHAR 303 #define EPILOGUE 303
#define EPILOGUE 304 #define EQUAL 304
#define EQUAL 305 #define ID 305
#define ID 306 #define ID_COLON 306
#define ID_COLON 307 #define PERCENT_PERCENT 307
#define PERCENT_PERCENT 308 #define PIPE 308
#define PIPE 309 #define PROLOGUE 309
#define PROLOGUE 310 #define SEMICOLON 310
#define SEMICOLON 311 #define TYPE 311
#define TYPE 312 #define TYPE_TAG_ANY 312
#define PERCENT_UNION 313 #define TYPE_TAG_NONE 313
#define PERCENT_UNION 314
@@ -177,7 +179,7 @@ typedef union YYSTYPE
} }
/* Line 1535 of yacc.c */ /* Line 1535 of yacc.c */
#line 181 "parse-gram.h" #line 183 "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,8 +116,6 @@ 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"
@@ -177,6 +175,8 @@ static int current_prec = 0;
%token PROLOGUE "%{...%}" %token PROLOGUE "%{...%}"
%token SEMICOLON ";" %token SEMICOLON ";"
%token TYPE "type" %token TYPE "type"
%token TYPE_TAG_ANY "<*>"
%token TYPE_TAG_NONE "<!>"
%type <character> CHAR %type <character> CHAR
%printer { fputs (char_name ($$), stderr); } CHAR %printer { fputs (char_name ($$), stderr); } CHAR
@@ -395,7 +395,8 @@ generic_symlist:
generic_symlist_item: generic_symlist_item:
symbol { $$ = symbol_list_sym_new ($1, @1); } symbol { $$ = symbol_list_sym_new ($1, @1); }
| TYPE { $$ = symbol_list_type_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. */ /* One token definition. */

View File

@@ -194,7 +194,6 @@ splice (\\[ \f\t\v]*\n)*
"%right" return PERCENT_RIGHT; "%right" return PERCENT_RIGHT;
"%skeleton" return PERCENT_SKELETON; "%skeleton" return PERCENT_SKELETON;
"%start" return PERCENT_START; "%start" return PERCENT_START;
"%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;
@@ -210,6 +209,8 @@ splice (\\[ \f\t\v]*\n)*
"=" return EQUAL; "=" return EQUAL;
"|" return PIPE; "|" return PIPE;
";" return SEMICOLON; ";" return SEMICOLON;
"<*>" return TYPE_TAG_ANY;
"<!>" return TYPE_TAG_NONE;
{id} { {id} {
val->uniqstr = uniqstr_new (yytext); 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 *
symbol_list_default_new (location loc) symbol_list_default_tagged_new (location loc)
{ {
symbol_list *res = xmalloc (sizeof *res); 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->location = loc;
res->next = NULL; res->next = NULL;
@@ -215,8 +232,11 @@ symbol_list_destructor_set (symbol_list *node, const char *destructor,
semantic_type_destructor_set ( semantic_type_destructor_set (
semantic_type_get (node->content.type_name), destructor, loc); semantic_type_get (node->content.type_name), destructor, loc);
break; break;
case SYMLIST_DEFAULT: case SYMLIST_DEFAULT_TAGGED:
default_destructor_set (destructor, loc); default_tagged_destructor_set (destructor, loc);
break;
case SYMLIST_DEFAULT_TAGLESS:
default_tagless_destructor_set (destructor, loc);
break; break;
} }
} }
@@ -233,8 +253,11 @@ symbol_list_printer_set (symbol_list *node, const char *printer, location loc)
semantic_type_printer_set ( semantic_type_printer_set (
semantic_type_get (node->content.type_name), printer, loc); semantic_type_get (node->content.type_name), printer, loc);
break; break;
case SYMLIST_DEFAULT: case SYMLIST_DEFAULT_TAGGED:
default_printer_set (printer, loc); default_tagged_printer_set (printer, loc);
break;
case SYMLIST_DEFAULT_TAGLESS:
default_tagless_printer_set (printer, loc);
break; break;
} }
} }

View File

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

View File

@@ -41,14 +41,19 @@ symbol *accept = NULL;
symbol *startsymbol = NULL; symbol *startsymbol = NULL;
location startsymbol_location; location startsymbol_location;
/*-----------------------------------. /*---------------------------------------.
| Default %destructor and %printer. | | Default %destructor's and %printer's. |
`-----------------------------------*/ `---------------------------------------*/
static const char *default_destructor = NULL; static const char *default_tagged_destructor = NULL;
static location default_destructor_location; static location default_tagged_destructor_location;
static const char *default_printer = NULL; static const char *default_tagless_destructor = NULL;
static location default_printer_location; 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. | | Create a new symbol, named TAG. |
@@ -220,10 +225,13 @@ symbol_destructor_get (symbol *sym)
return type->destructor; 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) if (sym->tag[0] == '$' || sym == errtoken)
return NULL; 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); semantic_type *type = semantic_type_get (sym->type_name);
if (type->destructor) if (type->destructor)
return type->destructor_location; 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. */ /* Apply the default %printer only to user-defined symbols. */
if (sym->tag[0] == '$' || sym == errtoken) if (sym->tag[0] == '$' || sym == errtoken)
return NULL; 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); semantic_type *type = semantic_type_get (sym->type_name);
if (type->printer) if (type->printer)
return type->printer_location; 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 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 (loc, _("redeclaration for default tagged %%destructor"));
complain_at (default_destructor_location, _("previous declaration")); complain_at (default_tagged_destructor_location,
_("previous declaration"));
} }
default_destructor = destructor; default_tagged_destructor = destructor;
default_destructor_location = loc; default_tagged_destructor_location = loc;
} }
void 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 (loc, _("redeclaration for default tagless %%destructor"));
complain_at (default_printer_location, _("previous declaration")); complain_at (default_tagless_destructor_location,
_("previous declaration"));
} }
default_printer = printer; default_tagless_destructor = destructor;
default_printer_location = loc; 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. /** Any \c \%destructor declared specifically for this symbol.
Access this field only through <tt>symbol</tt>'s interface functions. For Access this field only through <tt>symbol</tt>'s interface functions. For
example, if <tt>symbol::destructor = NULL</tt>, the default example, if <tt>symbol::destructor = NULL</tt>, a default \c \%destructor
\c \%destructor or a per-type \c \%destructor might be appropriate, and or a per-type \c \%destructor might be appropriate, and
\c symbol_destructor_get will compute the correct one. */ \c symbol_destructor_get will compute the correct one. */
const char *destructor; const char *destructor;
@@ -255,14 +255,18 @@ void symbols_check_defined (void);
void symbols_pack (void); void symbols_pack (void);
/*-----------------------------------. /*---------------------------------------.
| Default %destructor and %printer. | | Default %destructor's and %printer's. |
`-----------------------------------*/ `---------------------------------------*/
/** Set the default \c \%destructor. */ /** Set the default \c \%destructor for tagged values. */
void default_destructor_set (const char *destructor, location loc); 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. */ /** Set the default \c \%printer for tagged values. */
void default_printer_set (const char *printer, location loc); 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_ */ #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 # Check that the right %printer and %destructor are called, that they're not
# called for $end, and that $$ and @$ work correctly. # 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]], AT_DATA_GRAMMAR([[input.y]],
[[%error-verbose [[%error-verbose
@@ -610,11 +610,15 @@ AT_DATA_GRAMMAR([[input.y]],
%} %}
%printer { %printer {
fprintf (yyoutput, "Default printer for '%c' @ %d", $$, @$.first_column); fprintf (yyoutput, "<*> printer should not be called.\n");
} %symbol-default } <*>
%printer {
fprintf (yyoutput, "<!> printer for '%c' @ %d", $$, @$.first_column);
} <!>
%destructor { %destructor {
fprintf (stdout, "Default destructor for '%c' @ %d.\n", $$, @$.first_column); fprintf (stdout, "<!> 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);
@@ -623,6 +627,10 @@ AT_DATA_GRAMMAR([[input.y]],
fprintf (stdout, "'b'/'c' destructor for '%c' @ %d.\n", $$, @$.first_column); fprintf (stdout, "'b'/'c' destructor for '%c' @ %d.\n", $$, @$.first_column);
} 'b' 'c' } 'b' 'c'
%destructor {
fprintf (yyoutput, "<*> destructor should not be called.\n");
} <*>
%% %%
start: 'a' 'b' 'c' 'd' 'e' { $$ = 'S'; USE(($1, $2, $3, $4, $5)); } ; 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_CHECK([bison -o input.c input.y])
AT_COMPILE([input]) AT_COMPILE([input])
AT_PARSER_CHECK([./input], 1, AT_PARSER_CHECK([./input], 1,
[[Default destructor for 'd' @ 4. [[<!> destructor for 'd' @ 4.
'b'/'c' destructor for 'c' @ 3. 'b'/'c' destructor for 'c' @ 3.
'b'/'c' destructor for 'b' @ 2. 'b'/'c' destructor for 'b' @ 2.
Default destructor for 'a' @ 1. <!> destructor for 'a' @ 1.
]], ]],
[[Starting parse [[Starting parse
Entering state 0 Entering state 0
Reading a token: Next token is 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: Default printer for 'a' @ 1) Shifting token 'a' (1.1-1.1: <!> printer for 'a' @ 1)
Entering state 1 Entering state 1
Reading a token: Next token is token 'b' (1.2-1.2: 'b'/'c' printer for 'b' @ 2) 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) 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) 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) Shifting token 'c' (1.3-1.3: 'b'/'c' printer for 'c' @ 3)
Entering state 5 Entering state 5
Reading a token: Next token is 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: Default printer for 'd' @ 4) Shifting token 'd' (1.4-1.4: <!> printer for 'd' @ 4)
Entering state 6 Entering state 6
Reading a token: Now at end of input. Reading a token: Now at end of input.
syntax error, unexpected $end, expecting 'e' 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 Stack now 0 1 3 5
Error: popping token 'c' (1.3-1.3: 'b'/'c' printer for 'c' @ 3) Error: popping token 'c' (1.3-1.3: 'b'/'c' printer for 'c' @ 3)
Stack now 0 1 3 Stack now 0 1 3
Error: popping token 'b' (1.2-1.2: 'b'/'c' printer for 'b' @ 2) Error: popping token 'b' (1.2-1.2: 'b'/'c' printer for 'b' @ 2)
Stack now 0 1 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 Stack now 0
Cleanup: discarding lookahead token $end (1.5-1.5: ) Cleanup: discarding lookahead token $end (1.5-1.5: )
Stack now 0 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]], AT_DATA_GRAMMAR([[input.y]],
[[%error-verbose [[%error-verbose
@@ -714,16 +722,20 @@ AT_DATA_GRAMMAR([[input.y]],
# define USE(SYM) # define USE(SYM)
%} %}
%printer {
fprintf (yyoutput, "<!> printer should not be called.\n");
} <!>
%union { int field0; int field1; int field2; } %union { int field0; int field1; int field2; }
%type <field0> start 'a' 'g' %type <field0> start 'a' 'g'
%type <field1> 'e' %type <field1> 'e'
%type <field2> 'f' %type <field2> 'f'
%printer { %printer {
fprintf (yyoutput, "%%symbol-default/<field2>/e printer"); fprintf (yyoutput, "<*>/<field2>/e printer");
} %symbol-default 'e' <field2> } <*> 'e' <field2>
%destructor { %destructor {
fprintf (stdout, "%%symbol-default/<field2>/e destructor.\n"); fprintf (stdout, "<*>/<field2>/e destructor.\n");
} %symbol-default 'e' <field2> } <*> 'e' <field2>
%type <field1> 'b' %type <field1> 'b'
%printer { fprintf (yyoutput, "<field1> printer"); } <field1> %printer { fprintf (yyoutput, "<field1> printer"); } <field1>
@@ -737,6 +749,10 @@ AT_DATA_GRAMMAR([[input.y]],
%printer { fprintf (yyoutput, "'d' printer"); } 'd' %printer { fprintf (yyoutput, "'d' printer"); } 'd'
%destructor { fprintf (stdout, "'d' destructor.\n"); } 'd' %destructor { fprintf (stdout, "'d' destructor.\n"); } 'd'
%destructor {
fprintf (yyoutput, "<!> destructor should not be called.\n");
} <!>
%% %%
start: start:
@@ -776,17 +792,17 @@ main (void)
AT_CHECK([bison -o input.c input.y]) AT_CHECK([bison -o input.c input.y])
AT_COMPILE([input]) AT_COMPILE([input])
AT_PARSER_CHECK([./input], 1, AT_PARSER_CHECK([./input], 1,
[[%symbol-default/<field2>/e destructor. [[<*>/<field2>/e destructor.
%symbol-default/<field2>/e destructor. <*>/<field2>/e destructor.
'd' destructor. 'd' destructor.
'c' destructor. 'c' destructor.
<field1> destructor. <field1> destructor.
%symbol-default/<field2>/e destructor. <*>/<field2>/e destructor.
]], ]],
[[Starting parse [[Starting parse
Entering state 0 Entering state 0
Reading a token: Next token is token 'a' (%symbol-default/<field2>/e printer) Reading a token: Next token is token 'a' (<*>/<field2>/e printer)
Shifting token 'a' (%symbol-default/<field2>/e printer) Shifting token 'a' (<*>/<field2>/e printer)
Entering state 1 Entering state 1
Reading a token: Next token is token 'b' (<field1> printer) Reading a token: Next token is token 'b' (<field1> printer)
Shifting 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) Reading a token: Next token is token 'd' ('d' printer)
Shifting token 'd' ('d' printer) Shifting token 'd' ('d' printer)
Entering state 6 Entering state 6
Reading a token: Next token is token 'e' (%symbol-default/<field2>/e printer) Reading a token: Next token is token 'e' (<*>/<field2>/e printer)
Shifting token 'e' (%symbol-default/<field2>/e printer) Shifting token 'e' (<*>/<field2>/e printer)
Entering state 7 Entering state 7
Reading a token: Next token is token 'f' (%symbol-default/<field2>/e printer) Reading a token: Next token is token 'f' (<*>/<field2>/e printer)
Shifting token 'f' (%symbol-default/<field2>/e printer) Shifting token 'f' (<*>/<field2>/e printer)
Entering state 8 Entering state 8
Reading a token: Now at end of input. Reading a token: Now at end of input.
syntax error, unexpected $end, expecting 'g' 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 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 Stack now 0 1 3 5 6
Error: popping token 'd' ('d' printer) Error: popping token 'd' ('d' printer)
Stack now 0 1 3 5 Stack now 0 1 3 5
@@ -815,7 +831,7 @@ Error: popping token 'c' ('c' printer)
Stack now 0 1 3 Stack now 0 1 3
Error: popping token 'b' (<field1> printer) Error: popping token 'b' (<field1> printer)
Stack now 0 1 Stack now 0 1
Error: popping token 'a' (%symbol-default/<field2>/e printer) Error: popping token 'a' (<*>/<field2>/e printer)
Stack now 0 Stack now 0
Cleanup: discarding lookahead token $end () Cleanup: discarding lookahead token $end ()
Stack now 0 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_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 [[%error-verbose
%debug %debug
%locations %locations
@@ -848,13 +871,26 @@ AT_DATA_GRAMMAR([[input.y]],
# define USE(SYM) # define USE(SYM)
%} %}
%destructor {
fprintf (yyoutput, "<]]not_kind[[> destructor should not be called.\n");
} <]]not_kind[[>
%token END 0 %token END 0
%printer { %printer {
fprintf (yyoutput, "Default printer for '%c' @ %d", $$, @$.first_column); fprintf (yyoutput, "<]]kind[[> for '%c' @ %d", $$, @$.first_column);
} %symbol-default } <]]kind[[>
%destructor { %destructor {
fprintf (stdout, "Default destructor for '%c' @ %d.\n", $$, @$.first_column); fprintf (stdout, "<]]kind[[> for '%c' @ %d.\n", $$, @$.first_column);
} %symbol-default } <]]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; static int called;
if (called++) if (called++)
abort (); abort ();
yylval = 'E'; yylval]]m4_if($1, 0,, [[[.tag]]])[[ = 'E';
yylloc.first_line = yylloc.last_line = 1; yylloc.first_line = yylloc.last_line = 1;
yylloc.first_column = yylloc.last_column = 1; yylloc.first_column = yylloc.last_column = 1;
return 0; return 0;
@@ -888,26 +924,33 @@ main (void)
} }
]]) ]])
AT_CHECK([bison -o input.c input.y]) AT_CHECK([bison -o input$1.c input$1.y])
AT_COMPILE([input]) AT_COMPILE([input$1])
AT_PARSER_CHECK([./input], 0, AT_PARSER_CHECK([./input$1], 0,
[[Default destructor for 'E' @ 1. [[<]]kind[[> for 'E' @ 1.
Default destructor for 'S' @ 1. <]]kind[[> for 'S' @ 1.
]], ]],
[[Starting parse [[Starting parse
Entering state 0 Entering state 0
Reducing stack by rule 1 (line 35): Reducing stack by rule 1 (line 46):
-> $$ = nterm start (1.1-1.1: Default printer for 'S' @ 1) -> $$ = nterm start (1.1-1.1: <]]kind[[> for 'S' @ 1)
Stack now 0 Stack now 0
Entering state 1 Entering state 1
Reading a token: Now at end of input. 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 Entering state 2
Stack now 0 1 2 Stack now 0 1 2
Cleanup: popping token END (1.1-1.1: Default printer for 'E' @ 1) Cleanup: popping token END (1.1-1.1: <]]kind[[> for 'E' @ 1)
Cleanup: popping nterm start (1.1-1.1: Default printer for 'S' @ 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 AT_CLEANUP
@@ -940,10 +983,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 } <!> <*>
%% %%
@@ -1055,11 +1098,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
@@ -1119,8 +1162,10 @@ AT_DATA_GRAMMAR([[input.y]],
# define YY_LOCATION_PRINT(File, Loc) # define YY_LOCATION_PRINT(File, Loc)
%} %}
%printer { fprintf (yyoutput, "%d", @$); } %symbol-default %printer { fprintf (yyoutput, "%d", @$); } <!>
%destructor { fprintf (stderr, "DESTROY %d\n", @$); } %symbol-default %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,, AT_CHECK([bison -o input.c input.y], 0,,
[[input.y:31.3-23: warning: unset value: $$ [[input.y:33.3-23: warning: unset value: $$
input.y:28.3-33.37: warning: unused value: $3 input.y:30.3-35.37: warning: unused value: $3
]]) ]])
AT_COMPILE([input]) AT_COMPILE([input])
AT_PARSER_CHECK([./input], 1,, AT_PARSER_CHECK([./input], 1,,
[[Starting parse [[Starting parse
Entering state 0 Entering state 0
Reducing stack by rule 1 (line 28): Reducing stack by rule 1 (line 30):
-> $$ = nterm $@1 (: ) -> $$ = nterm $@1 (: )
Stack now 0 Stack now 0
Entering state 2 Entering state 2
Reducing stack by rule 2 (line 29): Reducing stack by rule 2 (line 31):
-> $$ = nterm @2 (: 2) -> $$ = nterm @2 (: 2)
Stack now 0 2 Stack now 0 2
Entering state 4 Entering state 4
Reducing stack by rule 3 (line 30): Reducing stack by rule 3 (line 32):
-> $$ = nterm @3 (: 3) -> $$ = nterm @3 (: 3)
Stack now 0 2 4 Stack now 0 2 4
Entering state 5 Entering state 5
Reducing stack by rule 4 (line 31): Reducing stack by rule 4 (line 33):
-> $$ = nterm @4 (: 4) -> $$ = nterm @4 (: 4)
Stack now 0 2 4 5 Stack now 0 2 4 5
Entering state 6 Entering state 6

View File

@@ -178,33 +178,54 @@ 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 ($$); } %symbol-default %symbol-default [[%destructor { destroy ($$); } <*> <*>
%printer { destroy ($$); } %symbol-default %symbol-default %printer { destroy ($$); } <*> <*>
%destructor { destroy ($$); } %symbol-default %destructor { destroy ($$); } <*>
%printer { destroy ($$); } %symbol-default %printer { destroy ($$); } <*>
%destructor { destroy ($$); } <!> <!>
%printer { destroy ($$); } <!> <!>
%destructor { destroy ($$); } <!>
%printer { destroy ($$); } <!>
%% %%
start: ; start: ;
%destructor { destroy ($$); } %symbol-default; %destructor { destroy ($$); } <*>;
%printer { destroy ($$); } %symbol-default; %printer { destroy ($$); } <*>;
%destructor { destroy ($$); } <!>;
%printer { destroy ($$); } <!>;
]]) ]])
AT_CHECK([bison input.y], [1], [], 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: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: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: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: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: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: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 AT_CLEANUP
@@ -260,18 +281,36 @@ 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 ($$); } %symbol-default [[%destructor { destroy ($$); } <!>
%type <tag> tagged
%% %%
start: end end { $1; } ; start: end end tagged tagged { $<tag>1; $3; } ;
end: { } ; end: { } ;
tagged: { } ;
]]) ]])
AT_CHECK([bison input.y], [0], [], AT_CHECK([bison input.y], [0], [],
[[input.y:5.8-22: warning: unset value: $$ [[input.y:6.8-45: warning: unset value: $$
input.y:5.8-22: warning: unused value: $2 input.y:6.8-45: warning: unused value: $2
input.y:6.6-8: warning: unset value: $$ 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 AT_CLEANUP