Es gibt eine viel einfachere Lösung. Wenn Sie wissen, wie LR Parser arbeiten, dann wissen Sie, dass der Konflikt geschieht hier:
if (expression) statement * else statement
wo der Stern die aktuelle Position des Cursors markiert. Die Frage, die der Parser beantworten muss, lautet: "Soll ich verschieben, oder sollte ich reduzieren?". Normalerweise möchten Sie den else
an den nächsten if
binden, was bedeutet, dass Sie den else
Token jetzt verschieben möchten. Reduzieren würde jetzt bedeuten, dass Sie die else
warten möchten, um an eine "ältere" if
gebunden zu werden.
Jetzt wollen Sie Ihren Parser-Generator zu „sagen“, dass „wenn es eine Verschiebung/reduzieren Konflikt zwischen dem Token "else"
und die Regel ist‚stm -> if (exp) stm‘, dann muss das Token gewinnen“. Um dies zu tun, geben Sie dem Vorrang Ihrer Regel einen Namen (z. B. "then"
) und geben Sie an, dass "then"
weniger Vorrang hat als "else"
. Etwas wie:
// Precedences go increasing, so "then" < "else".
%nonassoc "then"
%nonassoc "else"
%%
stm: "if" "(" exp ")" stm %prec "then"
| "if" "(" exp ")" stm "else" stm
mit Bisonsyntax.
Eigentlich meine Lieblingsantwort ist sogar "then"
und "else"
die gleiche Priorität geben. Wenn die Vorbedingungen gleich sind, um die Verbindung zwischen dem Token, das verschoben werden soll, und der Regel, die reduziert werden soll, zu durchbrechen, wird Bison/Yacc auf Assoziativität schauen. Hier wollen Sie mit der rechten Assoziativität zu fördern, um zu sprechen (genauer gesagt, wollen Sie „shift“ fördern), so:
%right "then" "else" // Same precedence, but "shift" wins.
genügt.
Für zukünftige Personen, [diese Seite] (http://www.tldp.org/HOWTO/Lex-YACC-HOWTO-7. html) half mir durch ein ähnliches Problem. Übergeben Sie auch die Switches '--debug' und' --verbose' an bison und sehen Sie sich die generierten Dateien an. Nicht alle Informationen werden standardmäßig ausgedruckt. –