【问题标题】:Slices with attoparsec带有 attoparsec 的切片
【发布时间】:2020-09-05 08:09:27
【问题描述】:

我正在查看 attoparsec 文档中的 this example

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

这将构建一个 [Char] 而不是 ByteString 切片。这对巨大的 cmets 不好,对吧?

另一种选择,takeWhile

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

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

有没有办法用 attoparsec 解析 ByteString 的块,而不涉及在此过程中构建 [Char]

【问题讨论】:

    标签: haskell attoparsec


    【解决方案1】:

    你可以使用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 获取字节,包括最后的"--&gt;"。我在这里使用的状态告诉我们到目前为止我们看到了多少个"--&gt;" 字符。一旦我们看到它们,我们就会通知scan,是时候停下来了。这只是为了说明这个想法;为了提高效率,您可能希望使用比关联列表更高效的数据结构,将 *Enum 调用移至查找表,甚至考虑直接编写函数。

    【讨论】:

    • 好的,在这种情况下可以工作,但没有办法像manyTill 那样推广到自定义解析器?举个例子,说结束 HTML 注释也可以散布数字而不是 --&gt; - 例如-1-9&gt;-55-&gt;--37&gt; 都是有效的结尾。当然,您可以使用 scan 手动编写它,但有点违背解析器的目的,对吧?
    • @levantpied 我相信 API 目前不能方便地从 attoparsec 公开。将其添加到 API 的补丁几乎肯定会被接受,而且我相信没有技术原因无法创建它。与此同时,Parser 类型的足够多的内部组件看起来像是暴露在售后市场上供您使用,可以这么说,并且只有在您有工作时才提出补丁。
    猜你喜欢
    • 2018-04-30
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    • 2019-07-05
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2014-05-28
    相关资源
    最近更新 更多