Perché ho un turno di ridurre / conflitto sulla ')' e non '('?
-
11-09-2019 - |
Domanda
Ho sintassi del tipo
%(var)
e
%var
e (Var)
Le mie regole sono qualcosa come
optExpr:
| '%''('CommaLoop')'
| '%' CommaLoop
CommaLoop:
val | CommaLoop',' val
Expr:
MoreRules
| '(' val ')'
Il problema è che pretende molto sembra essere in grado di dire se) appartiene alla %(CommaLoop)
o % (val)
ma lamenta il) al posto della (. Che diamine? Shouldnt si lamentano su (
? E come devo correggere l'errore? Credo che facendo %(
un token è una buona soluzione, ma voglio essere sicuro perché $(
è neanche un errore prima di fare questo.
Soluzione
Ciò è dovuto al modo in cui le opere LR parsing. LR analisi è effettivamente basso verso l'alto, raggruppando gettoni in base al RHS delle regole grammaticali, e la loro sostituzione con l'LHS. Quando il parser 'sposta', mette un gettone sullo stack, ma in realtà non corrisponde a una regola ancora. Invece, che riproduce parzialmente regole abbinato con lo stato attuale. Quando si arriva ad uno stato che corrisponde alla fine della regola, può ridurre, spuntando i simboli per la RHS dallo stack e spingendo indietro un unico simbolo che denota l'LHS. Quindi, se ci sono conflitti, non mostrano fino a quando il parser arriva alla fine di qualche regola e non può decidere se ridurre (o quello che per ridurre).
Nel tuo esempio, dopo aver visto % ( val , che è ciò che sarà sullo stack ( superiore è sul lato destro qui) Quando il lookahead è ) , non può decidere se dovrebbe pop val e ridurre tramite la regola CommaLoop:. val , o se dovesse spostare la ) in modo che possa poi pop 3 cose e ridurre con la regola Expr: '(' val ')'
Sto assumendo qui che si dispone di alcune regole aggiuntive come CommaLoop:. Expr , altrimenti la tua grammatica non corrisponde in realtà nulla e bisonte / yacc si lamentano non-terminali inutilizzati
Altri suggerimenti
In questo momento, la tua spiegazione e la tua grammatica non sembrano corrispondere. Nella tua spiegazione, si mostrano tutte e tre le frasi come avere 'var', ma la grammatica mostra quelli che iniziano con '%' a permettere ad un elenco separato da virgole, mentre quello senza consente solo un singolo 'val'.
Per il momento, darò per scontato tutti e tre dovrebbero consentire a un elenco separato da virgole. In questo caso, mi piacerebbe fattore la grammatica più simile a questo:
optExpr: '%' aList
aList: CommaLoop
| parenList
parenList: '(' CommaLoop ')'
CommaLoop:
| val
| CommaLoop ',' val
Expr: MoreRules
| parenList
Ho cambiato optExpr e Espr così nessuno dei due può abbinare una sequenza vuota - la mia ipotesi è che probabilmente non intendeva che per cominciare. Ho polpa questo fuori sufficiente per eseguire attraverso byacc; produce nessun avviso o errori.