Infix Calculator in yacc and flex


Calc.yacc

%{
#include "stdio.h"
#include "math.h"
#define YYSTYPE double
YYSTYPE last_value = 0;
extern int yylex(void);
%}
%token NUMBER
%token LAST
%left '+' '-'
%left '*' '/'
%left '^'
%left NEGATIVE
%left COS EXP SIN SQRT TAN
%%list:
| list '\n'
| list expr '\n' { printf("%.8g\n",last_value=$2);
}
;
expr: term { $$ = $1; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
| expr '^' expr { $$ = pow($1,$3); }
| '-' expr %prec NEGATIVE { $$ = - $2; }
| COS term { $$ = cos($2*3.141592654/180); }
| SIN term { $$ = sin($2*3.141592654/180); }
| SQRT term { $$ = sqrt($2); }
| TAN term { $$ = tan($2*3.141592654/180); }
;term: NUMBER { $$ = $1; }
| LAST { $$ = last_value; }
| '(' expr ')' { $$ = $2; }

;
%%
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
int lineno;
char *fname = "-stdin-";
int yyerror(const char *s)
{
fprintf(stderr,"%s(%d):%s\n",fname,lineno,s);
return 0;
}
main()
{
yyparse();
return 0;
}

Calc.flex

%{
#include "stdio.h"
#include "unistd.h"
#include "stdlib.h"
#include "math.h"
#define YYSTYPE double
#include "y.tab.h"

extern int lineno; /* current line number */
extern YYSTYPE yylval; /* value of numeric token */
%}

digit [0-9]
space [ \t]

%%

{space} { ; } /* spaces are ignored */
{digit}+\.?|{digit}*\.{digit}+ {
yylval = strtod(yytext,0);
return NUMBER; }
\*\* { return '^'; }
last { return LAST; }
cos { return COS; }
exp { return EXP; }
sin { return SIN; }
sqrt { return SQRT; }
tan { return TAN; }
pi { yylval = atan(1.0)*4;
return NUMBER; }
e { yylval = exp(1.0);
return NUMBER; }
\n { lineno++; return '\n'; }
. { return yytext[0]; }
%%

How to Compile & Run:
Open Terminal, then

[root@Srijon Desktop]# yacc -d Calc.yacc
[root@Srijon Desktop]# flex Calc.flex
[root@Srijon Desktop]# g++ lex.yy.c y.tab.c -ll
[root@Srijon Desktop]# ./a.out

That’s it. ENJOY!!!!!!!!

Advertisements