数式の評価を便利な道具で #6

引き算や割り算や括弧も使えるように。
割り算は0方向への丸め。0除算でこける。

calc.y
%{
#include <stdio.h>
#include <gmp.h>
int yylex(void);
void yyerror(char *s);

%}
%union {
    mpz_t val;
}
%token <val> UINT
%left '+' '-'
%left '*' '/'
%left NEG
%type <val> expr
%destructor { mpz_clear($$); } <val>
%%
stmt:
      /* empty */
    | stmt '\n'
    | stmt expr '\n'    { gmp_printf("%Zd\n", $2); mpz_clear($2); }
    | error '\n'        { yyerrok; }
    ;
expr:
      UINT          { mpz_init($$); mpz_set($$, $1); }
    | expr '+' expr { mpz_init($$); mpz_add($$, $1, $3); mpz_clears($1, $3, NULL); }
    | expr '-' expr { mpz_init($$); mpz_sub($$, $1, $3); mpz_clears($1, $3, NULL); }
    | expr '*' expr { mpz_init($$); mpz_mul($$, $1, $3); mpz_clears($1, $3, NULL); }
    | expr '/' expr { mpz_init($$); mpz_tdiv_q($$, $1, $3); mpz_clears($1, $3, NULL); }
    | '-' expr %prec NEG { mpz_init($$); mpz_neg($$, $2); mpz_clear($2); }
    | '(' expr ')' { mpz_init($$); mpz_set($$, $2); mpz_clear($2); }
    ;
%%
int main(void)
{
    yyparse();
    return 0;
}

void yyerror(char *s)
{
    gmp_printf("%s\n", s);
}
calc.l
%{
#include <gmp.h>
#include "calc.tab.h"

#define YY_USER_INIT init_yylval()
void init_yylval(void);
int yylex(void);

void init_yylval(void)
{
    mpz_init(yylval.val);
}
%}
%option nounput
%option noyywrap
%%
[ \t]   {}
0|[1-9][0-9]*   { mpz_set_str(yylval.val, yytext, 10); return UINT; }
.|\n    { return yytext[0]; }
<<EOF>> { mpz_clear(yylval.val); return -1; }
%%