14

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

Fail をトリガーするために追加の文字が必要なのはなぜですか?

最初の「x」に遭遇するとすぐに失敗するべきではありませんか?

4

1 に答える 1

13

これは実装の詳細であり、stringパーサーは、成功するために十分な入力が残っているかどうかを知る前に終了しません。これは、これらのパーサーのオールオアナッシング動作の結果です(これは、一般的にパフォーマンスに適していると思います)。

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

string slength 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詳細を求める継続を作成しますPartialすぐに十分な入力が見つからない場合は、入力(結果)。

あなたは失敗する可能性があります

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

パーサーに、これ以上入力を取得しないことを事前に通知します(その後、demandInputfromensureは失敗します)、または後で

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

于 2013-01-11T23:02:07.053 に答える