2016-12-29 2 views
1

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?

Antwort

2

könnten Sie verwenden try

symbol s = try (spaces >> string s) 

The parser try p behaves like parser p, except that it pretends that it hasn't consumed any input when an error occurs.