如何合并多个解析器?

问题描述 投票:-1回答:2

为什么此解析器失败以及如何解决?

λ> str1 = string "elif "
λ> str2 = string "else "
λ> strs = (,) <$> many str1 <*> optionMaybe str2
λ> parse strs "" "elif elif elif else "
Left (line 1, column 16):
unexpected "s"
expecting "elif "

如何组合many解析器和optionalMaybe解析器?

parsing haskell functional-programming parsec
2个回答
0
投票

问题是,string "elif "会吃掉el中的else,并且由于它已经消耗了输入,因此不会回溯,而会抱怨意外的s

最简单的解决方法是允许使用try进行回溯:

str1 = try $ string "elif "

0
投票

另一个答案显示了使用try的简单解决方法。但是,这的确增加了成本,即引入了回溯。在此答案中,我介绍了没有回溯的另一种解决方案,因此,该解决方案应该更快一些并且使用更少的内存。基本思想是解析共享前缀,然后在我们碰到两件事实际上有所不同的部分时调度。因此:

strs = (string "el" *> (elseParser <|> elifParser)) <|> pure ([], Nothing) where
    elseParser = ([], Just "else ") <$ string "se "
    elifParser = liftA2
        (\_ (elifs, elses) -> ("elif ":elifs, elses))
        (string "if ")
        strs

为简单起见,我在结果中使用了恒定的"else ""elif "字符串,但这些字符串可以由string解析器的部分结果构建而成,并需要额外的布线。

© www.soinside.com 2019 - 2024. All rights reserved.