Learning Bison and Flex: The calculator

Published 2016-08-20 18:28:25

Hello everynyan,

I’m learning how Bison and Flex work with an O’Reilly book and there can be found an example on how to build a calculator (which has an error on the code, probably there are more in the book, that’s why it has that kind of critics, but it works.).

I ended up making an extension on it just to test my forgotten grammar skills. The code is the following:

calc-tokenizer.l (Flex)

/* recognize tokens for the calculator and print them out */

%{
#include "calc-parser.tab.h"
%}

%%
"+" 	{ return ADD; }
"-" 	{ return SUB; }
"*" 	{ return MUL; }
"/" 	{ return DIV; }
"|" 	{ return ABS; }
"("		{ return OPPAR; }
")"		{ return CLPAR; }
[0-9]+ 	{ yylval = atoi(yytext); printf("Number %i\n", yylval); return NUMBER; }
\n 		{ return EOL; }
[ \t] 	{ /* ignore whitespace */ }
. 		{ printf("Mystery character %c\n", *yytext); }
%%

calc-parser.y (Bison)

{
#include
%}

/* declare tokens */
%token NUMBER
%token ADD SUB MUL DIV ABS
%token OPPAR CLPAR
%token EOL

%%

calclist:
| calclist exp EOL { printf("= %d\n",$2); } //EOL is end of an expression
;

exp: factor {$$ = $1;}
| exp ADD factor { $$ = $1 + $3;}
| exp SUB factor { $$ = $1 - $3;}
;

factor: term {$$ = $1;}
| factor MUL term { $$ = $1 * $3; }
| factor DIV term { $$ = $1 / $3; }
;

term: NUMBER {$$ = $1;}
| OPPAR exp CLPAR { $$ = $2; }
| SUB term { $$ = -$2; }
| ABS term ABS { $$ = $2 >= 0? $2 : - $2; }
;
%%

main(int argc, char **argv) {
yyparse();
}

yyerror(char *s) {
fprintf(stderr, "error: %s\n", s);
}

In this case my only additions (aside from the fix on the printf in calclist [$2 was set as $1 originally]) are the parenthesis handling, the unary minus operator (In order to have, for example, -2) and a fix on absolute value (originally |Number, now |Number|). I have set parenthesis handling inside of term as it need to be priorized over the rest of operators.