我正在学习haskell Write yourself a scheme
。
我目前正在尝试char
在计划中实施认可。字符是#\<character>
or或#\<character-name>
like#\a
或#\
or #\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
从文档中<|>
:
该解析器称为预测性解析器,因为仅在解析器p不使用任何输入(即,前瞻为1)时才尝试q。
在您的情况下,两个解析都会"#\\"
在失败之前消耗掉,因此无法评估其他选择。您可以try
用来确保回溯按预期进行:
解析器的
try p
行为类似于解析器p
,只是它在发生错误时假装它没有消耗任何输入。
类似于下一个:
try parseSpecialCharNotation <|> parseSingleChar
旁注:最好"#\\"
从解析器中提取出来,因为否则您将做两次相同的工作。类似于下一个:
do
string "#\\"
try parseSpecialCharNotation <|> parseSingleChar
另外,您可以使用string
combinator而不是一系列char
解析器。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句