Bin ich gezwungen% glr-Parser zu verwenden?
Frage
Ich habe die Verschiebung wurde zu halten / reduzieren Fehler weg. Nun endlich ich glaube, ich mein Spiel traf.
Int[] a
a[0] = 1
Das Problem int [] als
definiertType OptSquareBrackets
, während ein [0] ist definiert als
Var | Var '[' expr ']'
Var und Typ beide als VAR definiert, die jede gültige Variable [a-zA-Z][a-zA-Z0-9_]
ist. Neben der Dummy-Token hinzugefügt (wie **Decl** Type OptSquareBrackets
statt) gibt es eine Möglichkeit, dies zu schreiben, um keinen Konflikt hat? Aus dieser einer Regel bekomme ich 1 Schiebe- / reduzieren und 1 verringern / verringern Warnung.
Lösung
Könnten Sie ein neues Token definieren
VarLBracket [a-zA-Z][a-zA-Z0-9_]*\[
Und deshalb definiert Deklaration
Type | VarLBracket ']';
und Zuweisungsziel als
definierenVar | VarLBracket expr ']';
Andere Tipps
Erstellen Sie eine Lex Regel mit [], da [] nur in Deklaration verwendet wird und überall sonst verwenden würde [var]
Technisch dieses Problem ergibt sich aus versuchen, die Grammatik auf eine semantische Bedeutung zu binden, der nicht wirklich in der Syntax unterscheiden.
ISTM, dass Sie nur eine einzige Grammatik Konstrukt müssen, die beide Typen und Ausdrücke beschreibt. Machen Sie den Unterschied im Code und nicht in der Grammatik, vor allem, wenn es nicht wirklich ein syntaktischer Unterschied. Yacc ist ein Compiler-Generator genannt, aber es ist kein bisschen wahr. Es macht einfach Parser.
Having said that, []
als Terminal-Symbol erkennen könnte ein einfacher Weg, das Problem zu beheben und mit den Dingen auszukommen. Yacc ist nicht sehr gut bei mehrdeutigen Grammatiken und es muss früh Entscheidungen treffen, auf dem Weg zu folgen.