【问题标题】:understanding attoparsec理解 attoparsec
【发布时间】:2010-08-27 16:05:44
【问题描述】:

有人建议我使用 attoparsec 来解析文件,现在我必须了解如何使用它; 有人给了我这段代码:

#

type Environment = M.Map String String 
import Data.Attoparsec (maybeResult)
import qualified Data.Attoparsec.Char8 as A
import qualified Data.ByteString.Char8 as B
environment :: A.Parser Environment
environment = M.fromList <$> A.sepBy entry A.endOfLine
parseEnvironment = maybeResult .flip A.feed B.empty . A.parse environment
spaces = A.many $ A.char ' '
entry = (,) <$> upTo ':' <*> upTo ';'
upTo delimiter = B.unpack <$> A.takeWhile (A.notInClass $ delimiter : " ")
                      <* (spaces >> A.char delimiter >> spaces)

效果很好,但我不知道为什么: 使用翻转的原因是什么,将A.feed的参数放在不同的顺序中不是更容易吗?为什么有B.empty? 有没有我可以学习的教程? 提前致谢

【问题讨论】:

  • 可能作者用了pointfree

标签: parsing haskell attoparsec


【解决方案1】:

this StackOverflow question 的答案中有对feed 需求的解释。正如 Bryan O'Sullivan(Attoparsec 的创建者)所说:

如果你编写一个 attoparsec 解析器 消耗尽可能多的输入 在失败之前,你必须告诉 部分结果延续时 您已完成输入。

你可以通过给它一个空的字节串来做到这一点。

我承认我写了有问题的代码,在这种情况下我实际上没有使用pointfree。简单的组合在这里对我来说很有意义:你运行解析器 (A.parse environment),告诉它你完成了 (flip A.feed B.empty),然后转换为 Maybe 作为一种基本的错误处理 (@987654328 @)。在我看来,这感觉比指出的版本更干净:

parseEnvironment b = maybeResult $ A.feed (A.parse environment b) B.empty

其余的是我认为相当惯用的applicative parsing,尽管我不确定为什么我会使用&gt;&gt; 而不是*&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多