Yacc/Bison, minimieren Sie die Menge durch Gruppierung von Mathematik -Ops
Frage
Ich schaue auf die Calc -Quelle hier http://epaperpress.com/lexandyacc/
Ich sehe diese Linien 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); }
Gibt es eine Möglichkeit, sie zu gruppieren? Also kann ich stattdessen so etwas wie unten schreiben?
| expr mathOp expr { $$ = opr(mathOp, 2, $1, $3); }
| expr cmpOp expr { $$ = opr(cmpOp, 2, $1, $3); }
Hinweis: Ich benutze Bison.
Lösung
Das Problem bei der Gruppierung wie diese ist, dass Sie die Vorrang vor den Regeln verlieren - Sie haben nur eine Regel, die unterschiedliche Vorrang hat, je nachdem, welcher Mathe es ist, mit dem Bison/yacc nicht umgehen kann. Trotzdem können Sie Ops gleicher Vorrangstufe zusammen gruppieren
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: '*' { $$ = '*'; }
| '/' { $$ = '/'; }
;
Andere Tipps
Sie können es auf 2 Arten tun:
- Definieren Sie bei der Lex-Stufe die Erkennung von Operatoren und geben Sie ein terminales Symbol (in Ihrer Syntaxmathop) mit dem Wert von Operator '+', '-' ...
Verwenden Sie Mathop als nicht terminal, können Sie einen zugeordneten Wert zurückgeben:
mathop: '+' {$$ = '+'; } | '-' {$$ = '-'; } ...
Dann sieht die Nutzung aus (achten Sie auf 2 US -Dollar):
| expr mathOp expr { $$ = opr($2, 2, $1, $3); }
Möglicherweise möchten Sie kompliziertere Mathop definieren, als % %Typ zu verwenden