尝试处理Maybe作为ParseError时,parsec会产生奇怪的错误

时间:2016-03-20 13:41:31

标签: parsing haskell

如果我有这段代码:

import Text.Parsec

ispositive a = if (a<0) then Nothing else (Just a)

f a b = a+b  

parserfrommaybe :: String -> (Maybe c) -> Parsec a b c
parserfrommaybe msg Nothing  = fail msg
parserfrommaybe _ (Just res)  = return res    

(<!>) :: Parsec a b (Maybe c) -> String -> Parsec a b c
(<!>) p1 msg = p1 >>= (parserfrommaybe msg)    

integermaybeparser = (ispositive <$> integer) <!> "negative numbers are not allowed"
testparser = f <$> (integermaybeparser <* whiteSpace) <*> integermaybeparser

当我用这样的输入测试testparser&#34; -1 3&#34;它给出了:

Left (line 1, column 4):
unexpected "3"
negative numbers are not allowed

我希望它在第1列上给出错误并给出错误消息,而不是句子&#34;意外的3&#34;但似乎parsec继续解析。

为什么会这样?以及如何使parsec给出我期望的错误消息?

1 个答案:

答案 0 :(得分:1)

我找到了解决方案,原因是第一个解析器运行并且即使在失败时也会消耗输入。

解决方案是使用lookAhead,如下所示:

(<!>) :: (Monad m,Stream a m t) => ParsecT a b m (Maybe c) -> String -> ParsecT a b m c
(<!>) p1 msg =  ((lookAhead p1) >>= (parserfrommaybe msg)) *> (p1 >>= (parserfrommaybe msg))

如果lookAhead p1返回Nothing,那么*>的第一个参数会因lookAhead而失去输入而失败,现在如果lookAhead p1返回Just res然后它会再次成功而不消耗输入,结果将从*>的第二个参数获得。

当然我不得不将parserfrommaybe类型注释更改为(Monad m) => String -> (Maybe c) -> ParsecT a b m c以满足ghc。