The %destructor directive
%destructor命令
The %destructor directive is used to specify a destructor for a non-terminal symbol. (See also the %token_destructor directive which is used to specify a destructor for terminal symbols.)
%destructor命令は、非終端シンボルのデストラクタを指定するために用いられる(終端シンボルのデストラクタを指定するために用いられる%token_destructor命令についても参照せよ)。
A non-terminal's destructor is called to dispose of the non-terminal's value whenever the non-terminal is popped from the stack. This includes all of the following circumstances:
非終端のデストラクタは、非終端がスタックからポップされるときは常に、非終端の値を破棄するために呼ばれる。これには下記の全ての場合が含まれる:
When a rule reduces and the value of a non-terminal on the right-hand side is not linked to C code.
- 規則が還元され、右辺の非終端の値がCコードに結びつけられていない場合
When the stack is popped during error processing.
- エラー処理中にスタックがポップされた場合
When the ParseFree() function runs.
- ParseFree()関数が実行された場合
The destructor can do whatever it wants with the value of the non-terminal, but its design is to deallocate memory or other resources held by that non-terminal.
デストラクタでは非終端の値を用いてどんなことでもできるが、その非終端によって保持されるメモリやその他のリソースを解放するために設計された。
Consider an example:
下記の例を検討する:
%type nt {void*} %destructor nt { free($$); } nt(A) ::= ID NUM. { A = malloc( 100 ); }
This example is a bit contrived but it serves to illustrate how destructors work. The example shows a non-terminal named “nt” that holds values of type “void*”. When the rule for an “nt” reduces, it sets the value of the non-terminal to space obtained from malloc(). Later, when the nt non-terminal is popped from the stack, the destructor will fire and call free() on this malloced space, thus avoiding a memory leak. (Note that the symbol “$$” in the destructor code is replaced by the value of the non-terminal.)
この例は若干不自然だが、デストラクタがどのように昨日するかを説明する役に立つ。この例は、“nt”と名づけられた非終端が“void*”型の値を保持することを示す。“nt”の規則が還元されたら、malloc()から得たメモリを非終端の値に設定する。その後、nt非終端がスタックからポップされたら、デストラクタが発火してmallocしたメモリに対してfree()を呼ぶ。つまり、メモリリークを避けるために。(“$$”シンボルがデストラクタのコード内で非終端の値に置換されることに留意せよ)
It is important to note that the value of a non-terminal is passed to the destructor whenever the non-terminal is removed from the stack, unless the non-terminal is used in a C-code action. If the non-terminal is used by C-code, then it is assumed that the C-code will take care of destroying it if it should really be destroyed. More commonly, the value is used to build some larger structure and we don't want to destroy it, which is why the destructor is not called in this circumstance.
非終端がCコードのアクションで使用されていなければ、非終端がスタックから取り除かれた場合は常に、非終端の値がデストラクタに渡されるという点が重要である。非終端がCコードで使用されていたら、それが本当に破棄されるべきであれば、破棄するように取りはからうと見なされる。より一般的に、そのような値はより大きな構造を構築するために用いられ、我々は破棄したくないというのが、この場合にデストラクタが呼ばれない理由である。
By appropriate use of destructors, it is possible to build a parser using Lemon that can be used within a long-running program, such as a GUI, that will not leak memory or other resources. To do the same using yacc or bison is much more difficult.
The %token_destructor directive
The %destructor directive assigns a destructor to a non-terminal symbol. (See the description of the %destructor directive above.) This directive does the same thing for all terminal symbols.
Unlike non-terminal symbols which may each have a different data type for their values, terminals all use the same data type (defined by the %token_type directive) and so they use a common destructor. Other than that, the token destructor works just like the non-terminal destructors.
このページへのコメント
Ivjs5R Great, thanks for sharing this blog article. Cool.
cCQyme <a href="http://brokedlgsilt.com/">brokedlgsilt</a>, [url=http://ipthfcsayqiv.com/]ipthfcsayqiv[/url], [link=http://profttbecqsj.com/]profttbecqsj[/link], http://bwcozunwkmsk.com/