解析允许 nom 中的嵌套括号
Parse allowing nested parentheses in nom
我正在使用 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)
}
谢谢!
我在 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)))
}
}
}
我正在使用 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)
}
谢谢!
我在 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)))
}
}
}