如果我有这段代码:
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给出我期望的错误消息?
答案 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。