Ich bin ein Neuling zum Parsen und möchte einen Clojure-Code analysieren. Ich hoffe, dass jemand ein Beispiel dafür liefern kann, wie Clojure-Code instpariert werden kann. Ich muss nur Zahlen, Symbole, Schlüsselwörter, Sexs, Vektoren und Leerzeichen machen.
Einige Beispiele, die ich analysieren möchte:
%Vor%Nun, es gibt zwei Teile zu Ihrer Frage. Der erste Teil analysiert den Ausdruck
%Vor%Der zweite Teil wandelt die Ausgabe in das gewünschte Ergebnis um. Um ein gutes Verständnis dieser Prinzipien zu bekommen, empfehle ich Udacitys Kurs Programmiersprachen. Carin Meier's blog post ist auch sehr hilfreich.
Der beste Weg zu verstehen, wie der Parser funktioniert, ist, ihn in kleinere Teile aufzuteilen. Also werden wir zuerst einige Parserregeln untersuchen, und im zweiten Teil werden wir unsere Sexs bauen.
Ein einfaches Beispiel
Sie müssen zuerst eine Grammatik schreiben, die instparse erklärt, wie der gegebene Ausdruck analysiert wird. Wir beginnen mit der Analyse der Nummer %code% :
%Vor%sexp beschreibt die höchste Grammatik für die Sexupression. Unsere Grammatik besagt, dass der Sexp nur eine Nummer haben kann. Die nächste Zeile besagt, dass die Zahl eine beliebige Zahl von 0-9 sein kann, und die %code% ist ähnlich der regex %code% , was bedeutet, dass eine Zahl beliebig oft wiederholt werden muss. Wenn wir unseren Parser ausführen, erhalten wir den folgenden Syntaxbaum:
%Vor%Ingorgende Klammer
Wir können bestimmte Werte ignorieren, indem wir unserer Grammatik spitze Klammern %code% hinzufügen. Wenn wir also %code% einfach als %code% analysieren wollen, können wir unsere Grammatik wie folgt korrigieren:
%Vor%und wenn wir den Parser erneut ausführen, ignoriert er die linke und rechte Klammer:
%Vor%Dies wird hilfreich sein, wenn wir unten die Grammatik für sexp schreiben.
Leerzeichen hinzufügen
Jetzt passiert, wenn wir Leerzeichen hinzufügen und %code% ausführen? Nun, wir bekommen einen Fehler:
%Vor%Das liegt daran, dass wir den Begriff des Raums in unserer Grammatik nicht definiert haben! So können wir Leerzeichen hinzufügen:
%Vor%Auch hier ist %code% ähnlich wie regex %code% und bedeutet null oder mehr als ein Auftreten eines Leerzeichens. Das bedeutet, dass die folgenden Beispiele alle das gleiche Ergebnis liefern:
%Vor%Aufbau der Sexp
Wir werden langsam unsere Grammatik von Grund auf aufbauen. Es könnte nützlich sein, sich das Endprodukt hier anzuschauen, nur um einen Überblick zu geben, wohin wir gehen.
Also, ein Sexp enthält mehr als nur Zahlen, wie durch unsere einfache Grammatik definiert. Eine Ansicht auf hoher Ebene, die wir von sexp haben können, besteht darin, sie als eine Operation zwischen zwei Klammern zu betrachten. Also grundsätzlich als %code% . Wir können dies direkt in unsere Grammatik schreiben.
%Vor%Wie oben erwähnt, geben die spitzen Klammern %code% an, diese Werte zu ignorieren, wenn sie den Parse-Baum erstellen. Was ist eine Operation? Nun, eine Operation besteht aus einem Operator wie %code% und einigen Argumenten wie den Zahlen %code% und %code% . So können wir sagen unsere Grammatik schreiben als:
%Vor%Wir haben nur einen möglichen Operator angegeben, %code% , um die Dinge einfach zu halten. Wir haben auch die Zahlengrammatikregel aus dem obigen einfachen Beispiel eingefügt. Unsere Grammatik ist jedoch sehr begrenzt. Der einzige gültige Sex, den es analysieren kann, ist %code% . Das liegt daran, dass wir das Konzept der Leerzeichen nicht berücksichtigt haben und dass Argumente nur eine Zahl haben dürfen. In diesem Schritt werden wir zwei Dinge tun. Wir fügen Leerzeichen hinzu und wir geben an, dass Argumente mehr als eine Zahl haben können.
%Vor%Wir haben %code% hinzugefügt, indem wir die Raumgrammatikregel verwendet haben, die wir im einfachen Beispiel definiert haben. Wir haben eine neue %code% erstellt, die als %code% und eine %code% definiert ist, und die %code% zu snumber hinzugefügt, um anzugeben, dass sie einmal vorkommen muss, aber beliebig oft wiederholt werden kann. So können wir unseren Parser so ausführen:
%Vor%Wir können unsere Grammatik robuster machen, indem wir %code% reference wieder auf %code% setzen. So können wir Sex in unserem Sex haben! Wir können dies tun, indem wir %code% erstellen, die% %code% zu %code% hinzufügt und dann %code% zu %code% hinzufügt.
%Vor%Jetzt können wir
ausführen %Vor%Transformationen
Dieser Schritt kann mit einer beliebigen Anzahl von Werkzeugen durchgeführt werden, die auf Bäumen funktionieren, wie z. B. Animationen, Zipper, Match und Tree-Seq. InstaParse enthält jedoch auch eine eigene nützliche Funktion namens %code% . Wir können unsere Transformationen erstellen, indem wir die Schlüssel in unserem Syntaxbaum durch die gültigen Clojure-Funktionen ersetzen. Zum Beispiel wird %code% zu %code% , um unsere Strings in gültige Zahlen umzuwandeln, %code% wird zu %code% , um unsere Argumente zu erstellen.
Also wollen wir das umwandeln:
%Vor%Dazu:
%Vor%Wir können das tun, indem wir unsere Transformationsoptionen definieren:
%Vor%Das einzige Kniffige war hier die Funktion %code% hinzuzufügen. Was wir wollen, ist, die Funktion %code% an %code% zu übergeben, aber wenn wir %code% durch %code% ersetzen, wird %code% als reguläre Funktion verwendet.Also wird es unseren Baum in folgendes verwandeln:
%Vor%Aber mit %code% wird %code% als Argument an %code% als solches übergeben:
%Vor%Fazit
Wir können nun unseren kleinen Interpreter ausführen, indem wir den Parser und den Transformator zusammensetzen:
%Vor%Sie finden den endgültigen Code in diesem Tutorial hier .
Hoffentlich reicht diese kurze Einführung, um eigene Projekte in Angriff zu nehmen. Sie können neue Zeilen erstellen, indem Sie eine Grammatik für %code% deklarieren, und Sie können sogar auswählen, Leerzeichen in Ihrem Syntaxbaum nicht zu ignorieren, indem Sie die spitzen Klammern %code% entfernen. Das könnte hilfreich sein, da Sie versuchen, die Einrückung beizubehalten. Hoffe das hilft, wenn nicht nur einen Kommentar schreiben!