我从attoparsec文档中看到这个例子:
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
有状态的扫描仪。谓词消耗并转换一个状态参数,每个转换后的状态都被传递给输入的每个字节上的谓词的连续调用,直到返回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
然后使用CCD_ 8获取直到并包括最终CCD_ 9的字节。我在这里使用的状态告诉到目前为止我们已经看到了"-->"
的多少个字符。一旦我们看到了它们,我们就会通知scan
是时候停止了。这只是为了说明这个想法;为了提高效率,您可能希望使用比关联列表更高效的数据结构,将*Enum
调用移动到查找表中,甚至可以考虑直接编写函数。