Was ist die leistungsstärkste Art von Parser?


28

Als Nebenprojekt schreibe ich eine Sprache mit Python. Ich habe mit einem Flex / Bison-Klon namens Ply angefangen, stoße aber an die Grenzen dessen, was ich mit dieser Art von Grammatik ausdrücken kann, und ich bin nicht daran interessiert, meine Sprache zu zerhacken, weil die Impedanz nicht mit der übereinstimmt das Werkzeug. Daher bin ich nicht abgeneigt, meine eigenen zu schreiben.

Also, was ist die mächtigste Art von Parser? Zitate zu Beiträgen (sowie zu weiteren einführenden Artikeln) sind willkommen.

(Ich weiß, dass 'mächtig' nicht genau definiert ist, aber lassen Sie uns ein wenig locker damit umgehen und sehen, wohin die Antworten gehen.)


1
Abgestimmt: nicht Forschungsniveau.
Warren Schudy

3
@Warren: Ich habe die FAQ gelesen, bevor ich gefragt habe - das scheint keine Voraussetzung zu sein.
Paul Biggar

1
Es gibt zwei FAQs, eine für die allgemeine Site und eine für CStheory. Die CStheory gibt an, dass Fragen, die zum Beispiel durch das Lesen von Wikipedia beantwortet werden können, nicht zum Thema gehören. siehe "Welche Art von Fragen sind zu grundlegend?" in meta.cstheory.stackexchange.com/questions/225/… .
Warren Schudy

1
@Warren: Das ist die FAQ, die ich gelesen habe. Ich hatte Wikipedia gelesen, aber ich hatte das Gefühl, dass dies einen tatsächlichen Einblick erfordert.
Paul Biggar

1
Sie meinen Parser in der Produktion oder theoretische, dh solche, die andere Grammatiktypen als CFG abdecken?
Raphael

Antworten:


33

Eine Grammatik wird normalerweise als kontextfreie Grammatik definiert - eine genaue Definition finden Sie auf der Wikipedia-Seite, aber sie funktioniert genauso wie bei PLY, das auf Bison basiert , das wiederum auf yacc basiert .

Hier steht , dass PLY einen LALR-Parser verwendet . Hierbei handelt es sich im Wesentlichen um einen LR-Parser, bei dem die Nachschlagetabellen komprimiert werden, was möglicherweise zu Analysekonflikten führt und die Aussagekraft einer LR-Grammatik (dh einer kontextfreien Grammatik, die ein LR-Parser analysieren kann) einschränkt. Wenn Sie sich über die Grenzen dieses besonderen Zweiges von Parsern und die der anderen Parser wissen wollen, ein Überblick über alle Arten von Parsing - Techniken (LL, LR und andere) gegeben hier .

Um Ihre Frage zu beantworten: Es gibt Parsing-Algorithmen, mit denen jede kontextfreie Sprache analysiert werden kann, auch wenn die Sprache mehrdeutig ist (dh es gibt mehr als eine Möglichkeit, die Eingabe zu interpretieren):

Der erste derartige Algorithmus war der CYK-Algorithmus , der leider eine Laufzeit von , wobei n die Länge der Eingabezeichenfolge und | ist G | ist die Größe der Grammatik und daher für das Parsen von Sprachen unpraktisch.O(n3|G|)n|G|

Der zweite Algorithmus ist der Earley-Algorithmus . Dieser Algorithmus kann auch jede kontextfreie Grammatik analysieren. Obwohl der Algorithmus Zeit benötigt, um eine mehrdeutige Sprache zu analysieren, benötigt er nur O ( n 2 ) Zeit, um eine eindeutige Sprache zu analysieren. Außerdem funktioniert es für die meisten LR-Grammatiken anscheinend in linearer Zeit und besonders gut für linksrekursive Grammatiken.O(n3)O(n2)

Hier finden Sie eine Abhandlung über die praktische Implementierung (Anpassung) des Earley-Algorithmus. Sie schließen daraus: "Angesichts der Allgemeingültigkeit des Earley-Parsings im Vergleich zu LALR (1) und der Tatsache, dass selbst PEPs ((deren Implementierung des Earley-Algorithmus)) die schlechteste Zeit für a nicht wahrnehmbar wären Benutzer, das ist ein hervorragendes Ergebnis ".

Der letzte Parsertyp ist der GLR-Parser . Dies ist eine verallgemeinerte Version des LR-Parsings, mit der jede kontextfreie Sprache analysiert werden kann.

Eine ausgereifte Implementierung von GLR ist ASF + SDF . Bison kann auch einen GLR-Parser generieren, obwohl seine Implementierung sich geringfügig vom 'Standard'-GLR-Algorithmus unterscheidet. Der Elkhound-Algorithmus ist ein GLR / LALR-Hybridalgorithmus. Wenn möglich, wird LALR und bei Bedarf GLR verwendet, um sowohl schnell als auch in der Lage zu sein, jede Grammatik zu analysieren.

Über die kontextfreien Grammatiken hinaus gibt es kontextsensitive Grammatiken , die jedoch im Allgemeinen schwer zu analysieren sind und nicht so viel Aussagekraft hinzufügen: Sie können mehr daraus machen, aber für die meisten Anwendungen sind die zusätzlichen Verwendungen nicht relevant, es sei denn, Sie analysieren eine natürliche Sprache.

Als letzter Schritt gibt es uneingeschränkte Grammatiken . Zu diesem Zeitpunkt ist die Grammatik Turing-vollständig, sodass man nicht festlegen kann, wie lange es dauern wird, eine bestimmte Sprache zu analysieren, was für die meisten Parsing-Anwendungen unerwünscht ist. Die Extraleistung wird fast nie benötigt. Wenn Sie die gesamte Leistung nutzen möchten, steht Ihnen die Sprachmaschine zur Verfügung.

Schließlich ist die Implementierung eines eigenen Parser-Generators keine triviale Angelegenheit, insbesondere, um eine schnelle Implementierung zu erreichen. Ich persönlich habe gerade meine eigene Version von flex (dem Lexer-Generator) fertiggestellt, und obwohl dies eine Übung für relativ einfache algorithmische Probleme zu sein schien, wurde es ziemlich kompliziert, die richtigen zu finden, insbesondere, als ich versuchte, Unicode zu unterstützen. Ziehen Sie in Betracht, eine bereits vorhandene Implementierung zu verwenden, anstatt Ihre eigene zu schreiben.


1
Hervorragende Antwort !! Irgendwelche Gedanken darüber, wie PEGs passen?
Paul Biggar

2
PEGs sind „anders“ als CFGs: Es gibt CFGs, die keine PEGs sind, und umgekehrt. Ich verweise Sie hier: stackoverflow.com/questions/1857022/… .
Alex ten Brink


1
Tatsächlich erlauben die meisten gängigen Parser-Generatoren (yacc, Antlr, bison) Nicht-CF-Konzepte durch Prädikate oder beliebigen Code, der prüft, ob eine Regel angewendet bzw. angewendet werden kann. Vorrang. Dies kann verwendet werden, um statische Semantik zu implementieren, da die grundlegende Syntax im Wesentlichen kontextfrei bleibt.
Raphael

1
Rekursive Sprachen sind genau die Sprachen, die von ständig stoppenden Turing-Maschinen entschieden werden können. Jede kontextsensitive Sprache ist daher auch rekursiv, aber da kontextsensitive Sprachen in exponentieller Zeit entscheidbar sind, gibt es rekursive Sprachen, die nicht kontextsensitiv sind. Uneingeschränkte Grammatik ist noch leistungsfähiger: Das Problem des Anhaltens kann durch eine uneingeschränkte Grammatik beschrieben werden, ist jedoch keine rekursive Sprache.
Alex ten Brink

15

Eine Veröffentlichung auf der ICFP 2010 in diesem Jahr, Total Parser Combinators , beschreibt eine nachweislich terminierende Parser-Kombinator-Bibliothek und stellt außerdem fest, dass in dieser Bibliothek "Parser-Kombinatoren so aussagekräftig wie möglich sind", da die Terminierung des Parsers garantiert ist. Leider kann ich mich nicht an die Erklärung erinnern, die der Autor für das gegeben hat, was "so ausdrucksvoll wie möglich" bedeutet, aber es scheint auf jeden Fall relevant für Ihre Frage nach "Macht" zu sein.


1
Ich habe ein Auto, das nicht verschmutzt. Tatsächlich bewegt es sich auch nicht. Die Frage ist also: Welche Art von Sprache wird von dieser Bibliothek analysiert? Das heißt natürlich nicht, dass diese Arbeit nicht interessant ist.
Babou

2

Wenn Sie nicht nur kontextfreie Grammatiken zum Parsen von Programmiersprachen verwenden möchten, sondern auch die Polynomzeit verwenden möchten, können Sie Ausdrucksgrammatiken oder Boolesche Grammatiken analysieren. Letztere sind auch in LL- und LR-Varianten verfügbar (siehe hier ). In der formalen Sprachtheorie werden auch die leistungsfähigen, aber in linearer Zeit erkennbaren Church-Rosser-Sprachen untersucht, mir sind jedoch keine implementierten Parser-Generatoren für diese bekannt.

In der Verarbeitung natürlicher Sprache sind die Geschmäcker unterschiedlich, beispielsweise spielt der Umgang mit Mehrdeutigkeiten (auch: inhärente Mehrdeutigkeiten) und der freien Wortreihenfolge eine sehr wichtige Rolle. Hier können Ihnen die Stichwörter " leicht kontextsensitive Sprachen" und " Automaten neu starten" beim Lesen helfen.


1
In Anbetracht der Art und Weise, wie die Frage gestellt wurde, und der Beschwerde, dass CF zu einschränkend ist, ist Ihre Antwort eindeutig die beste. So geht es ...
babou

0

Parser-Generator-Tools:

ANTLR ist sehr gut. Alternativ können Sie sich JavaCC anschauen


Ich bin kein Informatiker (trotz meines Abschlusses;), so dass meine Worte hier leicht wiegen könnten. Ich stimme Sazzad zu - ANTLR ist ein sehr mächtiges Werkzeug. Es ist sehr vollständig und ich habe noch keine Probleme mit dem Parser-Generator (LL (k), wenn ich mich richtig erinnere). Andererseits muss ich noch einen Compiler für eine etwas komplexe Grammatik implementieren ...
Jörgen Sigvardsson

5
Ich denke, Sie verpassen den Punkt der Frage und vielleicht die gesamte Website. Es geht um Parsing-Theorie, nicht um Implementierungen und Tools.
Paul Biggar
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.