Next: , Previous: Initial Action Decl, Up: Declarations


3.7.6 Freeing Discarded Symbols

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 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, $$ (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 %destructors. (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 STRING2
     %type  <string> string1 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 %destructors 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 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 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 right-hand side 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:

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.