问题
I am looking at the calc source here http://epaperpress.com/lexandyacc/
I see theses lines in calc.y
| expr '+' expr { $$ = opr('+', 2, $1, $3); }
| expr '-' expr { $$ = opr('-', 2, $1, $3); }
| expr '*' expr { $$ = opr('*', 2, $1, $3); }
| expr '/' expr { $$ = opr('/', 2, $1, $3); }
| expr '<' expr { $$ = opr('<', 2, $1, $3); }
| expr '>' expr { $$ = opr('>', 2, $1, $3); }
Is there a way to group them? so i can write something like the below instead?
| expr mathOp expr { $$ = opr(mathOp, 2, $1, $3); }
| expr cmpOp expr { $$ = opr(cmpOp, 2, $1, $3); }
NOTE: I am using bison.
回答1:
The problem with grouping them like that is that you lose the precedences on the rules -- you only have one rule that has different precedence depending on which mathop it is, which bison/yacc cannot handle. That said, you CAN group ops of the same precedence level together
expr: expr mulOp expr { $$ = opr($2, 2, $1, $3); } %prec '*'
| expr addOp expr { $$ = opr($2, 2, $1, $3); } %prec '+'
| expr relOp expr { $$ = opr($2, 2, $1, $3); } %prec '<'
:
mulOp: '*' { $$ = '*'; }
| '/' { $$ = '/'; }
;
回答2:
You can do it in 2 ways:
- At lex stage define recognition of operators and provide terminal symbol (in you syntax mathOp) with value of operator '+', '-' ...
Using mathOp as nonterminal you can return some associated value:
mathOp : '+' { $$ = '+'; } | '-' { $$ = '-'; } ...
Then usage will look like (pay attention to $2):
| expr mathOp expr { $$ = opr($2, 2, $1, $3); }
may be you would like to define more complicated mathOp then use %type
来源:https://stackoverflow.com/questions/1410875/yacc-bison-minimize-amount-by-grouping-math-ops