[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.7.7 Freeing Discarded Symbols
During error recovery (see section 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
or YYACCEPT
, 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.
- Directive: %destructor { code } symbols
-
Invoke the braced code whenever the parser discards one of the symbols. Within code,
$$
designates the semantic value associated with the discarded symbol, and@$
designates its location. The additional parser parameters are also available (see section The Parser Functionyyparse
).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. (These default forms are experimental. More user feedback will help to determine whether they should become permanent features.) 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 (%type
counts 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 %token <string> STRING2 %type <string> string1 %type <string> string2 %union { char character; } %token <character> CHR %type <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 also
prints its line number to stdout
.
It performs only the second %destructor
in this case, so it invokes
free
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 section Bison Symbols),
none of which you can reference in your grammar.
It also will not invoke either for the error
token (see section error), which is always defined by Bison regardless of whether you
reference it in your grammar.
However, it may invoke one of them for the end token (token 0) if you
redefine it from $end
to, for example, END
:
%token END 0 |
Finally, Bison will never invoke a %destructor
for an unreferenced
mid-rule semantic value (see section Actions in Mid-Rule).
That is, Bison does not consider a mid-rule to have a semantic value if you do
not reference $$
in the mid-rule's action or $n
(where
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
<>
%destructor
whenever it discards the mid-rule symbol.
Discarded symbols are the following:
- stacked symbols popped during the first phase of error recovery,
- incoming terminals during the second phase of error recovery,
- the current lookahead and the entire stack (except the current right-hand side symbols) when the parser returns immediately, and
- the start symbol, when the parser succeeds.
The parser can return immediately because of an explicit call to
YYABORT
or YYACCEPT
, 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.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |