Parsing in Haskell für einen einfachen Interpreter

8

Ich bin relativ neu in Haskell, da der Hauptprogrammierungshintergrund von OO-Sprachen kommt. Ich versuche einen Interpreter mit einem Parser für eine einfache Programmiersprache zu schreiben. Bisher habe ich den Dolmetscher in einem Zustand, mit dem ich einigermaßen zufrieden bin, aber ich kämpfe ein wenig mit dem Parser.

Hier ist der Code, mit dem ich Probleme habe

%Vor%

Die Sprache ist etwas komplexer, aber das ist genug, um mein Problem zu zeigen.

Also im Typ IntExp ICon ist eine Konstante und IVar ist eine Variable, aber jetzt auf das Problem. Dies wird beispielsweise erfolgreich ausgeführt

runP parseAdd "5 + 5"

was (Add (ICon 5) (ICon 5)) ergibt, was das erwartete Ergebnis ist. Das Problem tritt auf, wenn IV statt ICons verwendet werden, zB

runP parseAdd "n + m"

Dies führt dazu, dass das Programm fehlschlägt, da es ein unerwartetes "n" gab, wo eine Ziffer erwartet wurde. Dies führt zu der Annahme, dass parseIntExp nicht so funktioniert, wie ich es beabsichtigt hatte. Meine Absicht war, dass es versuchen wird, ein ICon zu parsen, wenn das fehlschlägt, dann versuche, ein IVar zu analysieren und so weiter.

Also ich glaube entweder, dass das Problem in parseIntExp existiert, oder dass mir etwas in parseIVar und parseICon fehlt.

Ich hoffe, ich habe genug Informationen über mein Problem gegeben und ich war klar genug.

Danke für jede Hilfe, die Sie mir geben können!

    
Josh 06.11.2010, 01:43
quelle

2 Antworten

13

Ihr Problem ist tatsächlich in parseICon :

%Vor%

Der many -Kombinator entspricht null oder mehr Vorkommen, also ist es auf "m" erfolgreich, indem er null Stellen abgleicht und dann wahrscheinlich stirbt, wenn read fehlschlägt.

Und während ich dabei bin, da Sie neu bei Haskell sind, hier ein unverbindlicher Rat:

  • Verwenden Sie keine falschen Klammern. many (digit) sollte nur many digit sein. Klammern gruppieren hier nur Dinge, die für die Funktionsanwendung nicht notwendig sind.

  • Sie müssen ICon (read x :: Int) nicht tun. Der Datenkonstruktor ICon kann nur eine Int annehmen, damit der Compiler selbst herausfinden kann, was Sie gemeint haben.

  • Sie brauchen nicht try um die ersten beiden Optionen in parseIntExp , wie es ist - es gibt keine Eingabe, die dazu führen würde, dass eine Eingabe verzehrt wird, bevor sie fehlschlägt. Sie werden entweder sofort fehlschlagen (was try nicht benötigt) oder sie werden erfolgreich sein, nachdem ein einzelnes Zeichen gefunden wurde.

  • Es ist normalerweise eine bessere Idee, vor dem Parsen zuerst zu tokenisieren. Der Umgang mit Leerraum bei gleichzeitiger Syntax ist ein Problem.

  • In Haskell ist es üblich, den Operator ($) zu verwenden, um Klammern zu vermeiden. Es ist nur Funktion Anwendung, aber mit sehr niedriger Priorität, so dass etwas wie many1 (char ' ') geschrieben werden kann many1 $ char ' ' .

Auch das ist überflüssig und unnötig:

%Vor%

Wenn Sie lediglich eine reguläre Funktion auf das Ergebnis eines Parsers anwenden, können Sie einfach fmap :

verwenden %Vor%

Sie sind genau dasselbe. Sie können die Dinge noch schöner aussehen lassen, wenn Sie das Modul Control.Applicative importieren, das Ihnen eine Operatorversion von fmap , genannt (<$>) , sowie einen weiteren Operator (<*>) bietet, mit dem Sie das Gleiche mit Funktionen von tun können mehrere Argumente. Es gibt auch die Operatoren (<*) und (*>) , die die rechten bzw. linken Werte verwerfen. In diesem Fall können Sie etwas parsen, während Sie das Ergebnis, z. B. Leerraum und dergleichen, verwerfen.

Hier ist eine leicht modifizierte Version Ihres Codes mit einigen der oben genannten Vorschläge und einigen anderen kleinen stilistischen Änderungen:

%Vor%     
C. A. McCann 06.11.2010, 02:31
quelle
1

Ich bin auch neu bei Haskell, ich frage mich nur:

parsIntExp wird es jemals zu parseAdd machen?

Es scheint so, als würde ICon oder IVar immer geparst, bevor 'parseAdd' erreicht wird.

z.B. runP parseIntExp "3 + m"

würde parseICon versuchen und erfolgreich sein und

geben

(ICon 3) anstelle von (Add (ICon 3) (IVar m))

Tut mir leid, wenn ich hier dumm bin, ich bin nur unsicher.

    
tre 07.11.2010 16:36
quelle

Tags und Links