web-dev-qa-db-de.com

Was ist der Unterschied zwischen LR (0) und SLR-Analyse?

Ich arbeite an den Konzepten meiner Compiler, aber ich bin ein wenig verwirrt.

Sind SLR- und LR (0) -Parser identisch? Wenn nicht, was ist der Unterschied?

71
Nitish Upreti

Sowohl LR (0) - als auch SLR (1) -Parser sind Bottom-Up-, Richtungs-, Vorhersage-Parser. Das bedeutet, dass

  • Die Parser versuchen, Produktionen in umgekehrter Reihenfolge anzuwenden, um den Eingabesatz wieder auf das Startsymbol zu reduzieren ( bottom-up)
  • Die Parser scannen die Eingabe von links nach rechts ( direktional)
  • Die Parser versuchen vorherzusagen, welche Verringerungen angewendet werden sollen, ohne unbedingt die gesamte Eingabe zu sehen ( Vorhersage)

Sowohl LR (0) als auch SLR (1) sind Verschieben/Reduzieren-Parser , was bedeutet, dass sie die Token des Eingabestreams verarbeiten, indem sie auf einem Stapel abgelegt werden und an jedem Punkt entweder ein Zeichen verschieben , indem es auf den Stapel geschoben wird, oder reduzieren Eine Folge von Terminals und Nichtterminals auf dem Stapel bis zu einem Nichtterminalsymbol. Es kann gezeigt werden, dass jede Grammatik mit einem Shift/Reduce-Parser von unten nach oben analysiert werden kann, dass der Parser jedoch möglicherweise nicht deterministisch ist. Das heißt, der Parser muss möglicherweise "raten", ob eine Verschiebung oder eine Reduzierung angewendet werden soll, und muss möglicherweise zurückverfolgen, um zu erkennen, dass er die falsche Wahl getroffen hat. Unabhängig davon, wie leistungsfähig ein deterministischer Verschiebungs-/Reduzierungsparser ist, den Sie erstellen, kann er niemals alle Grammatiken analysieren.

Wenn ein deterministischer Verschiebungs-/Reduzierungsparser verwendet wird, um eine Grammatik zu analysieren, die nicht verarbeitet werden kann, führt dies zu Verschiebungs-/Reduzierungskonflikten oder Reduzieren/Reduzieren von Konflikten , bei denen der Parser in einen Zustand eintreten kann, in dem er nicht sagen kann, welche Aktion er ausführen soll. In einem Verschiebungs-/Reduzierungskonflikt kann nicht festgestellt werden, ob dem Stapel ein weiteres Symbol hinzugefügt oder die oberen Symbole des Stapels reduziert werden sollen. In einem Reduce/Reduce-Konflikt weiß der Parser, dass die oberen Symbole des Stapels durch ein Nichtterminal ersetzt werden müssen, kann jedoch nicht feststellen, welche Reduktion verwendet werden soll.

Ich entschuldige mich, wenn dies eine langwierige Darstellung ist, aber wir brauchen dies, um den Unterschied zwischen der Analyse von LR (0) und SLR (1) beheben zu können. Ein LR (0) -Parser ist ein Verschiebungs-/Reduzierungs-Parser, der null Lookahead-Token verwendet, um zu bestimmen, welche Aktion ausgeführt werden soll (daher die 0). Dies bedeutet, dass der Parser in jeder Konfiguration des Parsers eine eindeutige Aktion auswählen muss - entweder wird ein bestimmtes Symbol verschoben oder eine bestimmte Reduzierung angewendet. Wenn jemals zwei oder mehr Entscheidungen zu treffen sind, schlägt der Parser fehl und wir sagen, dass die Grammatik nicht LR (0) ist.

Denken Sie daran, dass die beiden möglichen LR-Konflikte verschieben/reduzieren und reduzieren/reduzieren sind. In beiden Fällen gibt es mindestens zwei Aktionen, die der LR (0) -Automat ausführen könnte, und er kann nicht sagen, welche von ihnen er verwenden soll. Da es sich bei mindestens einer der in Konflikt stehenden Aktionen um eine Reduzierung handelt, besteht eine sinnvolle Angriffslinie darin, den Parser vorsichtiger zu machen, wenn er eine bestimmte Reduzierung durchführt. Nehmen wir genauer an, der Parser darf sich das nächste Eingabe-Token ansehen, um zu bestimmen, ob es verschoben oder verkleinert werden soll. Wenn wir dem Parser nur erlauben, zu reduzieren, wenn es "Sinn macht" (für eine Definition von "Sinn macht"), können wir den Konflikt möglicherweise beseitigen, indem der Automat spezifisch auswählt, ob er in a verschiebt oder reduziert bestimmter Schritt.

In SLR (1) ("Simplified LR (1)") darf der Parser einen Lookahead-Token betrachten, wenn er entscheidet, ob er verschoben oder verkleinert werden soll. Insbesondere, wenn der Parser versuchen möchte, etwas von der Form A → w (für Nichtterminal A und String w) zu reduzieren, untersucht er das nächste Eingabe-Token. Wenn dieses Token in einer Ableitung legal nach dem Nichtterminal A erscheinen könnte, wird der Parser reduziert. Ansonsten nicht. Die Intuition hier ist, dass es in einigen Fällen keinen Sinn macht, eine Reduzierung zu versuchen, da es angesichts der Token, die wir bisher gesehen haben, und des bevorstehenden Tokens keine Möglichkeit gibt, dass die Reduzierung jemals korrekt sein könnte.

Der einzige Unterschied zwischen LR (0) und SLR (1) besteht in der zusätzlichen Fähigkeit, bei Konflikten zu entscheiden, welche Maßnahmen ergriffen werden sollen. Aus diesem Grund kann jede Grammatik, die von einem LR (0) -Parser analysiert werden kann, von einem SLR (1) -Parser analysiert werden. SLR (1) -Parser können jedoch eine größere Anzahl von Grammatiken als LR (0) analysieren.

In der Praxis ist SLR (1) jedoch immer noch eine recht schwache Analysemethode. Häufiger werden LALR (1) ("Lookahead LR (1)") - Parser verwendet. Auch sie versuchen Konflikte in einem LR (0) -Parser aufzulösen, aber die Regeln, nach denen sie Konflikte auflösen, sind weitaus präziser als in SLR (1), und folglich ist die Anzahl der Grammatiken LALR (1). als sind SLR (1). Genauer gesagt versuchen SLR (1) -Parser, Konflikte zu lösen, indem sie sich die Struktur der Grammatik ansehen, um weitere Informationen darüber zu erhalten, wann eine Verschiebung und wann eine Reduzierung erforderlich ist. LALR (1) -Parser untersuchen sowohl die Grammatik als auch den LR (0) -Parser, um noch genauere Informationen darüber zu erhalten, wann verschoben und wann reduziert werden muss. Da LALR (1) die Struktur des LR (0) -Parsers untersuchen kann, kann es genauer identifizieren, wenn bestimmte Konflikte falsch sind. Die Linux-Dienstprogramme yacc und bison erzeugen standardmäßig LALR (1) -Parser.

In der Vergangenheit wurden LALR (1) -Parser in der Regel mit einer anderen Methode erstellt, die sich auf den weitaus leistungsstärkeren LR (1) -Parser stützte. Daher wird LALR (1) häufig so beschrieben. Um dies zu verstehen, müssen wir über LR (1) -Parser sprechen. In einem LR (0) -Parser verfolgt der Parser, wo er sich möglicherweise in der Mitte einer Produktion befindet. Sobald festgestellt wurde, dass das Ende einer Produktion erreicht ist, muss versucht werden, diese zu reduzieren. Der Parser ist jedoch möglicherweise nicht in der Lage zu erkennen, ob es sich am Ende einer Produktion und in der Mitte einer anderen befindet, was zu einem Verschiebungs-/Reduzierungskonflikt führt, oder welche von zwei verschiedenen Produktionen das Ende von (einer Reduzierungs-/Reduzierungs-) erreicht hat. Konflikt reduzieren). In LR (0) führt dies sofort zu einem Konflikt und der Parser schlägt fehl. In SLR (1) oder LALR (1) trifft der Parser dann die Entscheidung, basierend auf dem nächsten Lookahead-Token zu verschieben oder zu reduzieren.

In einem LR (1) -Parser verfolgt der Parser zusätzliche Informationen, während er arbeitet. Der Parser verfolgt nicht nur, welche Produktion verwendet wird, sondern verfolgt auch, welche möglichen Token nach Abschluss dieser Produktion angezeigt werden könnten. Da der Parser diese Informationen bei jedem Schritt nachverfolgt und nicht nur, wenn er eine Entscheidung treffen muss, ist der Parser LR (1) wesentlich leistungsfähiger und präziser als jeder der Parser LR (0), SLR (1) oder LALR (1) -Parser, über die wir bisher gesprochen haben. LR (1) ist eine äußerst leistungsfähige Parsing-Technik, und mit etwas kniffliger Mathematik kann gezeigt werden, dass jede Sprache durch eine Verschiebung/deterministisch analysiert werden kann. Parser reduzieren hat eine Grammatik, die mit einem LR (1) -Automaten analysiert werden könnte. (Beachten Sie, dass dies nicht bedeutet, dass alle Grammatiken , die deterministisch analysiert werden können, LR (1) sind, sondern nur, dass eine Sprache deterministisch analysiert werden kann hat etwas LR (1) Grammatik). Diese Leistung hat jedoch einen Preis, und ein generierter LR (1) -Parser benötigt möglicherweise so viele Informationen, dass er in der Praxis möglicherweise nicht verwendet werden kann. Ein LR (1) -Parser für eine echte Programmiersprache benötigt möglicherweise mehrere zehn bis hundert Megabyte an zusätzlichen Informationen, um ordnungsgemäß zu funktionieren. Aus diesem Grund wird LR (1) in der Praxis normalerweise nicht verwendet. Stattdessen werden schwächere Parser wie LALR (1) oder SLR (1) verwendet.

In jüngerer Zeit hat ein neuer Parsing-Algorithmus namens GLR (0) ("Generalized LR (0)") an Popularität gewonnen. Anstatt zu versuchen, die Konflikte zu lösen, die in einem LR (0) -Parser auftreten, versucht der GLR (0) -Parser stattdessen alle möglichen Optionen parallel. Mit einigen cleveren Tricks kann dies für viele Grammatiken sehr effizient ausgeführt werden. Darüber hinaus kann GLR (0) jede kontextfreie Grammatik überhaupt, auch Grammatiken, die nicht von einem LR (k) -Parser für jedes k analysiert werden können. Dies können auch andere Parser (z. B. der Earley-Parser oder ein CYK-Parser), obwohl GLR (0) in der Praxis tendenziell schneller ist.

Wenn Sie mehr erfahren möchten, habe ich in diesem Sommer einen Einführungskurs für Compiler gehalten und knapp zwei Wochen lang über Analysetechniken gesprochen. Wenn Sie eine genauere Einführung in LR (0), SLR (1) und eine Reihe anderer leistungsstarker Analysetechniken erhalten möchten, können Sie sich über meine Vorlesungsfolien und Hausaufgaben zum Thema Analysieren freuen. Alle Kursmaterialien sind verfügbar hier auf meiner persönlichen Seite .

Hoffe das hilft!

224
templatetypedef

Das habe ich gelernt. Normalerweise kann der LR (0) -Parser mehrdeutig sein, d. H. Ein Feld der Tabelle (das Sie zum Erstellen des Parsers ableiten) kann mehrere Werte haben (oder), um es besser auszudrücken: Der Parser führt zu zwei Endzuständen mit derselben Eingabe. Daher wird ein SLR-Parser erstellt, um diese Mehrdeutigkeit zu beseitigen. Um es zu konstruieren, finden Sie alle Produktionen, die zu goto-Zuständen führen, finden Sie die Verfolgung für das Produktionssymbol auf der linken Seite und enthalten nur die goto-Zustände, die in der Verfolgung vorhanden sind. Dies bedeutet, dass Sie keine Produktion einschließen, die mit dem Originalgrammer nicht möglich ist (weil dieser Status nicht im folgenden Satz enthalten ist).

1
Yeswantth