Подтвердить что ты не робот

Почему я вижу частичные результаты с attoparsec, когда я ожидаю увидеть Failure?

Я немного смущен этим поведением 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"?

4b9b3361

Ответ 1

Это деталь реализации, синтаксический анализатор 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 input (a Partial result), если он не находит достаточно ввода сразу.

Вы можете получить сбой

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

сообщив синтаксическому анализатору, что он больше не будет вводить (тогда demandInput из 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, что это было, подавая ему пустой Text.