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.