我有一个NOM解析器,它可以解析字符串,但无法解析关键字.

当给定关键字时,下面的解析器会正确地失败.

但是,由于遇到关键字而导致失败的错误消息不会传播.

问题是,当label人失败时,many0(label)人成功了,但结果少了一个.随后,eof失败,因为并非所有内容都已解析.此操作会正确失败,但会丢失错误消息.

如何传播本地错误消息?

(See below code on 100.)

use nom::bytes::complete::{take_while, take_while1};
use nom::error::{VerboseError};
use nom::multi::{many0};
use nom::{IResult};
use nom::error::{context};
use nom::combinator::{eof, fail};

type ParseResult<'input, Out> = IResult<&'input str, Out, VerboseError<&'input str>>;

fn label(s1: &str) -> ParseResult<&str> {
    let (s2, a) = take_while1(|c: char| c.is_alphabetic())(s1)?;
    let (s3, _) = take_while(|c: char| c.is_whitespace())(s2)?;
    if a == "derp" {
        return context("this message is lost", fail)(s1);
    }
    Ok((s3, a))
}

fn parse(s: &str) -> ParseResult<Vec<&str>> {
    let (s, labels) = many0(label)(s)?;
    let (s, _) = eof(s)?;
    Ok((s, labels))
}

fn main() {
    println!("{:?}", parse("foo bar herp flerp"));
    // Ok(("", ["foo", "bar", "herp", "flerp"]))

    // This fails with Nom(Eof), both Nom(Fail) and context is lost
    println!("{:?}", parse("foo bar herp derp"));
    // Err(Error(VerboseError { errors: [("derp", Nom(Eof))] }))
}

推荐答案

在失败的情况下,您可以使用cut来防止many0来探索替代方案(消耗更少):

use nom::combinator::cut;
return cut(context("this message is lost", fail))(s1);

Playground

Rust相关问答推荐

为什么是!为Rust中的RwLockReadGuard和RwLockWriteGuard实现的发送特征?

为什么单元类型(空元组)实现了`Extend`trait?

在actix—web中使用Redirect或NamedFile响应

无法理解铁 rust &S错误处理

铁 rust 中的共享对象实现特征

如何用Axum/Tower压缩Html内容?

如何使用RefCell::JOYMOMTborrow 对 struct 不同字段的可变引用

如何从ruust中的fig.toml中读取?

为什么AsyncRead在Box上的实现有一个Unpin特征绑定?

减少指示ProgressBar在Rust中的开销

为什么 `Deref` 没有在 `Cell` 上实现?

为什么实现特征的对象期望比具体对象有更长的生命周期?

信号量释放后 Rust 输出挂起线程

Rust 中的复合 `HashSet` 操作或如何在 Rust 中获得 `HashSet` 的显式差异/并集

将泛型中的 Box 转换为 rust 中的 Box

从 HashMap>, _> 中删除的生命周期问题

在异步 Rust 中,Future 如何确保它只调用最近的 Waker?

试图理解 Rust 中的可变闭包

当特征函数依赖于为 Self 实现的通用标记特征时实现通用包装器

TinyVec 如何与 Vec 大小相同?