Originariamente inviato da Matthew82
Avevo provato così:
%left operazione1
%left operazione2
ma non funzionava....
Adesso scrivendo così:
expression: expression operazione1 expression { $$ = ... }
| expression operazione2 expression { $$ = ... }
sembra funzionare. Quindi forse avevi ragione tu. Quale è la giusta risposta???
La risposta giusta è sicuramente quella del manuale.
Scrivendo
expression: expression operazione1 expression { $$ = ... }
| expression operazione2 expression { $$ = ... }
senza specificare la precedenza nella sezione delle dichiarazioni, funziona perchè Yacc/Bison produce un parser di tipo LALR(1) in cui le derivazioni sono di tipo Right-Most.
Quindi viene valutata prima l'espressione più a destra (expression operazione2 expression).
Devi comunque scrivere sia la dichiarazione (precedenza + associatività ) sia la regola grammaticale.
Nell'esempio seguente ho definito due operatori: ~ esegue la sottrazione e # esegue la moltiplicazione. Scrivendo l'espressione 8 ~ 5 # 3, il parser fornisce il risultato corretto, -7.
codice:
%{
#include "symtab.h"
#include <string.h>
#include <stdio.h>
#include "errors.h"
void yyerror(char *s)
{
Error(Current_Line,"%s\n",s);
}
%}
%union {
double dval;
struct symtab *symp;
}
%token <symp> NAME
%token <dval> NUMBER
%left '~'
%left '#'
%nonassoc UMINUS
%type <dval> expression
%%
statement_list: statement '\n'
| statement_list statement '\n'
;
statement: NAME '=' expression { $1->Value = $3; }
| expression { printf("= %g\n", $1); }
;
expression: expression '~' expression { $$ = $1 - $3; }
| expression '#' expression { $$ = $1 * $3; }
| '-' expression %prec UMINUS { $$ = -$2; }
| '(' expression ')' { $$ = $2; }
| NUMBER
| NAME { $$ = $1->Value; }
;
%%
struct symtab * symlook(char *s)
{
char *p;
struct symtab *sp;
for(sp = symtab; sp < &symtab[MAX_SYMBOLS]; sp++)
{
if(sp->VariableName && !strcmp(sp->VariableName, s))
return sp;
if(!sp->VariableName)
{
sp->VariableName = strdup(s);
return sp;
}
}
yyerror("Troppi simboli");
exit(1);
}
Come vedi ho dichiarato precedenza e associatività:
%left '~'
%left '#'
e ho definito le regole grammaticali:
expression: expression '~' expression { $$ = $1 - $3; }
| expression '#' expression { $$ = $1 * $3; }
Fammi sapere e, se hai ancora problemi, posta il codice per intero.
Ciao