You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需自定义ErrorKind,如何为Nom解析器添加越界错误上下文?

解决方案:为Nom解析器添加错误上下文(无需自定义ErrorKind)

要在不自定义ErrorKind的前提下为错误添加“n越界”的上下文说明,你可以使用Nom提供的context组合子,或者直接构造关联上下文的错误返回。以下是两种可行的实现方式:

方法一:用context包裹验证逻辑(推荐)

context组合子可以为一段解析逻辑添加上下文描述,当内部逻辑失败时,错误信息会自动携带该上下文,让报错更清晰。

use nom::IResult;
use nom::bytes::complete::tag;
use nom::character::complete::digit1;
use nom::combinator::{context, err};
use nom::error::{Error, ErrorKind};

fn dup(s: &str) -> IResult<&str, u64> {
    let (s, _) = tag("dup")(s)?;
    // 用context包裹数字解析与验证逻辑,指定上下文描述
    let (s, n) = context("n越界", |input| {
        let (rest, n_str) = digit1(input)?;
        match n_str {
            "0" => Ok((rest, 0)),
            "1" => Ok((rest, 1)),
            "2" => Ok((rest, 2)),
            // 验证失败时返回标准Fail类型错误
            _ => err(Error::new(rest, ErrorKind::Fail)),
        }
    })(s)?;

    Ok((s, n))
}

方法二:手动构造带上下文的错误

如果不想额外包裹逻辑,也可以在错误分支直接返回关联上下文的错误,通过Nom的Error类型绑定位置信息:

use nom::IResult;
use nom::bytes::complete::tag;
use nom::character::complete::digit1;
use nom::err::Error;
use nom::error::ErrorKind;

fn dup(s: &str) -> IResult<&str, u64> {
    let (s, _) = tag("dup")(s)?;
    let (s, n_str) = digit1(s)?;

    let n = match n_str {
        "0" => 0,
        "1" => 1,
        "2" => 2,
        // 构造错误并绑定当前位置,配合外部上下文说明报错原因
        _ => return Err(nom::Err::Error(Error::new(s, ErrorKind::Fail))),
    };

    Ok((s, n))
}

补充说明

  • 使用context是最简洁的方案,无需修改错误类型,仅通过包裹逻辑就能为错误添加上下文。后续用nom::error::convert_error打印错误时,会直接显示“n越界”的描述。
  • 若需要更详尽的错误信息,可以将IResult的错误类型指定为VerboseError<&str>,这依然不需要自定义ErrorKind,但能在错误中包含更完整的上下文轨迹。

内容的提问来源于stack exchange,提问作者sshine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 15:05:20