嵌套的sepBy1具有相同的分隔符

时间:2017-01-24 16:23:43

标签: haskell parsec

#!/usr/bin/env runhaskell

import           Control.Applicative           ((<|>))
import           Text.Parsec.Char
import           Text.ParserCombinators.Parsec hiding (spaces, (<|>))

main :: IO ()
main = do
  print $ parse p "" "a\nb\n\nc\nd" where
  p  = sepBy1 (try pp) newline
  pp = sepBy1 l newline
  l  = many1 letter

我试图解析这个:

a
b

c
d

到此:[["a", "b"], ["c", "d"]]。我试图摆弄try,但它似乎没有效果。

这可能是非常基本的,请尝试解释你的答案中发生了什么(我是Haskell和Parsec的初学者)。

编辑:忘记添加错误消息。

Left (line 3, column 1):
unexpected "\n"
expecting letter

1 个答案:

答案 0 :(得分:2)

问题似乎是sepBy1的实现,因为即使parse pp "" "a\nb\n"也出现错误。虽然我们希望这会返回Right ["a","b"],但会引发相同的expected \n错误。

因此,sepBy1看起来像预期的那样工作,除非要解析的字符串以分隔符结束。这似乎是无害的,因为那个案例还有另一个解析器组合器。但是现在我们想要两个具有相同分隔符的嵌套sepBy1,这是一个问题。

我找到的唯一解决方案是编写自己的回溯sepBy1,并在内部情况下使用它。

main :: IO ()
main = print $ parse p "" "a\nb\n\nc\nd"
  where  pp = mySepBy1 l newline
         l  = many1 letter
         p  = sepBy1 pp (newline >> newline)

mySepBy1 parser separator = do
  x <- parser
  xs <- many (try $ separator >> parser)
  return (x:xs)