带有 attoparsec 的切片
Slices with attoparsec
我正在查看来自 attoparsec 文档的 this example:
simpleComment = string "<!--" *> manyTill anyChar (string "-->")
这将构建一个 [Char]
而不是 ByteString
切片。大量评论不好,对吧?
另一种选择,takeWhile:
takeWhile :: (Word8 -> Bool) -> Parser ByteString
无法接受解析器(即无法匹配 ByteString
,只能匹配 Word8
)。
有没有一种方法可以使用 attoparsec 解析 ByteString
的块,而不涉及在此过程中构建 [Char]
?
您可以使用 scan
:
scan :: s -> (s -> Word8 -> Maybe s) -> Parser ByteString
A stateful scanner. The predicate consumes and transforms a state argument, and each transformed state is passed to successive invocations of the predicate on each byte of the input until one returns Nothing or the input ends.
看起来像这样:
transitions :: [((Int, Char), Int)]
transitions = [((0, '-'), 1), ((1, '-'), 2), ((2, '-'), 2), ((2, '>'), 3)]
dfa :: Int -> Word8 -> Maybe Int
dfa 3 w = Nothing
dfa s w = lookup (s, toEnum (fromEnum w)) transitions <|> Just 0
然后使用 scan 0 dfa
获取字节直到并包括最后的 "-->"
。我在这里使用的状态告诉我们到目前为止已经看到了 "-->"
的多少个字符。一旦我们看到所有这些,我们就会通知 scan
是时候停止了。这只是为了说明这个想法;为了提高效率,您可能希望使用比关联列表更高效的数据结构,将 *Enum
调用移至查找 table,甚至考虑直接编写函数。
我正在查看来自 attoparsec 文档的 this example:
simpleComment = string "<!--" *> manyTill anyChar (string "-->")
这将构建一个 [Char]
而不是 ByteString
切片。大量评论不好,对吧?
另一种选择,takeWhile:
takeWhile :: (Word8 -> Bool) -> Parser ByteString
无法接受解析器(即无法匹配 ByteString
,只能匹配 Word8
)。
有没有一种方法可以使用 attoparsec 解析 ByteString
的块,而不涉及在此过程中构建 [Char]
?
您可以使用 scan
:
scan :: s -> (s -> Word8 -> Maybe s) -> Parser ByteString
A stateful scanner. The predicate consumes and transforms a state argument, and each transformed state is passed to successive invocations of the predicate on each byte of the input until one returns Nothing or the input ends.
看起来像这样:
transitions :: [((Int, Char), Int)]
transitions = [((0, '-'), 1), ((1, '-'), 2), ((2, '-'), 2), ((2, '>'), 3)]
dfa :: Int -> Word8 -> Maybe Int
dfa 3 w = Nothing
dfa s w = lookup (s, toEnum (fromEnum w)) transitions <|> Just 0
然后使用 scan 0 dfa
获取字节直到并包括最后的 "-->"
。我在这里使用的状态告诉我们到目前为止已经看到了 "-->"
的多少个字符。一旦我们看到所有这些,我们就会通知 scan
是时候停止了。这只是为了说明这个想法;为了提高效率,您可能希望使用比关联列表更高效的数据结构,将 *Enum
调用移至查找 table,甚至考虑直接编写函数。