首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >平衡括号的Parsec

平衡括号的Parsec
EN

Stack Overflow用户
提问于 2018-04-13 20:39:10
回答 1查看 685关注 0票数 2

作为学习使用Parsec的一个练习,我正在编写一个验证平衡括号的解析器。我只担心对()[]{},但不能让我的解析器处理第一个内的多个括号组。

我正在针对从托架推杆练习中从exercism.io中提取的许多测试用例进行测试,但值得注意的边缘案例是:

代码语言:javascript
复制
isBalanced "" = True
isBalanced "(some[nonsense]with)brackets" = True
isBalanced "}{" = False   -- reversed brackets no good.
isBalanced "{}}" = False  -- extra ending brackets no good either.

我的解析器看起来像:

代码语言:javascript
复制
import Text.Parsec
import Text.Parsec.Char

hasMatchingBrackets = go >> eof
  where
  go = skipMany (noneOf "[{()}]")
        >> optional (
           between (char '(') (char ')') go
       <|> between (char '{') (char '}') go
       <|> between (char '[') (char ']') go )
        >> skipMany (noneOf "[{()}]")

isBalanced :: String -> Bool
isBalanced xs = case parse hasMatchingBrackets "isBalanced" xs of
                  Right _ -> True
                  Left  _ -> False

我的解析器是-is,适用于上述所有情况,但下面的测试用例应该通过。

代码语言:javascript
复制
isBalanced "([{}({}[])])" = True  -- Fails with the parser above!

我已经发现了这个问题,因为我对between的修改只允许在两个括号之间出现一个go,而[{}(...中的open产生了两个,但我不知道如何修复它。我试着在skipMany1面前拍go,读到

代码语言:javascript
复制
    between (char '(') (char ')') (skipMany1 go)
<|> ...etc

但我知道错误是:

*例外: Text.ParserCombinators.Parsec.Prim.many: combinator‘多’被应用于接受空字符串的解析器。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-13 20:49:08

使用many是正确的解决方案,但您需要首先摆脱optional

问题是,正如错误消息所述,optional可以匹配空字符串,问题是只要给定的解析器仍能找到匹配,many就会重复匹配。如果解析器与空字符串匹配,它将始终找到匹配(空字符串),因此它将永远不会停止循环。因此,这是不允许的,以防止无限循环。

因为many已经可以匹配零次,所以不需要optional,所以您可以直接摆脱它。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49824802

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档