ref: 0fdd9b51c7c4ada3a441c3a7baa58be31e24a22c
dir: /calc.y/
%{
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
int yylex(void);
int yyparse(void);
void yyerror(char*);
Biobuf *bf;
%}
%union{
int i;
}
%token<i> NUM
%type<i> expr
%left '+' '-'
%left '*' '/' '%'
%%
input: | input expr '\n' { print("%d\n", $2); }
expr: NUM { $$ = $1; }
| '(' expr ')' { $$ = $2; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
| expr '%' expr { $$ = $1 % $3; }
%%
void
yyerror(char *s)
{
fprint(2, "%s\n", s);
}
int
getnum(int c)
{
char s[64], *p;
for(p=s, *p++=c; isdigit(c=Bgetc(bf));)
if(p < s+sizeof(s)-1)
*p++ = c;
*p = 0;
Bungetc(bf);
return strtol(s, nil, 10);
}
int
yylex(void)
{
int n, c;
do
c = Bgetc(bf);
while(c != '\n' && isspace(c));
if(isdigit(c)){
yylval.i = getnum(c);
return NUM;
}else if(c == 'd'){
n = getnum(Bgetc(bf));
yylval.i = nrand(n != 0 ? n : 1);
return NUM;
}else
return c;
}
void
main(int argc, char **argv)
{
ARGBEGIN{
}ARGEND
if((bf = Bfdopen(0, OREAD)) == nil)
sysfatal("Bfdopen: %r");
yyparse();
}