Dies ist eine Neuformulierung von Sind Grammatikprogramme? vorher von Vag gefragt und mit vielen Vorschlägen der Kommentatoren.
Inwiefern kann eine Grammatik als Spezifizierung eines Rechenmodells angesehen werden? Nehmen wir zum Beispiel eine einfache kontextfreie Grammatik wie
G ::= '1' -> '0' '+' '1'
'1' -> '1' '+' '0'
'2' -> '2' '+' '0'
'2' -> '1' '+' '1'
'2' -> '0' '+' '2'
'3' -> '3' '+' '0'
'3' -> '2' '+' '1'
'3' -> '1' '+' '2'
'3' -> '1' '+' '2'
Unter der Annahme , dass der Parser nicht zwischen differenziert Terminal und Nicht - End - Symbole , wie ich hier gezeigt habe, dann ist es möglich , einfache Arithmetik für Zahlen bis zu 3 durchzuführen.
Nehmen Sie zum Beispiel die Zeichenfolge
"2 + 0 + 1"
Wenn Sie einen LR (1) -Parser für diesen String ausführen, erhalten Sie den folgenden konkreten Syntaxbaum, in dem das Ergebnis der Berechnung im Stammverzeichnis des Baums gespeichert wird:
'3'
/ | \
/ | \
'2' '+' '1'
/ | \
/ | \
'2' '+' '0'
Wenn wir also eine Grammatik als Programm und einen Parsergenerator als Compiler betrachten , können wir dann die Grammatikspezifikationssprache als Programmiersprache betrachten ?
Könnten wir außerdem Turing-complete-Programme erstellen, indem wir Grammatiken angeben , wie Sie Turing-complete-Programme mit Celullar-Automaten oder dem Lambda-Kalkül erstellen könnten ?
In anderen Worten ist es bekannt , dass im Sinne der Erkennung eine Sprache, reguläre Sprachen entsprechen endliche Automaten , kontextfreie Sprachen entsprechen Automaten nach unten drücken , und kontextsensitiven Sprachen entsprechen begrenzte Automaten linear . Wenn wir jedoch Grammatiken als Rechengeräte betrachten (dh Programme im Sinne des obigen Beispiels), wie klassifizieren wir dann die Rechenstärke jeder Grammatikklasse in der Chomsky-Hierarchie?
- Regelmäßige Grammatiken
- Kontextfreie Grammatiken
- Kontextsensitive Grammatiken
- Uneingeschränkte Grammatik (für rekursiv aufzählbare Sprachen )
Wie wäre es auch mit den weniger bekannten Unterklassen von Grammatiken wie
- Deterministische kontextfreie Grammatiken (auch LR (k) / LL (k) / SLR / LALR usw.)
- Verschachtelte Wortgrammatiken
- Baum neben Grammatiken
- Indizierte Grammatiken
EDIT: Übrigens, das ist ein Trottel zu meiner eigenen Frage, aber ich habe nicht erwähnt, dass ich kein Startsymbol für die Beispielgrammatik angegeben und bei der Notwendigkeit, zwischen Terminals und Nichtterminals zu unterscheiden, von Hand gewinkt habe. Technisch oder traditionell denke ich, dass die Grammatik wahrscheinlich in einer komplizierteren Form wie dieser geschrieben werden müsste (wobei S das Startsymbol und $ das End-of-Stream-Terminal darstellt):
G ::= S -> R0 '$'
S -> R1 '$'
S -> R2 '$'
R0 -> '0'
R0 -> R0 '+' '0'
R1 -> '1'
R1 -> R0 '+' '1'
R1 -> '1' '+' R0
R1 -> R0 '+' '1' '+' R0
R2 -> '2'
R2 -> R0 '+' '2'
R2 -> '2' '+' R0
R2 -> R0 '+' '2' '+' R0
R2 -> R1 '+' '1'
R2 -> R1 '+' '1' '+' R0
... nicht, dass es wirklich etwas ändert, aber ich dachte, ich sollte es erwähnen.
EDIT: Etwas anderes, was mir beim Lesen der Antwort von gasche in den Sinn kam, ist, dass jeder Zweig im Baum in meinem Beispiel eine Teilberechnung darstellt. Wenn Sie jede Produktionsregel als eine Funktion betrachten, bei der die LHS das Ergebnis und die RHS die Argumente darstellt, bestimmt die Struktur der Grammatik, wie Funktionen zusammengesetzt sind.
Mit anderen Worten, der Kontext des Parsers zusammen mit seinem Lookahead-Mechanismus hilft dabei, nicht nur zu bestimmen, welche Funktionen angewendet werden sollen (ein bisschen wie parametrischer Polymorphismus), sondern wie sie zusammengesetzt werden sollten, um neue Funktionen zu bilden.
Zumindest könnte man das für eindeutige CFGs so sehen, für andere Grammatiken ist mir die mentale Gymnastik im Moment ein bisschen zu viel.
Antworten:
Es gibt eine Eins-zu-Eins-Entsprechung zwischen Chomsky-Typ-0-Grammatiken und Turing-Maschinen.
Dies wird in der Programmiersprache Thue ausgenutzt, mit der Sie Turing-vollständige Programme schreiben können, die durch eine anfängliche Zeichenfolge und einen Satz von Regeln zum Umschreiben von Zeichenfolgen (eine Semi-Thue-Grammatik , die einer Grammatik vom Typ 0 entspricht) festgelegt sind.
AKTUALISIEREN:
Abgesehen von esoterischen "Turing Tar-Pit" -Sprachen wie Thue können verschiedene Mehrzwecksprachen verwendet werden, mit denen der Programmierer seine eigene Syntax erweitern kann, um während der Parsing-Kompilierungsphase eine Turing-vollständige Berechnung durchzuführen.
Sprachen in der Lisp- Familie, insbesondere Common Lisp , sind wahrscheinlich die offensichtlichsten Beispiele, aber im Allgemeinen auch Sprachen mit statischer Typprüfung, die nicht immer angehalten werden müssen, wie C ++ mit Vorlagen , Scala und Qi .
quelle
Meine Antwort soll nicht formal, präzise und absolut themenbezogen sein. Ich denke, die Antwort von Marc Hamman ist absolut sicher, aber Ihre Frage hat mich zu einem verwandten Thema gebracht.
Grammatiken können als Sonderfälle deduktiver Systeme betrachtet werden: Die Eingabe ist ein Urteil, und der Analysebaum ist eine Ableitung des Urteils oder ein Beweis dafür, dass das Urteil nach den (grammatischen) Regeln gültig ist.
In diesem Sinne könnte sich Ihre Frage auf den Ansatz eines Teils der Community für Logikprogrammierung / Proof-Suche beziehen (ich denke zum Beispiel an Dale Miller ), der besagt, dass die Proof- Suche im Gegensatz zur klassischen Suche einen rechnerischen Inhalt hat Typ / Beweis Theorie Sicht wo Berechnung Beweis Normalisierung ist .
Bemerkung: Wenn ich meine Antwort noch einmal lese, denke ich, dass die Idee, dass "Syntaxanalyse eine Beweissuche ist", hier etwas weit hergeholt ist. Die Beweisrecherche verläuft vielmehr in die andere Richtung: Man geht von einem gegebenen, recht komplexen Urteil aus und erreicht durch die wiederholte Verwendung von Inferenzregeln, die an der Struktur des Beweises arbeiten, hoffentlich einfachere Axiome, die nicht weiter bewiesen werden müssen. Daher wäre es natürlicher, komplexe Urteile in Grammatik als nicht endständig, Atome als endständig und die Beweissuche als Worterzeugungsproblem oder Nicht-Leertest zu sehen.
quelle
Ich bin mir nicht sicher, ob ich Ihre Frage richtig verstanden habe, aber wenn Sie nach einer Programmiersprache suchen, die auf einer Art String-Umschreibesystem basiert, sind Sie wahrscheinlich an Refal interessiert , das auf dem Markov-Algorithmus- Formalismus (einem Turing- Algorithmus) basiert. vollständiger Formalismus, der auch ein grammatikalisches System zum Umschreiben von Zeichenketten ist).
quelle
S -> A a; S -> B b; A -> 0; B -> 0
. Wenn wir dies durch Umkehren der Regeln programmieren, müssen wir verschiedene Regeln für die Verarbeitung0
zur Laufzeit auswählen , um "0a" oder "0b" zu bewertenS
.(Nur ein paar triviale Überlegungen. Könnte ein Kommentar sein, aber zu lang.)
Was Sie beschreiben, sieht tatsächlich so aus, als wäre es eine ganz natürliche Sicht auf das, was eine Sprache ist (im menschlichen Verständnis von "Sprache", ihrem Zweck) und wie eine Grammatik eine Sprache definiert.
Eine Sprache besteht aus (unendlich vielen) korrekten syntaktischen Formen, die interpretiert werden, um die semantischen Werte zu erhalten .
Wenn die Interpretation berechenbar ist, können die syntaktischen Formen einer Sprache als Programme angesehen werden, die die semantischen Werte berechnen.
Wenn wir annehmen, dass eine Sprache als endliches Gerät implementiert ist, können wir diese endliche Repräsentation einer Sprache als "Grammatik" bezeichnen. Nach diesem Verständnis kümmert sich eine Grammatik um die Syntax, aber auch um die Semantik, dh wie der semantische Wert eines ganzen Ausdrucks aus den Werten seiner Teile berechnet wird (die atomaren Teile und ihre Werte werden in einem "Lexikon" gespeichert). .
Einige Theorien der natürlichen Sprache haben eine solche Form (die Form, die mit den obigen Überlegungen übereinstimmt; sie wurde bereits in der Antwort von @ gasche erwähnt): ein deduktives System , das nach einer Ableitung der Eingabe sucht (gekoppelt mit der Berechnung der Semantik) Wert oder die Bildung des Beweisbegriffs (vgl. Curry-Horward-Korrespondenz). Wenn wir also solche Systeme betrachten und sie als Grammatik betrachten, ist Ihre Frage trivial : Diese Systeme sind genau so konzipiert, dass sie Berechnungen in der von Ihnen beschriebenen Weise ausführen.
(Tatsächlich sehen die echten Compiler für Programmiersprachen eher wie ein System mit Syntax und Semantik aus: Sie transformieren die syntaktische Form eines Programms in eine ausführbare Datei, die die semantische Bedeutung des Programms darstellt, und nicht nur in ein Startsymbol der Grammatik.)
quelle
Nur um hinzuzufügen:
Eine grammatische Sicht der Logikprogrammierung von Pierre Deransart und Jan Maluszynski.
quelle
Was ist mit so etwas wie Peano-Zahlen:
es wird jede Zeichenfolge (Nummer) dieser Form erkennen:
und es sollte eine verschachtelte Struktur zurückgeben, wobei die Tiefe die Zahl ist.
Aber es wird langsam kompliziert, wenn man nur noch sagen will:
Es macht durchaus Sinn, dass es nur wohlgeformte Ints wie dieses erkennt:
Diese Grammatik führt jedoch eine Aufteilung des Analysebaums ein, wenn eine Summe vorhanden ist. Anstatt also einen schönen, einseitig verzweigten Baum zu haben, der direkt einer Zahl zugeordnet ist, haben wir die Struktur des Ausdrucks, der noch ein paar Berechnungen von der tatsächlichen entfernt ist Wert. Es erfolgt also keine Berechnung, sondern nur eine Erkennung. Das Problem ist möglicherweise nicht die Grammatik, sondern der Parser. Man kann stattdessen etwas anderes verwenden, idk ... Ein weiterer Punkt, der in den Sinn kommt, ist die Angemessenheit des Grammatikformalismus, um Berechnung auszudrücken. Wenn Sie das Axiom eines Peano betrachten (in Haskell-ähnlicher Notation):
Die dritte Regel besagt ausdrücklich eine Transformation. Könnte sich jemand vorstellen, in einer kontextfreien Grammatikregel die gleiche Bedeutung zu haben? Und wenn ja, wie?
quelle