Jest to szczegół implementacji, parser string
nie kończy się, zanim wie, czy jest wystarczająco dużo danych wejściowych, aby mogło dojść do skutku. Jest to konsekwencja działania tych lub wszystkich parserów (co, jak sądzę, jest ogólnie dobre dla wydajności).
string :: Text -> Parser Text
string s = takeWith (T.length s) (==s)
string s
próbuje wziąć length s
jednostek z Text
, a następnie porównać je z 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
próbuje najpierw upewnić się, że n
jednostki Text
są dostępne, a
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
tworzy kontynuację prosząc o więcej kleik wejścia (a Partial
wynik) jeśli nie znajdzie wystarczające dane wejściowe natychmiast.
Można uzyskać awarię z
Prelude Data.Attoparsec.Text Data.Text> parseOnly (string (pack "module")) (pack "mox")
Left "not enough input"
mówi parser z góry, że nie będzie żadnych więcej wejście (wówczas demandInput
z ensure
sprawia, że nie), czy później
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"
, informując o tym, że to było to, podając go pusty Text
.
W razie potrzeby otworzyłem bilet, a opiekun Attoparsec naprawił ten błąd: https://github.com/bos/attoparsec/issues/97 –