reduzieren reduzieren und verschieben reduzieren Fehler in der LALR-Grammatik

7

Ich muss eine Grammatik für Pascal schreiben, und es gibt nur eine Sache, die Probleme verursacht.

Nehmen wir an, wir haben Operatoren (sortiert nach Priorität von niedrig nach hoch):

  1. Postfix^ .
  2. Präfix^ .
  3. [ ], und ., (gleiche Priorität und linker Assoziativ).
  4. Das einzige Terminal idist ein Kleinbuchstabe.

Nehmen wir nun an, ein Ausdruck ist:

  1. Beliebige ID.
  2. Beliebiger Ausdruck mit dem Postfix-^ Operator.
  3. Beliebiger Ausdruck mit dem Präfixoperator^ .
  4. Jeder Ausdruck mit .gefolgt von id.
  5. Jeder Ausdruck mit [und ein anderer Ausdruck und ].

Jetzt möchte ich wissen, wie ich eine LALR-Grammatik ohne Shift-Reduce- und Reduce-Reduce-Konflikte erstellen kann, ODER wenn dies nicht möglich ist, wie kann ich beweisen, dass dies nicht möglich ist.

Einige Beispiele:

good:
a.b.c.d               
a.b^.c
^a.b^
a.b^^[c]^^.d.e        
^^a.b^.d.e^[]

bad:
a.^b.c

Ohne das Präfix ^ist dieses Problem leicht zu lösen, aber das Präfixzeichen bringt mich immer wieder auf den Punkt. Kann jemand helfen? Meine bisherigen Lösungen:

// this works without the prefix but it does not produce a.b^.c which is wrong.
A ::= B | A ^ ;
B ::= C | ^ B ;
C ::= id | C [ A ] | C . id;

Daher dachte ich, dass das Präfix nur vor dem ersten Punkt auftreten kann und zwischen Punkten nur ein Postfix ^und Klammern stehen können. Also habe ich mir Folgendes ausgedacht:

A ::= B | A ^ ;
B ::= C | ^ B ;
C ::= id | C [ A ] |id D;
D ::= id E;
F ::= E | F ^;
E ::= id | F . id;

Dies führt jedoch zu 3 Konflikten.

zidarsk8
quelle
Ich erinnere mich überhaupt nicht an das Präfix ^ aus meinen Pascal-Tagen. Und Konstruktionen mit ^^ definitiv nicht. Pascal wurde sorgfältig so entworfen, dass es durch rekursiven Abstieg analysiert werden kann, und LL (1) ist eine strikte Teilmenge von LR (0).
vonbrand

Antworten:

4

Ich sehe kein Problem mit Ihrer ersten Grammatik und Bison beschwert sich nicht über das Rendering, das ich damit gemacht habe.

Ich (und Bison) sehe einen Konflikt in Ihrer zweiten Grammatik (die nicht dieselbe Sprache beschreibt wie die erste BTW). Nachdem Sie id id idmit einem ausstehenden gesehen haben ^, wissen Sie nicht, ob Ihr letzter idund der letzte ^ein F sein sollten oder ob Sie die drei IDs zusammenhalten sollten, um ein A zu bilden, das mit dem '^' gesammelt wird.


Nach deinem Kommentar bearbeiten:

Eine direkte Wiedergabe Ihrer Regeln:

EXP ::= id | EXP ^ | ^ EXP | EXP . id | EXP [ EXP ]

wird mehrdeutig sein - und daher Konflikte haben -, weil Sie nicht angeben, ob die Präfixversion von ^Vorrang vor den anderen (Postfix-) Operatoren hat. Ich erinnere mich nicht, wie es in Pascal war, aber Sie können beide Effekte mit bekommen

EXP ::= POST | ^ EXP
POST ::= id | POST ^ | POST . id | POST [ EXP ]

und

EXP ::= PRE | EXP ^ | EXP . id | EXP [ EXP ]
PRE ::= id | ^ PRE

Nochmals bearbeiten: eine gemischte Version, die meinem Verständnis dessen entspricht, was Sie im Kommentar fragen (ich finde das weiterhin verwirrend und betrachte die Komplexität der Grammatik - mit zweimal angegebenen Postoperatoren - als Hinweis, dass dies so ist :-))

EXP ::= PRE | POST2
POST2 ::= PRE '^' | POST2 '^' | POST2 '.' id | POST2 '[' EXP ']'
PRE ::= POST | '^' PRE
POST ::= id | POST '.' id | POST '[' EXP ']'
Ein Programmierer
quelle
Die erste Grammatik hat keine Konflikte, ist aber falsch, da sie nicht erzeugt a.b^.c. Ich habe es nur hinzugefügt, um zu zeigen, wo ich angefangen habe.
Zidarsk8
Mit Ihrer Lösung sind zwei Dinge falsch. Erstens, dass es nicht alle guten Beispiele hervorbringt, die ich in meiner Frage aufgelistet habe, wie ab ^ .c, zweitens, dass es die Prioritäten nicht berücksichtigt und daher einen falschen Ausdrucksbaum ergibt.
Zidarsk8
@ zidarsk8, Ableitung von a.b^.caus der ersten Grammatik : EXP -> POST -> POST . id -> POST ^ . id -> POST . id ^ . id -> id . id ^ . id. Können Sie ein Beispiel für einen problematischen Ausdruck geben, der das Prioritätsproblem zeigt?
AProgrammer
Ihre erste Version: postfix ^ hat eine höhere Priorität als der Präfix ^ -Operator (das ist nicht gut). zweite Version: Präfix ^ hat eine höhere Priorität als der Punktoperator (auch nicht gut). Die kombinierten Versionen können nicht ab ^ .c erzeugen. Das Problem mit der Priorität ist dann, wie es analysiert wird. Ab ^ .c sollte ((ab) ^). C ... und nicht (a. (B ^)) sein. C ... und ^ b ^ sollten analysiert werden (^ b) ^. Vielen Dank für Ihren Versuch und Entschuldigung, ich lehne Ihre Lösungen immer wieder ab, aber sie funktionieren nicht.
Zidarsk8