带有 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,甚至考虑直接编写函数。