Verwenden moderne Sprachen immer noch Parser-Generatoren?

38

Ich war die Erforschung über die gcc - Compiler - Suite auf wikipedia hier , wenn dies kam:

GCC begann mit der Verwendung von LALR-Parsern, die mit Bison generiert wurden, wechselte jedoch allmählich zu handgeschriebenen rekursiven Parsern. Für C ++ im Jahr 2004 und für C und Objective-C im Jahr 2006. Derzeit verwenden alle Frontends handgeschriebene Parser mit rekursiver Herkunft

Anhand dieses letzten Satzes (und soweit ich Wikipedia vertraue) kann ich definitiv sagen, dass "C (gcc), C ++ (g ++), Objective-C, Objective-C ++, Fortran (gfortran), Java (gcj), Ada (GNAT), Go (gccgo), Pascal (gpc), ... Mercury, Modula-2, Modula-3, PL / I, D (gdc) und VHDL (ghdl) "sind alle Frontends, die nicht Verwenden Sie länger einen Parser-Generator. Das heißt, sie alle verwenden handgeschriebene Parser.

Meine Frage ist dann, ist diese Praxis allgegenwärtig? Insbesondere suche ich nach genauen Antworten auf die Frage "Hat die Standard- / offizielle Implementierung von x einen handgeschriebenen Parser" für x in [Python, Swift, Ruby, Java, Scala, ML, Haskell]? (Informationen in anderen Sprachen sind hier auch willkommen.) Ich bin mir sicher, dass ich diese nach langem Graben selbst finden kann. Aber ich bin mir auch sicher, dass dies von der Community leicht zu beantworten ist. Vielen Dank!

Eatonphil
quelle
3
Datenpunkt: CPython verfügt über einen selbst gebrauten LALR-Parser-Generator (pgen). Ich weiß nichts über den Rest.
8
Datenpunkt: Ghc (haskell) verwendet ebenso wie OCaml einen LALR-Parser-Generator (happy).
Twan van Laarhoven
1
Sollte "Moderne Hochleistungs-Compiler ausführen ..." oder ähnlich sein, da die Sprache die Spezifikation und nicht die Implementierung ist, während der Compiler entweder einen maschinengenerierten Parser verwendet oder nicht.
DMCKEE
@dmckee, ja du bist richtig. Die Benennung wird jedoch immer kürzer. Fühlen Sie sich frei, es zu bearbeiten, wenn Sie kreativer sind als ich!
Eatonphil
In Bezug auf ML: MLton verwendet einen Parser-Generator, der spezifisch für ML ist. Ich bin mir zu 90% sicher, dass SML / NJ dies auch tut, obwohl ich damit weniger vertraut bin. Vielleicht möchten Sie das als "handgeschrieben" bezeichnen oder auch nicht.
Patrick Collins

Antworten:

34

AFAIK, GCC verwenden handgeschriebene Parser insbesondere, um die syntaktische Fehlerdiagnose zu verbessern (dh menschliche aussagekräftige Meldungen zu Syntaxfehlern zu geben).

Bei der Parsing-Theorie (und den von ihr abgeleiteten Parsing-Generatoren) geht es hauptsächlich darum, eine korrekte Eingabephrase zu erkennen und zu analysieren . Wir erwarten jedoch von Compilern, dass sie eine aussagekräftige Fehlermeldung ausgeben (und den Rest der Eingabe nach dem syntaktischen Fehler sinnvoll analysieren können), wenn eine falsche Eingabe vorliegt.

Auch alte Legacy-Sprachen wie C11 oder C ++ 11 (die konzeptionell alt sind, auch wenn ihre letzte Revision erst drei Jahre alt ist) sind überhaupt nicht kontextfrei. Der Umgang mit diesem Zusammenhang ist in Grammatiken für Parsergeneratoren (zB Bisons oder sogar Menhirs ) langweilig schwierig.

Basile Starynkevitch
quelle
2
Concur. Gute Wiederherstellung nach Parsing-Fehlern (wenn Sie nicht gleich beim ersten Fehler aufhören möchten, a la the old Borland Pascal) und die Erstellung qualitativ hochwertiger Fehlermeldungen (einschließlich Hinweisen und Lösungsvorschlägen, wie sie von Menschen gewünscht werden) gehören zum eigentlichen Kontext heuristische Aufgaben. Sie können etwas oberhalb der Leistung des Parsergenerators durchgeführt werden, aber es ist eine Schande.
Jonathan Eunice
2
Dealing with that context sensitiveness in grammars for parser generators is boringly difficult. Es ist auch mehr oder weniger unmöglich, da diese Tools kontextfreie Parser generieren. Der richtige Ort, um zu überprüfen, ob alle kontextsensitiven Einschränkungen vorhanden sind, ist, nachdem Sie den Analysebaum generiert haben, wenn Sie solche Tools verwenden.
Dtech
7

Parser-Generatoren und Parser-Engines sind recht allgemein. Der Vorteil der Allgemeinheit besteht darin, dass das schnelle Erstellen und Funktionieren eines genauen Parsers im Gesamtschema einfach ist.

Die Parser-Engine selbst leidet an der Leistungsfront aufgrund ihrer Allgemeinheit. Jeder handgeschriebene Code ist immer deutlich schneller als die tabellengesteuerten Parser-Engines.

Der zweite Bereich, in dem Parser-Generatoren / Engines Schwierigkeiten haben, ist, dass alle realen Programmiersprachen kontextsensitiv sind, oft auf subtile Weise. LR-Sprachen sind kontextfrei, was bedeutet, dass es viele Feinheiten in Bezug auf Positionierung und Umgebung gibt, die in der Syntax nicht richtig vermittelt werden können. Mit Attributen versehene Grammatiker versuchen, grundlegende Sprachregeln wie "Vor Verwendung deklarieren" usw. zu behandeln. Die Verknüpfung dieser Kontextsensitivität mit handgeschriebenem Code ist unkompliziert.

BobDalgleish
quelle
15
Zitat für den Leistungsanspruch bitte? Tabellengesteuert zu sein kann eine signifikante Leistungsoptimierung sein und Generatoren haben Zugriff auf Algorithmen, die sehr effizient sind, aber praktisch nie von Hand implementiert werden (gerade weil sie ein undurchdringliches Durcheinander von Tabellen und magischen Zahlen sind).
2
Und zum zweiten Bereich: Viele, viele der wichtigsten realen Programmiersprachen sind in keiner Weise kontextsensitiv (Sie müssten nach der Typprüfung auf den Satz aller gültigen Programme verweisen und so weiter, was niemals eine handgeschriebene oder eine handgeschriebene ist generierter Parser versucht zu analysieren). Es ist wahr, dass handgeschriebene Parser flexibler sind, und dies ist für einige Sprachen nützlich, aber vor allem im Bereich der Fehlerbehebung und Berichterstellung, der Inkrementalität usw. - Parsergeneratoren werden aufgrund der Erkennungsleistung (unabhängig davon, ob Sie dies möchten) selten gemieden Eine solche Grammatik schreiben zu wollen ist eine andere Geschichte). -1
Wenn Sie beim Parsen Symboltabelleninformationen verwenden, können Sie diese auch als kontextsensitiv bezeichnen. Zugeschriebene Grammatiken sind definitiv nicht kontextfrei, obwohl ich nicht denke, dass sie vollständig kontextsensitiv sind. Ihre anderen Punkte zur Fehlerbehebung und Berichterstellung sind gut aufgenommen.
BobDalgleish
1
C und C ++ benötigen beim Parsen Symboltabelleninformationen (oder akzeptieren einen weitaus weniger spezifischen Analysebaum, bei dem beispielsweise zwischen Ausdrucksanweisungen und Variablendeklarationen nicht unterschieden wird). Aber daran habe ich nicht gedacht. Sprachen wie Java, Lisps, JavaScript, Ruby, Python, Go, Rust, Scala, Swift, Haskell (und wahrscheinlich noch einige andere, vielleicht auch C # und ML?) Benötigen keine solchen Informationen, um die Art von AST zu erstellen, die Sie möchten will sowieso. Viele von ihnen haben LL (1) -Grammatiken oder sogar LALR-Grammatiken.
1
Zitat für alle realen Sprachen sind bitte kontextsensitiv?
PSR