单子解析器中的否定前瞻(notFollowedBy)实现问题咨询
实现单子解析器中
notFollowedBy函数的解决方案 老哥,我之前折腾单子解析器的时候也踩过这个坑!你要实现的notFollowedBy核心就是反转shouldFail的ExceptT结果对吧?给你捋捋具体的实现思路和代码:
首先得明确notFollowedBy的核心逻辑:它接收一个解析器p,如果p成功匹配了输入,那notFollowedBy就得失败;如果p匹配失败,那notFollowedBy就成功,而且绝对不能消耗任何输入——这是否定前瞻的关键特性。
基于ExceptT的结构,你可以这么写实现:
notFollowedBy :: Monad m => Parser m a -> Parser m () notFollowedBy p = do -- 第一步:先保存当前的解析状态(输入位置、剩余输入这些) currentState <- getParserState -- 运行目标解析器p,拿到ExceptT的结果 parseResult <- runExceptT $ runParser p -- 第二步:恢复之前的解析状态,确保输入完全没被消耗 putParserState currentState -- 第三步:反转结果判断 case parseResult of -- 如果p成功匹配了,那notFollowedBy就要抛出错误 Right _ -> throwError "notFollowedBy failed: unexpected token detected" -- 如果p匹配失败了,那notFollowedBy就成功返回空单元 Left _ -> pure ()
这里有几个必须注意的点:
- 一定要保存并恢复解析状态:否定前瞻只是“预判”,不能改变原有的解析位置,否则会影响后续的解析逻辑
- 直接通过
runExceptT的结果反转判断:你提到的shouldFail其实就是检查runExceptT的结果是否为Left,这里我们直接处理结果就行,不用额外封装(如果你的代码里已经有shouldFail,也可以替换成shouldFail p >>= \isFailed -> if isFailed then pure () else throwError ...) - 如果你的解析器框架支持原子操作,最好把
p限制为原子解析器(比如单个字符、固定关键字),避免回溯带来的意外问题
内容的提问来源于stack exchange,提问作者Bailey Parker
相关产品推荐
相关产品推荐

