当我期望看到失败时,为什么我会看到使用attoparsec的部分结果?

时间:2013-01-11 21:51:24

标签: haskell attoparsec

我对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"
> 

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

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

1 个答案:

答案 0 :(得分:13)

这是一个实现细节,string解析器在知道是否有足够的输入可能成功之前没有完成。这是这些解析器的全有或全无行为的结果(我认为这通常对性能有益)。

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

string s尝试获取length s Text个单位,然后将其与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首先尝试确保n个单位Text可用,

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如果没有立即找到足够的输入,则会创建一个继续请求更多 gruel 输入(Partial结果)。

您可能会因

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

预先告诉解析器它将不再获得任何输入(然后来自demandInput的{​​{1}}使其失败)或稍后

ensure

通过告诉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" 结果就是这样,为它提供空Partial