当我期望看到失败时,为什么我会用attoparsec查看部分结果? [英] Why do I see Partial results with attoparsec when I expect to see Failure?
问题描述
$ ghci
> 我对attoparsec的行为有些困惑。 :m Data.Attoparsec.Text
> :m + Data.Text
> parse(string(packmodule))(packmox)
Partial _
> parse(string(packmodule))(packmoxxxx)
失败moxxxx[]失败的阅读:takeWith
>
为什么我需要添加字符才能触发失败?
一旦遇到第一个x,它不应该失败吗?
详细信息,字符串
解析器在知道是否有足够的输入可能会成功之前未完成。这是这些解析器的全有或全无行为的结果(我认为这对于性能来说通常是有好处的)。
string :: Text - >解析器文本
字符串s = takeWith(T.length s)(== s)
字符串s
尝试使用长度s
文本
的单位,然后比较它们与 s
。
takeWith :: Int - > ; (文本 - > Bool) - >解析器文本
takeWith np = do
s< - 确保n
让h = unsafeTake ns
t = unsafeDrop ns
if ph
then put t> >返回h
其他失败takeWith
takeWith np
首先尝试确保
n
单位的 Text
可用,并且
ensure :: Int - >解析器文本
确保!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
您可以输入( 先告诉解析器它将不会得到任何更多的输入(然后从 I'm a little confused by this behaviour of attoparsec. Why do I need addition characters present to trigger the Fail? Shouldn't it Fail as soon as the first "x" is encountered? It's an implementation detail, a You can get a failure with telling the parser up front that it won't get any more input (then the by telling the 这篇关于当我期望看到失败时,为什么我会用attoparsec查看部分结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!确保n
创建一个延续,询问更多的稀饭
部分
结果)
Prelude Data.Attoparsec.Text Data.Text> parseOnly(string(packmodule))(packmox)
没有足够的输入
中的
使它失败),或稍后 demandInput
)确保
Prelude Data.Attoparsec.Text Data.Text> parse(string(packmodule))(packmox)
Partial _
Prelude Data.Attoparsec.Text Data.Text>喂它(pack)
失败mox[demandInput]没有足够的输入
$ b $通过告诉 Partial
结果表明这是它,并为它提供一个空的 Text
。$ 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"
>
string
parser doesn't finish before it knows whether there is enough input remaining for it to possibly succeed. It's a consequence of the all-or-nothing behaviour of these parsers (which, I think, is generally good for performance).string :: Text -> Parser Text
string s = takeWith (T.length s) (==s)
string s
tries to take length s
units of Text
, and then compare them with 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
first tries to ensure that n
units of Text
are available, andensure :: 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
creates a continuation asking for more gruel input (a Partial
result) if it doesn't find enough input immediately.Prelude Data.Attoparsec.Text Data.Text> parseOnly (string (pack "module")) (pack "mox")
Left "not enough input"
demandInput
from ensure
makes it fail), or laterPrelude 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
result that that was it, feeding it an empty Text
.