I'm noodling around with bison as I read a book on it, and I'm working on a simple infix calculator where I use the grammar to dictate precedence rather than using %left/%right
and the order of such declarations.
Most bison calculators I've seen have factorial as a function rather than an operator so those examples have not been helpful.
Currently I have:
15 calclist:
16 | calclist expr EOL { printf(" = %d\n", $2); }
17 | calclist EOL { /* nada */ }
18 ;
19 expr:
20 term
21 | expr '+' term { $$ = $1 + $3; }
22 | expr '-' term { $$ = $1 - $3; }
23 ;
24 term:
25 factor
26 | term '*' factor { $$ = $1 * $3; }
27 | term '/' factor { $$ = $1 / $3; }
28 ;
29 factor:
30 '|' factor { $$ = $2 > 0 ? $2 : -$2; }
31 | '-' factor { $$ = 0 - $2; }
32 | '(' expr ')' { $$ = $2; }
33 | '(' expr ')' '!' { $$ = factorial($2); }
34 | NUMBER '!' { $$ = factorial($1); }
35 | NUMBER
36 ;
Lines 33 and 34 seem overly verbose. I felt like the proper way to do this is replacing 33/34 with:
33 | factor '!' { $$ = factorial($1); }
But then I get shift/reduce conflicts with negation/abs value operators, which makes sense when I looked at the calc.output
file generated with bison -v
.
Is there a cleaner way to do this while maintaining the expr/term/factor grammar which defines the operator precedence? Or is my working solution the best I can do given my constraints (self imposed or otherwise).