Yacc / Bison, minimizza la quantità raggruppando le operazioni matematiche
Domanda
Sto osservando la fonte calc qui http://epaperpress.com/lexandyacc/
Vedo queste righe 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); }
C'è un modo per raggrupparli? quindi posso scrivere qualcosa di simile al seguente?
| expr mathOp expr { $ = opr(mathOp, 2, $1, $3); }
| expr cmpOp expr { $ = opr(cmpOp, 2, $1, $3); }
NOTA: sto usando il bisonte.
Soluzione
Il problema di raggrupparli in questo modo è che perdi le precedenti sulle regole - hai solo una regola che ha una precedenza diversa a seconda di quale matematica sia, che bisonte / yacc non può gestire. Detto questo, PUOI raggruppare le operazioni dello stesso livello di precedenza insieme
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: '*' { $ = '*'; }
| '/' { $ = '/'; }
;
Altri suggerimenti
Puoi farlo in 2 modi:
- Nella fase lex definisci il riconoscimento degli operatori e fornisci il simbolo del terminale (nella tua sintassi mathOp) con il valore dell'operatore '+', '-' ...
-
Usando mathOp come non terminale puoi restituire un valore associato:
mathOp: '+' {$$ = '+'; } | '-' {$$ = '-'; } ...
Quindi l'utilizzo sarà simile (prestare attenzione a $ 2):
| expr mathOp expr { $ = opr($2, 2, $1, $3); }
potresti voler definire mathOp più complicato quindi usare% type