2012-04-02 9 views
8

Ich versuche, einigen Text mit Parsec zu analysieren:Haskell Text.Parsec.Combinator Wahl Rückzieher nicht

data Cmd = LoginCmd String 
     | JoinCmd String 
     | LeaveCmd String 
    deriving (Show) 

singleparam :: Parser Cmd 
singleparam = do 
    cmd <- choice [string "leave", string "login", string "join"] 
    spaces 
    nick <- many1 anyChar 
    eof 
    return $ LoginCmd nick 

ich choice zu versuchen warte anzupassen „verlassen“, und wenn es scheitert, dann versuche "Login" usw. Aber es versucht nur, "verlassen" zu passen, und wenn es fehlschlägt, dann gibt es einen Fehler.

ghci> parseTest singleparam (pack "login asdf") 
parse error at (line 1, column 1): 
unexpected "o" 
expecting "leave" 
ghci> parseTest singleparam (pack "leave asdf") 
LoginCmd "asdf" 

Was mache ich falsch?

Antwort

14

Parsec kehrt nicht automatisch so zurück (für Effizienz). Die Regel ist, dass, sobald eine Verzweigung ein Token akzeptiert, alternative Verzweigungen abgeschnitten werden. Die Lösung ist einen expliziten Rückzieher mit try (string "leave") und try (string "login") usw.

In Ihrem Beispiel der ‚l‘ Zeichen sind das Zeichen hinzuzufügen, die Parsec zum ersten „verlassen“ Zweig begeht und verläßt die nächsten Filialen von „login“ und " Beitreten".

Mehr Detail in der realen Welt Haskell (Buch, online) on parsec.