parsec:带有有用错误消息的字符串选择解析器

2023-12-06

让我们有以下解析器:

parser :: GenParser Char st String
parser = choice (fmap (try . string) ["head", "tail", "tales"]
                    <?> "expected one of ['head', 'tail', 'tales']")

当我们解析格式错误的输入“ta”时,它将返回定义的错误,但由于回溯,它还会谈论unexpected "t"在第一个位置而不是unexpected " "在位置 3。

是否有一种简单(或内置)的方法来匹配多个预期字符串之一,从而产生良好的错误消息?我说的是显示正确的位置,在这种情况下类似expected "tail" or "tales"而不是我们硬编码的错误消息。


编写一个正确执行此操作的函数并不难。我们一次只会撕掉一个角色,使用Data.Map查找共享后缀:

{-# LANGUAGE FlexibleContexts #-}
import Control.Applicative
import Data.Map hiding (empty)
import Text.Parsec hiding ((<|>))
import Text.Parsec.Char

-- accept the empty string if that's a choice
possiblyEmpty :: Stream s m Char => [String] -> ParsecT s u m String
possiblyEmpty ss | "" `elem` ss = pure ""
                 | otherwise    = empty

chooseFrom :: Stream s m Char => [String] -> ParsecT s u m String
chooseFrom ss
     =  foldWithKey (\h ts parser -> liftA2 (:) (char h) (chooseFrom ts) <|> parser)
                    empty
                    (fromListWith (++) [(h, [t]) | h:t <- ss])
    <|> possiblyEmpty ss

我们可以在ghci中验证是否匹配成功"tail" and "tales",并且它要求i or l解析失败后ta:

*Main> parse (chooseFrom ["head", "tail", "tales"]) "" "tail"
Right "tail"
*Main> parse (chooseFrom ["head", "tail", "tales"]) "" "tales"
Right "tales"
*Main> parse (chooseFrom ["head", "tail", "tales"]) "" "tafoo"
Left (line 1, column 3):
unexpected "f"
expecting "i" or "l"
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

parsec:带有有用错误消息的字符串选择解析器 的相关文章

随机推荐