Yacc / Bison, minimizza la quantità raggruppando le operazioni matematiche

StackOverflow https://stackoverflow.com/questions/1410875

  •  05-07-2019
  •  | 
  •  

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.

È stato utile?

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top