Я изучаю haskell с Write yourself a scheme
.Parsec <|> выбор в синтаксическом анализаторе, ошибка бросает, но не переходит к следующему парсеру
Я в настоящее время пытаюсь реализовать признание в схеме char
. A 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
В этот момент я не знал о string
парсера Parsec
.
Проблема в том, что я признаю, #\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\""
Почему это происходит? Разве он не переместился в parseSingleChar
, так как parseSpecialCharNotation
не удалось?
Полный код по адресу: Gist