Ответ 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
.