了解attoparsec

时间:2010-08-27 16:05:44

标签: parsing haskell attoparsec

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? 有一些关于我可以学习的教程吗? 提前谢谢

1 个答案:

答案 0 :(得分:4)

this StackOverflow question的答案中,feed需要pointfree。正如Bryan O'Sullivan(Attoparsec的创始人)所说:

  

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

你可以通过输入一个空的字节串来实现这一点。

我承认我编写了有问题的代码,在这种情况下我实际上没有使用A.parse environment。简单的构图对我来说很有意义:你运行解析器(flip A.feed B.empty),你告诉它你完成了(Maybe),然后转换为maybeResult作为一种基本错误处理(parseEnvironment b = maybeResult $ A.feed (A.parse environment b) B.empty )。在我看来,这比尖头版本更清晰:

>>

其余的是我认为相当惯用的applicative parsing,虽然我不确定为什么我会使用*>代替{{1}}。