如何通过nom解析匹配的分隔符?

时间:2019-09-19 13:09:18

标签: regex parsing rust nom

我想通过 nom 库将YMD日期解析为四种形式(“ 20190919”,“ 2019.09.19”,“ 2019-09-19”和“ 2019/09/19”)

我从iso8601解析器开始,该解析器仅解析“ YYYY-MM-DD”格式。而且,我尝试匹配分隔符并将其重新用于下一个匹配,例如在正则表达式(\d{4})([.-/]?)(\d{2})\2(\d{2})中。

原来该代码有效:

fn parse_ymd(i: &[u8]) -> IResult<&[u8], DateType> {
    let (i, y) = year(i)?;

    // Match separator if it exist.
    let (i, sep) = opt(one_of(".-/"))(i)?;

    let (i, m) = month(i)?;

    // If first separator was matched then try to find next one.
    let (i, _) = if let Some(sep) = sep {
        tag(&[sep as u8])(i)?
    } else {
        // Support the same signature as previous branch.
        (i, &[' ' as u8][..])
    };

    let (i, d) = day(i)?;

    Ok((
        i,
        DateType::YMD {
            year: y,
            month: m,
            day: d,
        },
    ))
}

但是显然看起来很奇怪。

有一些标称工具可以更合适地做到这一点吗?

(关于 nom 功能以及如何正确执行操作的问题。不仅仅是这个特定示例。)

1 个答案:

答案 0 :(得分:1)

您的解决方案足够不错。我只能提供一个真正的建议:

fn parse_ymd(i: &[u8]) -> IResult<&[u8], DateType> {
    ...

    // If first separator was matched then try to find next one.
    let i = match sep {
        Some(sep) => tag(&[sep as u8])(i)?.0,
        _ => i,
    };

    ...
}

您可能不熟悉直接访问元组元素的语法。来自rust book

  

除了通过模式匹配进行结构分解之外,我们还可以通过使用句点(。)和要访问的值的索引直接访问元组元素。

在这种情况下,它可以省去尝试匹配两个手臂的签名的笨拙。