【问题标题】:How to distinguish between minus sign and negative number in nom?nom如何区分负号和负数?
【发布时间】:2019-08-20 14:07:50
【问题描述】:

使用解析器生成器nom,我如何编写一个解析器来提取术语1-21*-2 中减号的差异?

在第一个示例中,我期望令牌 1-2。在第二个中,“减号”表示负数。预期的令牌是1*-2。不是1*-2

如何使用用户定义的状态(例如 expect_literal: bool)使 nom 有状态?

【问题讨论】:

标签: rust parser-generator nom


【解决方案1】:

我目前找到的最佳解决方案是使用nom_locate,其跨度定义为

use nom_locate::LocatedSpanEx;

#[derive(Clone, PartialEq, Debug)]
struct LexState {
    pub accept_literal: bool,
}

type Span<'a> = LocatedSpanEx<&'a str, LexState>;

然后你可以通过修改状态

fn set_accept_literal(
    value: bool,
    code: IResult<Span, TokenPayload>,
) -> IResult<Span, TokenPayload> {
    match code {
        Ok(mut span) => {
            span.0.extra.accept_literal = value;
            Ok(span)
        }
        _ => code,
    }
}

TokenPayload 是一个枚举,代表我的令牌内容。

现在你可以编写运算符解析器了:

fn mathematical_operators(code: Span) -> IResult<Span, TokenPayload> {
    set_accept_literal(
        true,
        alt((
            map(tag("*"), |_| TokenPayload::Multiply),
            map(tag("/"), |_| TokenPayload::Divide),
            map(tag("+"), |_| TokenPayload::Add),
            map(tag("-"), |_| TokenPayload::Subtract),
            map(tag("%"), |_| TokenPayload::Remainder),
        ))(code),
    )
}

而整数解析器为:

fn parse_integer(code: Span) -> IResult<Span, TokenPayload> {
    let chars = "1234567890";
    // Sign ?
    let (code, sign) = opt(tag("-"))(code)?;
    let sign = sign.is_some();
    if sign && !code.extra.accept_literal {
        return Err(nom::Err::Error((code, ErrorKind::IsNot)));
    }
    let (code, slice) = take_while(move |c| chars.contains(c))(code)?;
    match slice.fragment.parse::<i32>() {
        Ok(value) => set_accept_literal(
            false,
            Ok((code, TokenPayload::Int32(if sign { -value } else { value }))),
        ),
        Err(_) => Err(nom::Err::Error((code, ErrorKind::Tag))),
    }
}

这可能不会赢得选美比赛,但它确实有效。剩下的部分应该是微不足道的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-16
    • 1970-01-01
    • 2020-01-15
    • 1970-01-01
    • 2017-02-07
    • 2017-03-25
    • 1970-01-01
    • 2019-04-06
    相关资源
    最近更新 更多