1

我有两个解析器parser1 :: Parser aparser2 :: Parser a.

我现在想解析一个a穿插它们的 s列表parser2

所需的签名类似于

interspersedParser :: Parser b -> Parser a -> Parser [a]

例如,如果Parser a解析'a'字符并Parser b解析'b'字符,那么interspersedParser应该解析

""
"a"
"aba"
"ababa"
...

我正在使用megaparsec。是否已经有一些行为像这样的组合器,我目前无法找到?

4

2 回答 2

3

在 parsec 中有一个sepBy解析器可以做到这一点。相同的解析器似乎也可以在 megaparsec 中使用:https ://hackage.haskell.org/package/megaparsec-4.4.0/docs/Text-Megaparsec-Combinator.html

于 2020-02-07T17:01:20.937 回答
3

当然,您可以使用sepBy,但这不仅仅是:

interspersedParser sepP thingP = (:) <$> thingP <*> many (sepP *> thingP)

编辑:哦,这至少需要一件事。你也想要空的,所以<|> pure []在最后贴上一个。

事实上,这基本上是如何实现sepBy1的(其中一种变体sepBy至少需要一个):

-- | @sepBy p sep@ parses /zero/ or more occurrences of @p@, separated
-- by @sep@. Returns a list of values returned by @p@.
--
-- > commaSep p = p `sepBy` comma

sepBy :: Alternative m => m a -> m sep -> m [a]
sepBy p sep = sepBy1 p sep <|> pure []
{-# INLINE sepBy #-}

-- | @sepBy1 p sep@ parses /one/ or more occurrences of @p@, separated
-- by @sep@. Returns a list of values returned by @p@.

sepBy1 :: Alternative m => m a -> m sep -> m [a]
sepBy1 p sep = (:) <$> p <*> many (sep *> p)
{-# INLINE sepBy1 #-}
于 2020-02-07T17:09:12.167 回答