我正在转换使用Parsec的一些功能正常的Haskell代码,而不是使用Attoparsec以期获得更好的性能。我做了更改,所有内容都编译但我的解析器无法正常工作。
我正在解析一个由各种记录类型组成的文件,每行一个。我用于解析记录或注释的每个函数都能正常工作,但是当我尝试编写一个函数来编译一系列记录时,解析器总是会返回一个部分结果,因为它需要更多的输入。
这是我尝试过的两个主要变体。两者都有同样的问题。
items :: Parser [Item]
items = sepBy (comment <|> recordType1 <|> recordType2) endOfLine
对于第二个,我更改了记录/评论解析器以使用行尾字符。
items :: Parser [Item]
items = manyTill (comment <|> recordType1 <|> recordType2) endOfInput
我的方法有什么问题吗?还有其他方法可以实现我的目标吗?
答案 0 :(得分:5)
如果编写一个attoparsec解析器,在失败之前消耗尽可能多的输入,则必须在输入结束时告知部分结果延续。
答案 1 :(得分:3)
之前我遇到过这个问题,我的理解是<|>
在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
ByteString调用parse
。这可能是一种黑客攻击,但它似乎也是attoparsec-iteratee
处理问题的方式:
f k (EOF Nothing) = finalChunk $ feed (k S.empty) S.empty
据我所知,这是attoparsec-iteratee
在这里工作而普通老parse
没有的唯一原因。
答案 2 :(得分:0)
你提供的信息很少,这就是为什么我觉得很难给你很好的帮助。但是我想提出几点意见: