【问题标题】:Conduit and Attoparsec - extracting delimited textConduit 和 Attoparsec - 提取分隔文本
【发布时间】:2015-05-23 01:44:32
【问题描述】:

假设我有一个文本由 Jade 式括号分隔的文档,例如 {{foo}}。我编写了一个 Attoparsec 解析器,它似乎可以正确提取 foo

findFoos :: Parser [T.Text]
findFoos = many $ do
  manyTill anyChar (string "{{")
  manyTill letter (string "}}")

测试表明它可以工作:

> parseOnly findFoos "{{foo}}"
Right ["foo"]
> parseOnly findFoos "{{foo}} "
Right ["foo"]

现在,使用conduit-extra 中的Data.Conduit.Attoparsec 模块,我似乎遇到了奇怪的行为:

> yield "{{foo}}" $= (mapOutput snd $ CA.conduitParser findFoos) $$ CL.mapM_ print
["foo"]
> yield "{{foo}} " $= (mapOutput snd $ CA.conduitParser findFoos) $$ CL.mapM_ print
-- floods stdout with empty lists

这是期望的行为吗?我应该在这里使用导管实用程序吗?对此的任何帮助都将是巨大的!

【问题讨论】:

    标签: haskell conduit attoparsec


    【解决方案1】:

    因为它使用many,所以findFoos 将在没有找到任何分隔文本时返回[] 而不会消耗输入。

    另一方面,conduitParser 对流重复应用解析器,返回每个解析的值,直到耗尽流。

    "{{foo}} " 的问题在于解析器将消耗{{foo}},但流中的空白空间仍未消耗,因此解析器的进一步调用总是返回[]

    如果您重新定义 findFoos 以一次使用一个带引号的元素,包括尾随空格,它应该可以工作:

    findFoos' :: Parser String
    findFoos' = do
       manyTill anyChar (string "{{")
       manyTill letter (string "}}") <* skipSpace
    

    现实世界的示例在括号文本之间会有其他字符,因此在每次解析后跳过“额外内容”(下一次解析不消耗任何 {{ 左大括号)将涉及更多内容。

    也许像下面这样会起作用:

    findFoos'' :: Parser String
    findFoos'' = do
        manyTill anyChar (string "{{")
        manyTill letter (string "}}") <* skipMany everythingExceptOpeningBraces
      where 
        -- is there a simpler / more efficient way of doing this?
        everythingExceptOpeningBraces =
            -- skip one or more non-braces
            (skip (/='{') *> skipWhile (/='{'))
            <|> 
            -- skip single brace followed by non-brace character
            (skip (=='{') *> skip (/='{'))
            <|>
            -- skip a brace at the very end 
            (skip (=='{') *> endOfInput)
    

    (但是,如果流中没有任何带括号的文本,则此解析器将失败。也许您可以构建一个Parser (Maybe Text),在这种情况下返回Nothing。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-07
      • 2020-10-19
      • 1970-01-01
      • 1970-01-01
      • 2017-06-27
      • 2017-06-25
      • 2016-01-03
      • 1970-01-01
      相关资源
      最近更新 更多