0

我正在按照本教程在 Haskell 中实现 Parser Combinators (a la parsec)。我实现了这篇文章中提到的所有 NanoParsec。

几个小时以来,我正在努力实施

-- try p. If p fails continue without consuming anything
try :: Parser a -> Parser a
try p = ...

-- Parser for everything, until the character-sequence stop appears. 
-- If stop does not appear at all: fail
untilStop :: String -> Parser String
untilStop stop = ...

我实现的最佳尝试untilStop看起来有点像这样,但不太奏效

untilStop :: String -> Parser String
untilStop (c : cs) = do
  s <- some $ satisfy (/= d)
  string (c : cs) <|> do
    i <- item
    untilStop (d : ds)
  -- maybe use msum from MonadPlus to combine?

我不知道如何组合si并且递归调用没有失败,因为string没有把所有东西放在一起。

我想一旦我有了tryuntilStop应该是直截了当的。有人可以为我指出正确的方向或实施它(try)吗?

现在我还在学习 Monads、Applicative 和相关的东西,所以试图理解 parsec 的源代码对我来说是不可能的。

4

1 回答 1

1

正如我在评论中所说,我认为您不需要类似 Parsec 的try.

对于untilStop,请检查:

untilStop :: String -> Parser String
untilStop [] = everything
untilStop (c:cs) = item >>= fun
  where fun i = do { s <- untilStop cs;
                     if i == c && s == "" then return "" else failure } <|> do
                     s <- untilStop (c : cs)
                     return (i : s)

首先,如果停止字符串为空,则解析所有内容。在哪里everything

everything :: Parser String
everything = Parser (\inp -> [(inp,"")])

否则,如果它的形式是c:cs,则解析一个字符i并考虑两种情况:

  • 停止字符串就在解析流的前面(因为c == i与字符串的其余部分一起解析cs会给出一个空结果),然后返回“”。或者,

  • 它在溪流中的某个地方,所以你要进一步寻找它。

请注意,<|>运算符用于回溯。如果untilStop cs不是我们想要的,我们需要重新解析,使用untilStop (c:cs)

于 2017-01-01T15:21:52.787 回答