Parsec解析器:在某些条件下不评估自定义失败

时间:2013-03-13 07:40:00

标签: haskell parsec

我刚开始学习使用Parsec解析字符串,我遇到了以下无法解决的问题:

以下代码包含三个解析器运行,其中两个显然会失败。奇怪的是,我的自定义失败消息只会在第二次运行时发生,而不是第三次运行。

import Text.Parsec
import Text.Parsec.String

ps :: Parser String
ps = (string "123") <|> (string "456") <|> fail "my-failure"

main = do
     putStrLn $ "A: " ++ show (parse ps "" "123")
     putStrLn $ "\nB: " ++ show (parse ps "" "789")
     putStrLn $ "\nC: " ++ show (parse ps "" "45x")

输出:

A: Right "123"

B: Left (line 1, column 1):
unexpected "7"
expecting "123" or "456"
my-failure

C: Left (line 1, column 1):
unexpected "x"
expecting "456"

当第二个<|>的左侧部分失败时,始终的正确方法是什么?我可以覆盖之前发生的任何错误吗?

1 个答案:

答案 0 :(得分:8)

Parsec中的<|>组合子仅在解析器不使用任何输入时尝试下一个选项。在您的情况下,解析器string "456""45x"的开头匹配,因此不再尝试其他替代方法。如果您需要任意预测,则需要使用try函数。

ps :: Parser String
ps = string "123" <|> try (string "456") <|> fail "my-failure"

来自Parsec的<|>文档:

  

这个组合器实现了选择。解析器p&lt; |&gt;首先应用p。如果成功,则返回p的值。如果p在没有消耗任何输入的情况下失败,则尝试解析器q。该组合子的定义等于MonadPlus类的mplus成员和Alternative的(&lt; |&gt;)成员。

     

解析器被称为预测,因为q仅在解析器p时尝试   不消耗任何输入(即......前瞻是1)。这个   非回溯行为允许有效的实现   解析器组合器的组合以及良好错误消息的生成。