数式の評価を便利な道具で #9
yylvalむき出しの解決法がスマートでないという考え方もあると思う。
構文解析の生成規則上で回避するなら、
デバグプリント版であれば、
...snip %type <val> expr uint %destructor { CHECK_MPZ("error_recovery_clear", $$); mpz_clear($$); } expr %% ...snip expr: uint { mpz_init($$); CHECK_MPZ("init", $$); mpz_set($$, $1); CHECK_MPZ("set", $$); CHECK_MPZ("clear", $1); mpz_clear($1); } ...snip ; uint: UINT { mpz_init($$); CHECK_MPZ("init", $$); mpz_set($$, $1); CHECK_MPZ("set", $$); } ; %% ...snip
要点は、%destructorの処理を行ってほしくない生成規則を新たな非終端記号を使って再定義する。
%destructorの処理が行われるべきなのはexprなので%destructorの対象を
そしてuintの生成規則でUINTからyylvalを切り離してしまえばよい。
uint ::= UINT
は還元に失敗することがないので後始末は不要である。
$ ./calc [lexer] init(003E24D0) 1 2 [lexer] set(003E24D0) [parser] init(003E2540) [parser] set(003E2540) [parser] init(003E2550) [parser] set(003E2550) [parser] clear(003E2540) [lexer] set(003E24D0) syntax error [parser] error_recovery_clear(003E2550) [lexer] clear(003E24D0) $