2010-11-28 2 views
2

Am noch neu in Haskell, so entschuldigen abgrenzen, wenn es eine offensichtliche Antwort ist ...


Ich möchte eine Funktion machen, die bis spaltet die dh alle folgenden Listen von Strings [String]:Haskell: eine Zeichenfolge, die von ausgewählten Unterketten und Leerzeichen

["int x = 1", "y := x + 123"] 
["int x= 1", "y:= x+123"] 
["int x=1", "y:=x+123"] 


Alle in die gleiche Reihe von Strings, dh [[Zeichenfolge]]:

[["int", "x", "=", "1"], ["y", ":=", "x", "+", "123"]] 



Sie können map words.lines für den ersten [String] verwenden.

Aber ich kenne keine wirklich nette Möglichkeiten, um auch die anderen zu berücksichtigen - wo Sie die verschiedenen Sub-Strings würde "=", ":=", "+" usw. die Hauptsaite aufzubrechen.



Danke für die Zeit nehmen mich auf Haskell zu erleuchten :-)

Antwort

7

Das Vorspiel kommt mit einer wenig bekannten praktischen Funktion namens lex, die eine Lexer für Haskell Ausdrücke ist. Diese entsprechen der Form, die Sie benötigen.

lex :: String -> [(String,String)] 

Was für ein komischer Typ! Die Liste ist da für die Schnittstelle mit einem Standardtyp von Parser, aber ich bin ziemlich sicher lex gibt immer entweder 1 oder 0 Elemente zurück (0 zeigt einen Parse-Fehler). Das Tupel ist (token-lexed, rest-of-input), also lex zieht nur ein Token ab. So eine einfache Möglichkeit, eine ganze Reihe wäre zu lex:

lexStr :: String -> [String] 
lexStr "" = [] 
lexStr s = 
    case lex s of 
     [(tok,rest)] -> tok : lexStr rest 
     []   -> error "Failed lex" 

Um die Pedanten zu beschwichtigen, ist dieser Code in der schrecklichen Form. Ein expliziter Aufruf an error anstelle der Rückgabe eines vernünftigen Fehlers mit Maybe, unter der Annahme lex gibt nur 1 oder 0 Elemente, etc. Der Code, der dies zuverlässig tut, ist etwa gleich lang, ist aber deutlich abstrakter, so verschonte ich Ihre Anfängeraugen.

3

ich einen Blick auf parsec nehmen und eine einfache Grammatik bauen die Saiten zum Parsen.

+0

Vielen Dank für Ihre Antwort. Ich hoffte jedoch auf einen einfachen Weg, um es "rein" zu machen, d. H. Ohne andere Bibliotheken. Oh, und am liebsten ohne Monaden (weil ich noch nicht ganz dazu gekommen bin, über sie zu lernen, lol). –

+0

Yeah parsec ist nicht großartig, wenn Sie anfangen. Ich fand es ziemlich einfach, einen Parser zu bearbeiten, den jemand anders geschrieben hatte, aber das Schreiben meiner eigenen war für eine Weile über meine Fähigkeiten hinaus. Benötigt etwas Trost mit Monaden. – luqui

+0

Fair genug. Es ist jedoch eine Überlegung wert, als eine Option. Wenn Sie etwas anderes möchten, das nicht monadisch ist, müssen Sie möglicherweise mit einer benutzerdefinierten Option gehen. –

0

wie Worte über die Verwendung.) words :: String -> [String] und Worte Pflege wird nicht für Whitespaces ..

words "Hello World" 
= words "Hello  World" 
= ["Hello", "World"] 
+0

Oh - gerade gesehen, dass ich nicht lange dachte: Wörter werden nicht "y: =" in "y", ": =" teilen, deshalb müssen Sie entweder Ihren eigenen einfachen Parser schreiben (vielleicht mit dem Hilfe der Wörter: P) oder benutze Parsec (was eine gute Wahl ist, um überhaupt zu wissen). –

+0

Plus die Verwendung von "Wörter" wurde bereits in der Frage erwähnt;) –

+0

Wonderfull - Ich sollte anfangen, die Orientierungslosigkeit meiner Kommentare als Indikator zu verwenden, um etwas Schlaf zu bekommen .. –

Verwandte Themen