Ich verwende das Parsec
-Modul in Haskell, um Dateien zu analysieren. Eine der Komponenten dieser Dateien sind Farben. Ich habe eine Art für Farben wie folgt erstellt:Parsing Whitespace vor oder sonst mit Parsec
data Color = Yellow | Red | Blue | Green deriving (Show)
Mein erster Versuch Parsen Farben wie folgt aussieht:
symbol :: String -> Parsec String() String
symbol s = spaces >> string s
colorP :: Parsec String() Color
colorP =
liftM mkColor $ symbol "Yellow" <|> symbol "Red" <|> symbol "Blue" <|> symbol "Green"
where
mkColor :: String -> Color
mkColor "Yellow" = Yellow
mkColor "Red" = Red
mkColor "Blue" = Blue
mkColor "Green" = Green
Ich habe die symbol
Parser, die im Grunde so viel Leerzeichen wie möglich isst und dann isst die angegebene Zeichenfolge s
. Dies scheint jedoch nicht zu funktionieren. Ich teste diesen Code mit dem folgenden Aufruf:
parse colorP "" " Red"
Das gab mir die folgende Fehlermeldung:
unexpected "R"
expecting space or "Yellow"
Allerdings habe ich auf Hoogle für die Dokumentation ging suchen, die mit dem <|>
Operator geht und dort fand ich die folgenden:
This combinator implements choice. The parser p <|> q first applies p. If it succeeds, the value of p is returned. If p fails without consuming any input, parser q is tried.
Also, ich denke, das Problem mit dem obigen Beispiel ist, dass Parser p
(in diesem Fall symbol "Yellow"
) alrea dy hat etwas Input verbraucht, nämlich die Leerzeichen! Also, ich meine Refactoring colorP
wie folgt aus:
colorP =
liftM mkColor $ spaces >> (string "Yellow" <|> string "Red" <|> string "Blue" <|> string "Green")
where
-- mkColor same as before
, die das Ergebnis gibt ich will.
Nun frage ich mich, ob es Parser wie der symbol
Parser, den ich geschrieben habe, gibt, aber das setzt die Eingabe im Falle eines Fehlers zurück. Oder ist die zweite Implementierung von colorP
diejenige, die am meisten Haskell-ish ist?