Yacc / Bison, minimiza la cantidad al agrupar operaciones matemáticas
Pregunta
Estoy viendo la fuente de cálculo aquí http://epaperpress.com/lexandyacc/
Veo estas líneas en 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); }
¿Hay alguna manera de agruparlos? así que puedo escribir algo como el siguiente en su lugar?
| expr mathOp expr { $ = opr(mathOp, 2, $1, $3); }
| expr cmpOp expr { $ = opr(cmpOp, 2, $1, $3); }
NOTA: Estoy usando bisonte.
Solución
El problema con agruparlos de esta manera es que se pierden las precedencias en las reglas; solo tiene una regla que tiene una precedencia diferente dependiendo de qué mathop es, que bison / yacc no puede manejar. Dicho esto, PUEDES agrupar operaciones del mismo nivel de precedencia juntas
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: '*' { $ = '*'; }
| '/' { $ = '/'; }
;
Otros consejos
Puedes hacerlo de 2 maneras:
- En la etapa lex, defina el reconocimiento de los operadores y proporcione un símbolo de terminal (en su sintaxis mathOp) con el valor del operador '+', '-' ...
-
Usando mathOp como no terminal, puede devolver algún valor asociado:
mathOp: '+' {$$ = '+'; } | '-' {$$ = '-'; } ...
Entonces el uso se verá como (preste atención a $ 2):
| expr mathOp expr { $ = opr($2, 2, $1, $3); }
puede ser que te gustaría definir mathOp más complicado y luego usar% type