当我期望看到失败时,为什么我会用attoparsec查看部分结果? [英] Why do I see Partial results with attoparsec when I expect to see Failure?

查看:196
本文介绍了当我期望看到失败时,为什么我会用attoparsec查看部分结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  $ ghci 
>

我对attoparsec的行为有些困惑。 :m Data.Attoparsec.Text
> :m + Data.Text
> parse(string(packmodule))(packmox)
Partial _
> parse(string(packmodule))(packmoxxxx)
失败moxxxx[]失败的阅读:takeWith
>

为什么我需要添加字符才能触发失败?

一旦遇到第一个x,它不应该失败吗?

解决方案

详细信息,字符串解析器在知道是否有足够的输入可能会成功之前未完成。这是这些解析器的全有或全无行为的结果(我认为这对于性能来说通常是有好处的)。

  string :: Text  - >解析器文本
字符串s = takeWith(T.length s)(== s)

字符串s 尝试使用长度s 文本的单位,然后比较它们与 s

  takeWith :: Int  - > ; (文本 - > Bool) - >解析器文本
takeWith np = do
s< - 确保n
让h = unsafeTake ns
t = unsafeDrop ns
if ph
then put t> >返回h
其他失败takeWith

takeWith np 首先尝试确保 n 单位的 Text 可用,并且

  ensure :: Int  - >解析器文本
确保!n = T.Parser $ \i0 a0 m0 kf ks - >
if lengthAtLeast(unI i0)n
then ks i0 a0 m0(unI i0)
else runParser(demandInput>> go n)i0 a0 m0 kf ks
where
go n'= T.Parser $ \i0 a0 m0 kf ks - >
if lengthAtLeast(unI i0)n'
then ks i0 a0 m0(unI i0)
else runParser(demandInput>> go n')i0 a0 m0 kf ks

确保n 创建一个延续,询问更多的稀饭

您可以输入(部分结果)

  Prelude Data.Attoparsec.Text Data.Text> parseOnly(string(packmodule))(packmox)
没有足够的输入

先告诉解析器它将不会得到任何更多的输入(然后从中的 demandInput )确保使它失败),或稍后

  Prelude Data.Attoparsec.Text Data.Text> parse(string(packmodule))(packmox)
Partial _
Prelude Data.Attoparsec.Text Data.Text>喂它(pack)
失败mox[demandInput]没有足够的输入


$ b $通过告诉 Partial 结果表明这是它,并为它提供一个空的 Text


I'm a little confused by this behaviour of attoparsec.

$ ghci
> :m Data.Attoparsec.Text
> :m + Data.Text
> parse (string (pack "module")) (pack "mox")
Partial _
> parse (string (pack "module")) (pack "moxxxx")
Fail "moxxxx" [] "Failed reading: takeWith"
> 

Why do I need addition characters present to trigger the Fail?

Shouldn't it Fail as soon as the first "x" is encountered?

解决方案

It's an implementation detail, a string parser doesn't finish before it knows whether there is enough input remaining for it to possibly succeed. It's a consequence of the all-or-nothing behaviour of these parsers (which, I think, is generally good for performance).

string :: Text -> Parser Text
string s = takeWith (T.length s) (==s)

string s tries to take length s units of Text, and then compare them with s.

takeWith :: Int -> (Text -> Bool) -> Parser Text
takeWith n p = do
  s <- ensure n
  let h = unsafeTake n s
      t = unsafeDrop n s
  if p h
    then put t >> return h
    else fail "takeWith"

takeWith n p first tries to ensure that n units of Text are available, and

ensure :: Int -> Parser Text
ensure !n = T.Parser $ \i0 a0 m0 kf ks ->
    if lengthAtLeast (unI i0) n
    then ks i0 a0 m0 (unI i0)
    else runParser (demandInput >> go n) i0 a0 m0 kf ks
  where
    go n' = T.Parser $ \i0 a0 m0 kf ks ->
        if lengthAtLeast (unI i0) n'
        then ks i0 a0 m0 (unI i0)
        else runParser (demandInput >> go n') i0 a0 m0 kf ks

ensure n creates a continuation asking for more gruel input (a Partial result) if it doesn't find enough input immediately.

You can get a failure with

Prelude Data.Attoparsec.Text Data.Text> parseOnly (string (pack "module")) (pack "mox")
Left "not enough input"

telling the parser up front that it won't get any more input (then the demandInput from ensure makes it fail), or later

Prelude Data.Attoparsec.Text Data.Text> parse (string (pack "module")) (pack "mox")
Partial _
Prelude Data.Attoparsec.Text Data.Text> feed it (pack "")
Fail "mox" ["demandInput"] "not enough input"

by telling the Partial result that that was it, feeding it an empty Text.

这篇关于当我期望看到失败时,为什么我会用attoparsec查看部分结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆