数式の評価を便利な道具で #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; } %%