Warum habe ich eine Verschiebung verringern / Konflikte auf dem ‚)‘ und nicht ‚(‘?
-
11-09-2019 - |
Frage
Ich habe Syntax wie
%(var)
und
%var
und (Var)
Meine Regeln sind so etwas wie
optExpr:
| '%''('CommaLoop')'
| '%' CommaLoop
CommaLoop:
val | CommaLoop',' val
Expr:
MoreRules
| '(' val ')'
Das Problem ist, es scheint nicht möglich zu sein, gehört zu sagen, ob) %(CommaLoop)
oder % (val)
aber es beschwert sich über die) anstelle des (. Was zum Teufel? Sollte es nicht auf (
beschweren? Und wie soll ich den Fehler beheben? ich denke, machen %(
ein Token ist eine gute Lösung, aber ich möchte sicher sein, warum $(
einen Fehler ist nicht vor dies zu tun.
Lösung
Dies ist auf die Art und Weise LR-Parsing funktioniert. LR-Parsing ist effektiv von unten nach oben, zusammen gruppiert Token nach der RHS Ihrer Grammatikregeln, und sie mit der LHS zu ersetzen. Wenn der Parser ‚verschiebt‘, bringt es ein Token auf dem Stapel, ist aber nicht wirklich eine Regel entspricht noch. Stattdessen verfolgen sie teilweise Regeln über den aktuellen Stand angepasst. Wenn es zu einem Zustand erhält, die das Ende der Regel entspricht, kann es zu reduzieren, um die Symbole für die RHS vom Stapel knallte und ein einzelnes Symbol bezeichnet die LHS zurückzuzudrängen. Also, wenn es Konflikte gibt, zeigen sie nicht, bis der Parser zu Ende einiger Regel bekommt und nicht entscheiden kann, ob zu reduzieren (oder was zu reduzieren).
In Ihrem Beispiel, nachdem er % ( val , das ist, was auf dem Stapel ist ( oben ist auf der rechten Seite hier) Wenn der Look-Ahead ist ) , kann es nicht entscheiden, ob sie die val Pop sollte und über die Regel CommaLoop reduzieren. val oder wenn es sollte verschiebt die ) , so dass es dann 3 Dinge, Pop und reduziert mit der Regel Expr: '(' val ')
Ich gehe davon aus, dass hier einige zusätzliche Regeln haben wie CommaLoop. Expr , sonst wird Ihre Grammatik passt nicht wirklich etwas und Bison / yacc wird über nicht verwendete Nicht-Terminals beschweren
Andere Tipps
Im Moment Ihre Erklärung und Ihre Grammatik scheinen nicht zu passen. In Ihrer Erklärung, zeigen Sie alle drei Sätze als mit ‚var‘, aber Ihre Grammatik zeigt die, die mit ‚%‘ beginnen als eine durch Kommata getrennte Liste ermöglicht, während die man ohne nur eine einzige ‚val‘ erlaubt.
Im Moment werde ich davon ausgehen, alle drei sollten eine durch Kommata getrennte Liste ermöglichen. In diesem Fall würde ich die Grammatik mehr wie dieser Faktor:
optExpr: '%' aList
aList: CommaLoop
| parenList
parenList: '(' CommaLoop ')'
CommaLoop:
| val
| CommaLoop ',' val
Expr: MoreRules
| parenList
Ich habe optExpr und Expr geändert, so kann weder eine leere Sequenz übereinstimmen - meine Vermutung ist, dass Sie wahrscheinlich nicht, dass für den Anfang der Absicht haben. Ich habe diese aus genug fleshed es durch byacc zu laufen; es erzeugt keine Warnungen oder Fehler.