数式の評価を便利な道具で #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の対象をでなくexprのみに限定する。
そして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)

$