Wie definieren wir eine Grammatik für Clojure-Code instparse?

8

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%     
zcaudate 12.08.2013, 12:39
quelle

1 Antwort

23

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.

  1. 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 1 :

    %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 + ist ähnlich der regex + , 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 < hinzufügen. Wenn wir also "(1)" einfach als 1 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 (parser "( 1 )") 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 * ähnlich wie regex * und bedeutet null oder mehr als ein Auftreten eines Leerzeichens. Das bedeutet, dass die folgenden Beispiele alle das gleiche Ergebnis liefern:

    %Vor%
  2. 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 ( operation ) . Wir können dies direkt in unsere Grammatik schreiben.

    %Vor%

    Wie oben erwähnt, geben die spitzen Klammern < an, diese Werte zu ignorieren, wenn sie den Parse-Baum erstellen. Was ist eine Operation? Nun, eine Operation besteht aus einem Operator wie + und einigen Argumenten wie den Zahlen 1 und 2 . So können wir sagen unsere Grammatik schreiben als:

    %Vor%

    Wir haben nur einen möglichen Operator angegeben, + , 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 (+1) . 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 space hinzugefügt, indem wir die Raumgrammatikregel verwendet haben, die wir im einfachen Beispiel definiert haben. Wir haben eine neue snumber erstellt, die als space und eine number definiert ist, und die + 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 args reference wieder auf sexp setzen. So können wir Sex in unserem Sex haben! Wir können dies tun, indem wir ssexp erstellen, die% space zu sexp hinzufügt und dann ssexp zu args hinzufügt.

    %Vor%

    Jetzt können wir

    ausführen %Vor%
  3. 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 insta\transform . Wir können unsere Transformationen erstellen, indem wir die Schlüssel in unserem Syntaxbaum durch die gültigen Clojure-Funktionen ersetzen. Zum Beispiel wird :number zu read-string , um unsere Strings in gültige Zahlen umzuwandeln, :args wird zu vector , 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 choose-op hinzuzufügen. Was wir wollen, ist, die Funktion + an apply zu übergeben, aber wenn wir operator durch + ersetzen, wird + als reguläre Funktion verwendet.Also wird es unseren Baum in folgendes verwandeln:

    %Vor%

    Aber mit choose-op wird + als Argument an apply 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 \n deklarieren, und Sie können sogar auswählen, Leerzeichen in Ihrem Syntaxbaum nicht zu ignorieren, indem Sie die spitzen Klammern < entfernen. Das könnte hilfreich sein, da Sie versuchen, die Einrückung beizubehalten. Hoffe das hilft, wenn nicht nur einen Kommentar schreiben!

    
pooya72 13.08.2013, 14:01
quelle

Tags und Links