代码之家  ›  专栏  ›  技术社区  ›  Dan Dyer

使用Attoparsec时输入不完整的问题

  •  7
  • Dan Dyer  · 技术社区  · 14 年前

    我正在将一些使用Parsec的Haskell代码转换为使用Attoparsec,以期获得更好的性能。我已经做了修改,所有的东西都编译了,但是我的解析器不能正常工作。

    我正在解析一个文件,该文件由各种记录类型组成,每行一个。我的每个用于解析记录或注释的函数都正常工作,但是当我试图编写一个函数来编译一系列记录时,解析器总是返回一个部分结果,因为它需要更多的输入。

    这是我尝试过的两个主要变体。两者都有相同的问题。

    items :: Parser [Item]
    items = sepBy (comment <|> recordType1 <|> recordType2) endOfLine
    

    items :: Parser [Item]
    items = manyTill (comment <|> recordType1 <|> recordType2) endOfInput
    

    我的方法有什么问题吗?有没有其他方法可以达到我的目的?

    3 回复  |  直到 14 年前
        1
  •  3
  •   Travis Brown    14 年前

    我以前遇到过这个问题,我的理解是它是由 <|> 作品的定义 sepBy

    sepBy1 :: Alternative f => f a -> f s -> f [a]
    sepBy1 p s = scan
        where scan = liftA2 (:) p ((s *> scan) <|> pure [])
    

    这只会移动到 pure [] 一旦 (s *> scan)

    我的解决办法就是打电话 feed 带着一个 empty Result 退回人 parse . 这可能是一种黑客行为,但似乎也是这样 attoparsec-iteratee 处理问题:

    f k (EOF Nothing)  = finalChunk $ feed (k S.empty) S.empty
    

    据我所知这是 阿托帕塞克迭代 解析 不。

        2
  •  6
  •   Bryan O'Sullivan    14 年前

        3
  •  0
  •   I GIVE CRAP ANSWERS    14 年前

    你提供的信息很少,所以我认为很难给你好的帮助。不过,我想提出几点意见:

    • 也许解析器没有意识到输入已经完成,它依赖于获取一个EOL或另一个记录。因此它要求部分结果。试着给它喂食等同于下线的食物,希望它能强迫它。
    • 我记不清代码了,但是使用替代实例可能对解析性能有害。如果是这样的话,您可能需要对注释和记录类型设置case。
    • 我使用谷类进行大量的二进制解析,而且速度非常快。不过,attoparsec作为文本解析器似乎更好。你绝对应该考虑这个选择。
    • 另一种选择是长期使用基于iteratee的IO。johnlato在最新的monad reader(我相信是第16期)上发表了一篇关于iteratees的优秀文章。行尾条件是要发出信号的迭代器。但是要注意,iteratee类型非常令人生畏,需要一些时间来适应。
    推荐文章