gpt4 book ai didi

haskell - 我如何强制 Parsec 返回错误?

转载 作者:行者123 更新时间:2023-12-03 07:41:32 24 4
gpt4 key购买 nike

我正在使用 Parsec 制作一个解析器,我尝试在解析期间返回一个特定的错误。

这是一个暴露我的问题的最小解析器示例:

parseA = try seq1
<|> seq2

seq1 = do
manyTill anyChar (try $ string "\n* ")
many1 anyChar
fail "My error message"

seq2 = do
manyTill anyChar (try $ string "\n- ")
many1 anyChar

我想在第一个 try $ do 序列中执行一些测试并停止解析并返回特定的错误消息。当我不使用 fail 时,我得到:

ghci>  parse parseA  "" "aaaaaa\nbbbb\n* ccccc\n- ddd"
Right "ccccc\n- ddd"

当我使用failunexpected 时,我的解析器不会停止(由于try 函数)并执行下一个序列:

ghci>  parse parseA  "" "aaaaaa\nbbbb\n* ccccc\n- ddd"
Right "ddd"

这不是我想要的!

我考虑过使用基本的 error 函数来停止我的解析器的执行,但我希望解析函数返回一个“干净”的错误,如下所示:

ghci>  parse parseA  "" "aaaaaa\nbbbb\n* ccccc\n- ddd"
Left "My error message"

您知道如何正确停止解析器并返回自定义错误吗?

最佳答案

如果您希望 monad 表现不同,那么也许您应该构建一个不同的 monad。 (注意,我不完全清楚你想要什么,但无论如何都要向前看)。

解决方案:使用 Monad 转换器堆栈

例如,要获得一个类似fail 的函数,它不会被Parsec 的try 捕获和忽略,您可以使用Except monad。 . Except 允许您像抛出异常一样抛出错误,但它们是单次探测的,而不是使用需要 IO 来捕获它的实际异常机制。

首先,让我们定义我们的 monad:

import Text.Parsec
import Text.Parsec.Combinator
import Text.Parsec.Char
import Control.Monad.Trans.Except
import Control.Monad.Trans

type EscParse a = ParsecT String () (Except String) a

所以 monad 是 EscParse 并结合了 Parsec 的特性(通过转换器 ParsecT)和 Except

其次,让我们定义一些助手:

run :: EscParse a -> SourceName -> String -> Either String (Either ParseError a)
run op sn input = runExcept (runPT op () sn input)

escFail :: String -> EscParse a
escFail = lift. throwE

我们的 run 类似于 runParse 但也运行 except monad。您可能想做一些事情来避免嵌套的 Either,但这是一个简单的外观更改。 escFail 是您不希望错误被忽略时使用的方法。

第三,我们需要使用这个新的 monad 来实现您的解析器:

parseA :: EscParse String
parseA = try seq1 <|> seq2

seq1 :: EscParse String
seq1 = do manyTill anyChar (try $ string "\n* ")
many1 anyChar
escFail "My error message"

seq2 :: EscParse String
seq2 = do manyTill anyChar (try $ string "\n- ")
many1 anyChar

除了间距和类型签名外,上面的内容与您所拥有的匹配,但使用 escFail 而不是 fail

关于haskell - 我如何强制 Parsec 返回错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54083473/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com