這是一個實現細節,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
創建一個延續,要求更多的稀粥輸入(Partial
結果),如果沒有找到足夠的輸入立即。
你可以得到一個失敗與
Prelude Data.Attoparsec.Text Data.Text> parseOnly (string (pack "module")) (pack "mox")
Left "not enough input"
告訴解析器前面,它不會得到任何更多的輸入(然後從ensure
的demandInput
使它失效),或更高版本
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
。
爲了將來的參考,我打開了一張票,Attoparsec維護人員修復了這個錯誤:https://github.com/bos/attoparsec/issues/97 –