首页 > 解决方案 > 带有 attoparsec 的切片

问题描述

我正在查看attoparsec 文档中的这个示例:

simpleComment   = string "<!--" *> manyTill anyChar (string "-->")

这将构建一个[Char]而不是ByteString切片。这对大量评论不好,对吧?

另一种选择,takeWhile

takeWhile :: (Word8 -> Bool) -> Parser ByteString

不能接受解析器(即不能匹配 a ByteString,只能匹配 a Word8)。

有没有办法ByteString用 attoparsec 解析大块而不涉及[Char]在过程中构建 a ?

标签: haskellattoparsec

解决方案


您可以使用scan

scan :: s -> (s -> Word8 -> Maybe s) -> Parser ByteString

有状态的扫描仪。谓词使用并转换一个状态参数,并且每个转换后的状态都被传递给对输入的每个字节的谓词的连续调用,直到一个返回 Nothing 或输入结束。

它看起来像这样:

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调用移动到查找表中,甚至考虑直接编写函数。


推荐阅读