我正在學習與Write yourself a scheme
haskell。Parsec <|>解析器的選擇,錯誤拋出但不去下一個解析器
我目前正試圖在計劃中實施char
識別。字符是#\<character>
或#\<character-name>
,如#\a
或#\
或#\space
。
所以我寫了下面的代碼:
-- .. some code ..
data LispVal = Atom String
| List [LispVal]
| DottedList [LispVal] LispVal
| String String
| Number Integer
| Bool Bool
| Char Char deriving Show
-- .... More code ...
parseChar :: Parser LispVal
parseChar = liftM Char (parseSingleChar <|> parseSpecialCharNotation)
parseSingleChar :: Parser Char
parseSingleChar = do string "#\\"
x <- letter
return x
parseSpecialCharNotation :: Parser Char
parseSpecialCharNotation = do string "#\\"
x <- (parseSpace <|> parseNewline)
return x
parseSpace :: Parser Char
parseSpace = do char 's'
char 'p'
char 'a'
char 'c'
char 'e'
return ' '
parseNewline :: Parser Char
parseNewline = do char 'n'
char 'e'
char 'w'
char 'l'
char 'i'
char 'n'
char 'e'
return '\n'
-- .. some more code...
readExpr :: String -> String
readExpr input = case parse parseExpr "lisp" input of
Left err -> "Parse Error: " ++ show err
Right val -> "Found value: " ++ show val
在這一刻,我不知道在Parsec
的string
解析器。
問題是我認識到,#\a
但#\space
被視爲s
。
*Main> readExpr "#\\space"
"Found value: Char 's'"
要解決此問題,我改變parseChar
爲
parseChar :: Parser LispVal
parseChar = liftM Char (parseSpecialCharNotation <|> parseSingleChar)
,但早期的問題是解決了,但現在它給我的錯誤與正常字符 -
*Main> readExpr "#\\s"
"Parse Error: \"lisp\" (line 1, column 4):\nunexpected end of input\nexpecting \"p\""
這是爲什麼發生?難道它不應該由於parseSpecialCharNotation
失敗而轉移到parseSingleChar
?
的完整代碼在:Gist