【问题标题】:Parsec parser: Custom fail is not evaluated in certain conditionsParsec 解析器:在某些条件下不评估自定义失败
【发布时间】:2013-03-13 07:39:59
【问题描述】:

我刚刚开始学习使用 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"

当第二个&lt;|&gt; 的左侧部分失败时,总是出现我的失败消息的正确方法是什么?我可以覆盖任何以前发生的错误吗?

【问题讨论】:

    标签: haskell parsec


    【解决方案1】:

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

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

    来自 Parsec 的 &lt;|&gt; 文档:

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

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

    【讨论】:

    • 您可能更喜欢使用&lt;?&gt; 而不是&lt;|&gt; fail "my-failure",而不是&lt;?&gt; "syntax element",这将产生错误消息expecting syntax element 而不是my-failure。但是您仍然需要使用try
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-01
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    • 2022-12-05
    • 1970-01-01
    相关资源
    最近更新 更多