具有相同分隔符的嵌套 sepBy1

Nested sepBy1 with same delimiter

#!/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

问题似乎出在sepBy1的实现上,因为parse pp "" "a\nb\n"也出现了错误。虽然我们期望这是 return 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)