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

Dan*_*yer 7 haskell attoparsec

我正在转换使用Parsec的一些正常运行的Haskell代码,而不是使用Attoparsec以期获得更好的性能.我做了更改,所有内容都编译但我的解析器无法正常工作.

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

这些是我尝试过的两个主要变体.两者都有同样的问题.

items :: Parser [Item]
items = sepBy (comment <|> recordType1 <|> recordType2) endOfLine
Run Code Online (Sandbox Code Playgroud)

对于第二个,我更改了记录/注释解析器以使用行尾字符.

items :: Parser [Item]
items = manyTill (comment <|> recordType1 <|> recordType2) endOfInput
Run Code Online (Sandbox Code Playgroud)

我的方法有什么问题吗?还有其他方法可以实现我的目标吗?

Bry*_*van 6

如果编写一个attoparsec解析器,在失败之前消耗尽可能多的输入,则必须在输入结束时告知部分结果延续.

  • 那么`feed`实际上是处理这种情况的正确方法吗?在文档中使它更清晰一点可能是一个好主意 - 我知道当我第一次遇到它时它让我很困惑. (6认同)

Tra*_*own 3

我以前遇到过这个问题,我的理解是它是由<|>定义中的工作方式引起的sepBy

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

这只会在失败pure []时转移到(s *> scan),这不会仅仅因为您处于输入末尾而发生。

我的解决方案只是在 .返回的值上feed使用ByteString 进行调用。这可能是一种黑客攻击,但这似乎也是解决该问题的方法:emptyResultparseattoparsec-iteratee

f k (EOF Nothing)  = finalChunk $ feed (k S.empty) S.empty
Run Code Online (Sandbox Code Playgroud)

据我所知,这是attoparsec-iteratee在这里起作用的唯一原因,而普通的旧方法则parse不起作用。