允许嵌套括号的解析在nom中的实现

4

我正在使用nom。 我想解析用括号括起来的字符串,并允许字符串中有额外嵌套的括号。

因此,(a + b)将解析为a + b,而((a + b))将解析为(a + b)

这对于第一种情况有效,但不适用于嵌套的情况:

pub fn parse_expr(input: &str) -> IResult<&str, &str> {
    // TODO: this will fail with nested parentheses, but `rest` doesn't seem to
    // be working.
    delimited(tag("("), take_until(")"), tag(")"))(input)
}

我尝试使用rest,但是这并没有考虑最终的)

pub fn parse_expr(input: &str) -> IResult<&str, &str> {
    delimited(tag("("), rest, tag(")"))(input)
}

感谢您!

1
input 在括号前面和/或后面会有其他表达式吗?例如,input 是否可能像这样:"(a + b) + (c + d)"? - Adam Comer
“(a + b) + (c + d)” 会失败。或者只解析“a + b”,并将“+ (c + d)”作为余数返回也可以。但是只有第一个带括号的表达式会被解析。 - Maximilian
1个回答

1
我在nom问题日志中发现了这个参考链接:https://github.com/Geal/nom/issues/1253 我正在使用从parse_hyperlinks中提取的函数,它是一个手写解析器,用于处理https://docs.rs/parse-hyperlinks/0.23.3/src/parse_hyperlinks/lib.rs.html#41页面的内容。
pub fn take_until_unbalanced(
    opening_bracket: char,
    closing_bracket: char,
) -> impl Fn(&str) -> IResult<&str, &str> {
    move |i: &str| {
        let mut index = 0;
        let mut bracket_counter = 0;
        while let Some(n) = &i[index..].find(&[opening_bracket, closing_bracket, '\\'][..]) {
            index += n;
            let mut it = i[index..].chars();
            match it.next().unwrap_or_default() {
                c if c == '\\' => {
                    // Skip the escape char `\`.
                    index += '\\'.len_utf8();
                    // Skip also the following char.
                    let c = it.next().unwrap_or_default();
                    index += c.len_utf8();
                }
                c if c == opening_bracket => {
                    bracket_counter += 1;
                    index += opening_bracket.len_utf8();
                }
                c if c == closing_bracket => {
                    // Closing bracket.
                    bracket_counter -= 1;
                    index += closing_bracket.len_utf8();
                }
                // Can not happen.
                _ => unreachable!(),
            };
            // We found the unmatched closing bracket.
            if bracket_counter == -1 {
                // We do not consume it.
                index -= closing_bracket.len_utf8();
                return Ok((&i[index..], &i[0..index]));
            };
        }

        if bracket_counter == 0 {
            Ok(("", i))
        } else {
            Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil)))
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接