pub fn left_assoc<I, E, O, OP, G, F, B>(
child: F,
operator: G,
builder: B,
) -> impl Parser<I, Output = O, Error = E>Expand description
Applies a parser multiple times separated by another parser.
It is similar to separated_list1 but instead of collecting
into a vector, you have a callback to build the output.
In a LALR grammar a left recursive operator is usually built with a rule syntax such as:
- A := A op B | B
If you try to parse that wth alt it will fail with a stack overflow
because the recusion is unlimited. This function solves this problem by converting the recusion
into an iteration.
Compare with a right recursive operator, that in LALR would be:
- A := B op A | B Or equivalently:
- A := B (op A)?
That can be written in nom trivially.
This stops when either parser returns an error and returns the last built value. to instead chain an error up, see
cut.
ยงArguments
childThe parser to apply.operatorParses the operator between argument.initA function returning the initial value.foldThe function that combines a result offwith the current accumulator.
use nom_language::precedence::left_assoc;
use nom::branch::alt;
use nom::sequence::delimited;
use nom::character::complete::{char, digit1};
fn add(i: &str) -> IResult<&str, String> {
left_assoc(mult, char('+'), |a, o, b| format!("{o}{a}{b}")).parse(i)
}
fn mult(i: &str) -> IResult<&str, String> {
left_assoc(single, char('*'), |a, o, b| format!("{o}{a}{b}")).parse(i)
}
fn single(i: &str) -> IResult<&str, String> {
alt((
digit1.map(|x: &str| x.to_string()),
delimited(char('('), add, char(')'))
)).parse(i)
}
assert_eq!(single("(1+2*3)"), Ok(("", String::from("+1*23"))));
assert_eq!(single("((1+2)*3)"), Ok(("", String::from("*+123"))));
assert_eq!(single("(1*2+3)"), Ok(("", String::from("+*123"))));
assert_eq!(single("((1+2*3)+4)"), Ok(("", String::from("++1*234"))));
assert_eq!(single("(1+(2*3+4))"), Ok(("", String::from("+1+*234"))));