C'è una soluzione molto più semplice. Se sai come funzionano i parser LR, poi si sa che il conflitto accade qui:
if (expression) statement * else statement
dove la stella indica la posizione corrente del cursore. La domanda a cui deve rispondere il parser è "dovrei cambiare, o dovrei ridurre". Di solito, si desidera associare lo else
allo if
più vicino, il che significa che si desidera spostare il token else
ora. Ridurre ora significherebbe che si desidera che else
attenda di essere associato a un "vecchio" if
.
Ora si vuole "dire" al proprio generatore di parser che "quando c'è uno spostamento/riduzione del conflitto tra il token "else"
e la regola" stm -> if (exp) stm ", allora il token deve vincere". Per fare ciò, "dai un nome" alla precedenza della regola (ad es. "then"
) e specifica che "then"
ha meno precedenza di "else"
. Qualcosa del tipo:
// Precedences go increasing, so "then" < "else".
%nonassoc "then"
%nonassoc "else"
%%
stm: "if" "(" exp ")" stm %prec "then"
| "if" "(" exp ")" stm "else" stm
utilizzando la sintassi Bison.
In realtà, la mia risposta preferita è anche dare "then"
e "else"
la stessa precedenza. Quando le precedenze sono uguali, per spezzare il legame tra il token che vuole essere spostato e la regola che vuole essere ridotta, Bison/Yacc esaminerà l'associatività. Qui, si vuole promuovere il tasto destro del associatività per così dire (più esattamente, si vuole promuovere "shift"), in modo da:
%right "then" "else" // Same precedence, but "shift" wins.
sarà sufficiente.
Per gli individui futuri, [questa pagina] (http://www.tldp.org/HOWTO/Lex-YACC-HOWTO-7. html) mi ha aiutato a risolvere un problema simile. Inoltre, passa le opzioni '--debug' e' --verbose' a bison e guarda i file generati. Non tutte le informazioni vengono stampate per standard. –