首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >三重解析器中故障信号的处理

三重解析器中故障信号的处理
EN

Stack Overflow用户
提问于 2016-03-21 21:35:30
回答 2查看 323关注 0票数 2

作为trifecta的一个实验,我编写了以下简单的函数:

代码语言:javascript
复制
filterParser :: (a -> Bool) -> Parser a -> Parser a
filterParser cond p = do
  a <- p
  if cond a 
    then return a 
    else unexpected "condition failed!"

其想法是能够向解析器添加一个条件。例如(假设谓词prime已经存在),您可以编写:filterParser prime integer来创建一个只接受素数的解析器。

对于单个分析,似乎没什么问题:

代码语言:javascript
复制
> parseString (filterParser (> 'm') letter) mempty "z"
> Success 'z

> parseString (filterParser (> 'm') letter) mempty "a"
> Failure (interactive):1:2: error: unexpected
> condition failed!

但与“很多”相比,这是行不通的:

代码语言:javascript
复制
> parseString (many $ filterParser (> 'm') letter) mempty "zzz2"
> Success "zzz"

> parseString (many $ filterParser (> 'm') letter) mempty "zzza"
> Failure (interactive):1:5: error: unexpected
> condition failed!

我希望最后一个例子也能返回Success "zzz"。对unexpected的调用似乎偏离了整个解析的轨道,这不是我想要的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-03-22 06:09:34

您需要通过使用filterParser使try恢复

代码语言:javascript
复制
import Text.Trifecta
import Control.Applicative

filterParser :: (a -> Bool) -> Parser a -> Parser a
filterParser cond p = try $ do
  x <- p
  if cond x then return x else empty

但是,这将消除自定义解析错误。通过在unexpected "Condition failed"分支中使用else来恢复这一点也没有帮助,因为try

相反,我们可以在try之后恢复自定义错误消息。

代码语言:javascript
复制
filterParser :: (a -> Bool) -> Parser a -> Parser a
filterParser cond p = (<|> unexpected "Condition failed") $ try $ do
  x <- p
  if cond x then return x else empty

这项工作如预期的那样:

代码语言:javascript
复制
*Main> parseString (many $ filterParser (> 'm') letter) mempty "zzza"
Success "zzz"

代码语言:javascript
复制
*Main> parseString (filterParser (> 'm') letter) mempty "a"
Failure (interactive):1:1: error: unexpected
    Condition failed
a<EOF> 
票数 1
EN

Stack Overflow用户

发布于 2016-03-22 14:41:00

除了仙人掌提出的解决办法外,还有以下几点:

代码语言:javascript
复制
filterParser :: (a -> Bool) -> Parser a -> Parser a
filterParser cond p = do
  a <- lookAhead p
  if cond a then p else unexpected "condition failed!"

这似乎给了我我想要的:

代码语言:javascript
复制
> parseString (filterParser (> 'm') letter) mempty "z"
> Success 'z'

> parseString (filterParser (> 'm') letter) mempty "4"
> Failure (interactive):1:1: error: expected: letter

> parseString (filterParser (> 'm') letter) mempty "a"
> Failure (interactive):1:1: error: unexpected
>     condition failed!

> parseString (many $ filterParser (> 'm') letter) mempty "zzz4"
> Success "zzz"

> parseString (many $ filterParser (> 'm') letter) mempty "zzza"
> Success "zzz"
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36142078

复制
相关文章

相似问题

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