Next: Printing Semantic Values, Previous: Performing Actions before Parsing, Up: Bison Declarations [Contents][Index]
During error recovery (see Error Recovery), symbols already pushed on
the stack and tokens coming from the rest of the file are discarded until
the parser falls on its feet. If the parser runs out of memory, or if it
returns via YYABORT
, YYACCEPT
or YYNOMEM
, all the
symbols on the stack must be discarded. Even if the parser succeeds, it
must discard the start symbol.
When discarded symbols convey heap based information, this memory is lost. While this behavior can be tolerable for batch parsers, such as in traditional compilers, it is unacceptable for programs like shells or protocol implementations that may parse and execute indefinitely.
The %destructor
directive defines code that is called when a
symbol is automatically discarded.
Invoke the braced code whenever the parser discards one of the
symbols. Within code, $$
(or $<tag>$
)
designates the semantic value associated with the discarded symbol, and
@$
designates its location. The additional parser parameters are
also available (see The Parser Function yyparse
).
When a symbol is listed among symbols, its %destructor
is called a
per-symbol %destructor
.
You may also define a per-type %destructor
by listing a semantic type
tag among symbols.
In that case, the parser will invoke this code whenever it discards any
grammar symbol that has that semantic type tag unless that symbol has its own
per-symbol %destructor
.
Finally, you can define two different kinds of default %destructor
s.
You can place each of <*>
and <>
in the symbols list of
exactly one %destructor
declaration in your grammar file.
The parser will invoke the code associated with one of these whenever it
discards any user-defined grammar symbol that has no per-symbol and no per-type
%destructor
.
The parser uses the code for <*>
in the case of such a grammar
symbol for which you have formally declared a semantic type tag (%token
,
%nterm
, and %type
count as such a declaration, but $<tag>$
does not).
The parser uses the code for <>
in the case of such a grammar
symbol that has no declared semantic type tag.
For example:
%union { char *string; } %token <string> STRING1 STRING2 %nterm <string> string1 string2 %union { char character; } %token <character> CHR %nterm <character> chr %token TAGLESS %destructor { } <character> %destructor { free ($$); } <*> %destructor { free ($$); printf ("%d", @$.first_line); } STRING1 string1 %destructor { printf ("Discarding tagless symbol.\n"); } <>
guarantees that, when the parser discards any user-defined symbol that has a
semantic type tag other than <character>
, it passes its semantic value
to free
by default.
However, when the parser discards a STRING1
or a string1
,
it uses the third %destructor
, which frees it and
prints its line number to stdout
(free
is invoked only once).
Finally, the parser merely prints a message whenever it discards any symbol,
such as TAGLESS
, that has no semantic type tag.
A Bison-generated parser invokes the default %destructor
s only for
user-defined as opposed to Bison-defined symbols.
For example, the parser will not invoke either kind of default
%destructor
for the special Bison-defined symbols $accept
,
$undefined
, or $end
(see Bison Symbols),
none of which you can reference in your grammar.
It also will not invoke either for the error
token (see Bison Symbols), which is always defined by Bison regardless of whether you
reference it in your grammar.
However, it may invoke one of them for the end token (token 0) if you
redefine it from $end
to, for example, END
:
%token END 0
Finally, Bison will never invoke a %destructor
for an unreferenced
midrule semantic value (see Actions in Midrule).
That is, Bison does not consider a midrule to have a semantic value if you
do not reference $$
in the midrule’s action or $n
(where n is the right-hand side symbol position of the midrule) in
any later action in that rule. However, if you do reference either, the
Bison-generated parser will invoke the <>
%destructor
whenever
it discards the midrule symbol.
Discarded symbols are the following:
parse
,
The parser can return immediately because of an explicit call to
YYABORT
, YYACCEPT
or YYNOMEM
, or failed error recovery,
or memory exhaustion.
Right-hand side symbols of a rule that explicitly triggers a syntax
error via YYERROR
are not discarded automatically. As a rule
of thumb, destructors are invoked only when user actions cannot manage
the memory.
Next: Printing Semantic Values, Previous: Performing Actions before Parsing, Up: Bison Declarations [Contents][Index]