使用解析器组合器实现 try(先行)和 untilStop
Implementing try (look-ahead) and untilStop with parser combinators
我正在关注 this tutorial 在 Haskell 中实现解析器组合器(la parsec)。我实现了在此 post.
中提到的 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?
我不知道如何结合 s
、i
和递归调用而不失败,因为 string
没有把所有东西放在一起。
我想一旦有了 try
,untilStop
就应该很简单了。有人可以为我指明正确的方向或实施它 (try
) 吗?
现在我还在学习 Monads、Applicative 和相关的东西,所以试图理解 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
一起解析得到空结果),然后return“”。或者,
它在流中的某个地方,所以你进一步寻找它。
请注意,<|>
运算符用于回溯。如果 untilStop cs
不是我们想要的,我们需要 重新解析 ,改用 untilStop (c:cs)
。
我正在关注 this tutorial 在 Haskell 中实现解析器组合器(la parsec)。我实现了在此 post.
中提到的 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?
我不知道如何结合 s
、i
和递归调用而不失败,因为 string
没有把所有东西放在一起。
我想一旦有了 try
,untilStop
就应该很简单了。有人可以为我指明正确的方向或实施它 (try
) 吗?
现在我还在学习 Monads、Applicative 和相关的东西,所以试图理解 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
一起解析得到空结果),然后return“”。或者,它在流中的某个地方,所以你进一步寻找它。
请注意,<|>
运算符用于回溯。如果 untilStop cs
不是我们想要的,我们需要 重新解析 ,改用 untilStop (c:cs)
。