parsec:字符串选择解析器,包含有用的错误消息 [英] parsec: string choice parser with useful error messages
问题描述
解析器:: GenParser字符串
解析器=选择(fmap ,尾巴,故事])
<>预期的['head','tail','tales' code>
当我们解析格式错误的输入ta时,它会返回已定义的错误,但由于回溯,它还会讨论意外的t
在第一个位置,而不是意外的
在位置3。
是否有一种简单的(或内置的)方式来匹配产生好的错误消息的多个预期字符串之一?我说的是显示正确的位置,在这种情况下,像预计tail或tales
,而不是硬编码的错误信息。
制作一个正确执行此操作的函数并不困难。我们只需一次性删除一个字符,使用 Data.Map
查找共享后缀:
<$ p $($ lt; code> { - #LANGUAGE FlexibleContexts# - }
import Control.Applicative
import Data.Map hiding(empty)
import Text.Parsec hiding((< |>))
import Text.Parsec.Char
- 如果这是一个选项,接受空字符串
possibleEmpty :: Stream sm Char => [字符串] - > ParsecT s u m字符串
可能是空的ss | elem` ss =纯
|否则=空
chooseFrom :: Stream s m Char => [字符串] - > parsecT sum String
chooseFrom ss
= foldWithKey(\ h ts parser - > liftA2(:)(char h)(chooseFrom ts)< |> parser)
empty
(fromListWith(++)[(h,[t])| h:t <-ss])
< |>可能是空的ss
我们可以在ghci中验证它是否成功匹配tail / code>和
tales
,并要求 i
或 ta
:
*主>解析(chooseFrom [head,tail,tales])tail
右尾
* Main>解析(chooseFrom [head,tail,tales])tales
正确的故事
* Main>解析(chooseFrom [head,tail,tales])tafoo
Left(line 1,column 3):
unexpectedf
expecti 或l
Let's have following parser:
parser :: GenParser Char st String
parser = choice (fmap (try . string) ["head", "tail", "tales"]
<?> "expected one of ['head', 'tail', 'tales']")
When we parse the malformed input "ta" it will return the defined error but because of backtracking it will also talk about unexpected "t"
at first position instead of unexpected " "
at position 3.
Is there an easy (or built-in) way of matching one of multiple expected strings that produces good error messages? I am talking about showing the correct position and in this case something like expected "tail" or "tales"
instead of our hard-coded error message.
It's not hard to cook up a function which does this correctly. We'll just rip one character off at a time, using Data.Map
to find the shared suffixes:
{-# 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
We can verify in ghci that it succesfully matches "tail"
and "tales"
, and that it asks for i
or l
after a failed parse starting with 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"
这篇关于parsec:字符串选择解析器,包含有用的错误消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!