Sono costretto a usare% glr-parser?
Domanda
Ho tenuto lontano lo spostamento / riduzione degli errori. Ora finalmente penso di aver incontrato la mia partita.
Int[] a
a[0] = 1
Il problema è int [] è definito come
Type OptSquareBrackets
mentre uno [0] è definito come
Var | Var '[' expr ']'
Var e Type sono entrambi definiti come VAR che è una variabile valida [a-zA-Z] [a-zA-Z0-9_]
. Oltre ad aggiungere un token fittizio (come ** Decl ** Type OptSquareBrackets
) c'è un modo per scrivere questo per non avere un conflitto? Da questa regola ottengo 1 spostamento / riduzione e 1 avviso di riduzione / riduzione.
Soluzione
Potresti definire un nuovo token
VarLBracket [a-zA-Z][a-zA-Z0-9_]*\[
E quindi definire la dichiarazione
Type | VarLBracket ']';
e definire il target di assegnazione come
Var | VarLBracket expr ']';
Altri suggerimenti
Crea una regola Lex con [] poiché [] viene utilizzato solo nella dichiarazione e in qualsiasi altro luogo verrebbe utilizzato [var]
Tecnicamente, questo problema deriva dal tentativo di legare la grammatica a un significato semantico che in realtà non differisce nella sintassi.
ISTM che ti serve solo un singolo costrutto grammaticale che descriva sia i tipi che le espressioni. Fai la distinzione nel codice e non nella grammatica, specialmente se in realtà non c'è una differenza sintattica. Yacc è chiamato un generatore di compilatore ma non è affatto vero. Produce solo parser.
Detto questo, riconoscere []
come simbolo terminale potrebbe essere un modo più semplice per risolvere il problema e andare avanti con le cose. Yacc non è molto bravo nelle grammatiche ambigue e deve prendere le prime decisioni su quale percorso seguire.