【问题标题】:Why do I see Partial results with attoparsec when I expect to see Failure?当我预计会看到失败时,为什么我会看到 attoparsec 的部分结果?
【发布时间】:2013-01-11 21:51:24
【问题描述】:

我对 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”就失败吗?

【问题讨论】:

标签: haskell attoparsec


【解决方案1】:

这是一个实现细节,string 解析器在知道是否还有足够的输入使其可能成功之前不会完成。这是这些解析器要么全有要么全无行为的结果(我认为这通常对性能有好处)。

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

string s 尝试以Textlength s 为单位,然后将它们与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"

提前告诉解析器它不会再获得任何输入(然后来自ensuredemandInput 使其失败),或者稍后

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 结果就是它,给它一个空的Text

【讨论】:

  • 谢谢 - 经过您的解释,这很有意义。
猜你喜欢
  • 2011-10-24
  • 2016-02-02
  • 1970-01-01
  • 2021-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-10
相关资源
最近更新 更多