Skip to content

Commit bcc1b0c

Browse files
committed
move the left_assoc combinator to nom-language
1 parent 9b0e18c commit bcc1b0c

File tree

2 files changed

+136
-136
lines changed

2 files changed

+136
-136
lines changed

nom-language/src/precedence/mod.rs

Lines changed: 136 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
mod tests;
55

66
use nom::error::{ErrorKind, FromExternalError, ParseError};
7-
use nom::{Err, IResult, Parser};
7+
use nom::{Check, Err, IResult, Input, Mode, OutputM, OutputMode, Parser};
88

99
/// An unary operator.
1010
pub struct Unary<V, Q: Ord + Copy> {
@@ -367,3 +367,138 @@ where
367367
}
368368
}
369369
}
370+
371+
/// Applies a parser multiple times separated by another parser.
372+
///
373+
/// It is similar to [`separated_list1`][crate::multi::separated_list1] but instead of collecting
374+
/// into a vector, you have a callback to build the output.
375+
///
376+
/// In a LALR grammar a left recursive operator is usually built with a rule syntax such as:
377+
/// * A := A op B | B
378+
///
379+
/// If you try to parse that wth [`alt`][crate::branch::alt] it will fail with a stack overflow
380+
/// because the recusion is unlimited. This function solves this problem by converting the recusion
381+
/// into an iteration.
382+
///
383+
/// Compare with a right recursive operator, that in LALR would be:
384+
/// * A := B op A | B
385+
/// Or equivalently:
386+
/// * A := B (op A)?
387+
///
388+
/// That can be written in `nom` trivially.
389+
///
390+
/// This stops when either parser returns [`err::error`] and returns the last built value. to instead chain an error up, see
391+
/// [`cut`][crate::combinator::cut].
392+
///
393+
/// # Arguments
394+
/// * `child` The parser to apply.
395+
/// * `operator` Parses the operator between argument.
396+
/// * `init` A function returning the initial value.
397+
/// * `fold` The function that combines a result of `f` with
398+
/// the current accumulator.
399+
/// ```rust
400+
/// # #[macro_use] extern crate nom;
401+
/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser};
402+
/// use nom::multi::left_assoc;
403+
/// use nom::branch::alt;
404+
/// use nom::sequence::delimited;
405+
/// use nom::character::complete::{char, digit1};
406+
///
407+
/// fn add(i: &str) -> IResult<&str, String> {
408+
/// left_assoc(mult, char('+'), |a, o, b| format!("{o}{a}{b}")).parse(i)
409+
/// }
410+
/// fn mult(i: &str) -> IResult<&str, String> {
411+
/// left_assoc(single, char('*'), |a, o, b| format!("{o}{a}{b}")).parse(i)
412+
/// }
413+
/// fn single(i: &str) -> IResult<&str, String> {
414+
/// alt((
415+
/// digit1.map(|x: &str| x.to_string()),
416+
/// delimited(char('('), add, char(')'))
417+
/// )).parse(i)
418+
/// }
419+
///
420+
/// assert_eq!(single("(1+2*3)"), Ok(("", String::from("+1*23"))));
421+
/// assert_eq!(single("((1+2)*3)"), Ok(("", String::from("*+123"))));
422+
/// assert_eq!(single("(1*2+3)"), Ok(("", String::from("+*123"))));
423+
/// assert_eq!(single("((1+2*3)+4)"), Ok(("", String::from("++1*234"))));
424+
/// assert_eq!(single("(1+(2*3+4))"), Ok(("", String::from("+1+*234"))));
425+
/// ```
426+
pub fn left_assoc<I, E, O, OP, G, F, B>(
427+
child: F,
428+
operator: G,
429+
builder: B,
430+
) -> impl Parser<I, Output = O, Error = E>
431+
where
432+
I: Clone + Input,
433+
E: ParseError<I>,
434+
F: Parser<I, Output = O, Error = E>,
435+
G: Parser<I, Output = OP, Error = E>,
436+
B: FnMut(O, OP, O) -> O,
437+
{
438+
LeftAssoc {
439+
child,
440+
operator,
441+
builder,
442+
}
443+
}
444+
445+
/// Parser implementation for the [separated_list1] combinator
446+
pub struct LeftAssoc<F, G, B> {
447+
child: F,
448+
operator: G,
449+
builder: B,
450+
}
451+
452+
impl<I, E, O, OP, G, F, B> Parser<I> for LeftAssoc<F, G, B>
453+
where
454+
I: Clone + Input,
455+
E: ParseError<I>,
456+
F: Parser<I, Output = O, Error = E>,
457+
G: Parser<I, Output = OP, Error = E>,
458+
B: FnMut(O, OP, O) -> O,
459+
{
460+
type Output = O;
461+
type Error = E;
462+
463+
fn process<OM: OutputMode>(
464+
&mut self,
465+
mut i: I,
466+
) -> nom::PResult<OM, I, Self::Output, Self::Error> {
467+
let (i1, mut res) = self.child.process::<OM>(i)?;
468+
i = i1;
469+
470+
loop {
471+
let len = i.input_len();
472+
match self
473+
.operator
474+
.process::<OutputM<OM::Output, Check, OM::Incomplete>>(i.clone())
475+
{
476+
Err(Err::Error(_)) => return Ok((i, res)),
477+
Err(Err::Failure(e)) => return Err(Err::Failure(e)),
478+
Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)),
479+
Ok((i1, op)) => {
480+
match self
481+
.child
482+
.process::<OutputM<OM::Output, Check, OM::Incomplete>>(i1.clone())
483+
{
484+
Err(Err::Error(_)) => return Ok((i, res)),
485+
Err(Err::Failure(e)) => return Err(Err::Failure(e)),
486+
Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)),
487+
Ok((i2, rhs)) => {
488+
// infinite loop check: the parser must always consume
489+
if i2.input_len() == len {
490+
return Err(Err::Error(OM::Error::bind(|| {
491+
<F as Parser<I>>::Error::from_error_kind(i, ErrorKind::SeparatedList)
492+
})));
493+
}
494+
// there is no combine() with 3 arguments, fake it with a tuple and two calls
495+
let op_rhs = OM::Output::combine(op, rhs, |op, rhs| (op, rhs));
496+
res = OM::Output::combine(res, op_rhs, |lhs, (op, rhs)| (self.builder)(lhs, op, rhs));
497+
i = i2;
498+
}
499+
}
500+
}
501+
}
502+
}
503+
}
504+
}

src/multi/mod.rs

Lines changed: 0 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,138 +1868,3 @@ where
18681868
Ok((input, acc))
18691869
}
18701870
}
1871-
1872-
/// Applies a parser multiple times separated by another parser.
1873-
///
1874-
/// It is similar to [`separated_list1`][crate::multi::separated_list1] but instead of collecting
1875-
/// into a vector, you have a callback to build the output.
1876-
///
1877-
/// In a LALR grammar a left recursive operator is usually built with a rule syntax such as:
1878-
/// * A := A op B | B
1879-
///
1880-
/// If you try to parse that wth [`alt`][crate::branch::alt] it will fail with a stack overflow
1881-
/// because the recusion is unlimited. This function solves this problem by converting the recusion
1882-
/// into an iteration.
1883-
///
1884-
/// Compare with a right recursive operator, that in LALR would be:
1885-
/// * A := B op A | B
1886-
/// Or equivalently:
1887-
/// * A := B (op A)?
1888-
///
1889-
/// That can be written in `nom` trivially.
1890-
///
1891-
/// This stops when either parser returns [`err::error`] and returns the last built value. to instead chain an error up, see
1892-
/// [`cut`][crate::combinator::cut].
1893-
///
1894-
/// # Arguments
1895-
/// * `child` The parser to apply.
1896-
/// * `operator` Parses the operator between argument.
1897-
/// * `init` A function returning the initial value.
1898-
/// * `fold` The function that combines a result of `f` with
1899-
/// the current accumulator.
1900-
/// ```rust
1901-
/// # #[macro_use] extern crate nom;
1902-
/// # use nom::{Err, error::ErrorKind, Needed, IResult, Parser};
1903-
/// use nom::multi::left_assoc;
1904-
/// use nom::branch::alt;
1905-
/// use nom::sequence::delimited;
1906-
/// use nom::character::complete::{char, digit1};
1907-
///
1908-
/// fn add(i: &str) -> IResult<&str, String> {
1909-
/// left_assoc(mult, char('+'), |a, o, b| format!("{o}{a}{b}")).parse(i)
1910-
/// }
1911-
/// fn mult(i: &str) -> IResult<&str, String> {
1912-
/// left_assoc(single, char('*'), |a, o, b| format!("{o}{a}{b}")).parse(i)
1913-
/// }
1914-
/// fn single(i: &str) -> IResult<&str, String> {
1915-
/// alt((
1916-
/// digit1.map(|x: &str| x.to_string()),
1917-
/// delimited(char('('), add, char(')'))
1918-
/// )).parse(i)
1919-
/// }
1920-
///
1921-
/// assert_eq!(single("(1+2*3)"), Ok(("", String::from("+1*23"))));
1922-
/// assert_eq!(single("((1+2)*3)"), Ok(("", String::from("*+123"))));
1923-
/// assert_eq!(single("(1*2+3)"), Ok(("", String::from("+*123"))));
1924-
/// assert_eq!(single("((1+2*3)+4)"), Ok(("", String::from("++1*234"))));
1925-
/// assert_eq!(single("(1+(2*3+4))"), Ok(("", String::from("+1+*234"))));
1926-
/// ```
1927-
pub fn left_assoc<I, E, O, OP, G, F, B>(
1928-
child: F,
1929-
operator: G,
1930-
builder: B,
1931-
) -> impl Parser<I, Output = O, Error = E>
1932-
where
1933-
I: Clone + Input,
1934-
E: ParseError<I>,
1935-
F: Parser<I, Output = O, Error = E>,
1936-
G: Parser<I, Output = OP, Error = E>,
1937-
B: FnMut(O, OP, O) -> O,
1938-
{
1939-
LeftAssoc {
1940-
child,
1941-
operator,
1942-
builder,
1943-
}
1944-
}
1945-
1946-
/// Parser implementation for the [separated_list1] combinator
1947-
pub struct LeftAssoc<F, G, B> {
1948-
child: F,
1949-
operator: G,
1950-
builder: B,
1951-
}
1952-
1953-
impl<I, E, O, OP, G, F, B> Parser<I> for LeftAssoc<F, G, B>
1954-
where
1955-
I: Clone + Input,
1956-
E: ParseError<I>,
1957-
F: Parser<I, Output = O, Error = E>,
1958-
G: Parser<I, Output = OP, Error = E>,
1959-
B: FnMut(O, OP, O) -> O,
1960-
{
1961-
type Output = O;
1962-
type Error = E;
1963-
1964-
fn process<OM: OutputMode>(
1965-
&mut self,
1966-
mut i: I,
1967-
) -> crate::PResult<OM, I, Self::Output, Self::Error> {
1968-
let (i1, mut res) = self.child.process::<OM>(i)?;
1969-
i = i1;
1970-
1971-
loop {
1972-
let len = i.input_len();
1973-
match self
1974-
.operator
1975-
.process::<OutputM<OM::Output, Check, OM::Incomplete>>(i.clone())
1976-
{
1977-
Err(Err::Error(_)) => return Ok((i, res)),
1978-
Err(Err::Failure(e)) => return Err(Err::Failure(e)),
1979-
Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)),
1980-
Ok((i1, op)) => {
1981-
match self
1982-
.child
1983-
.process::<OutputM<OM::Output, Check, OM::Incomplete>>(i1.clone())
1984-
{
1985-
Err(Err::Error(_)) => return Ok((i, res)),
1986-
Err(Err::Failure(e)) => return Err(Err::Failure(e)),
1987-
Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)),
1988-
Ok((i2, rhs)) => {
1989-
// infinite loop check: the parser must always consume
1990-
if i2.input_len() == len {
1991-
return Err(Err::Error(OM::Error::bind(|| {
1992-
<F as Parser<I>>::Error::from_error_kind(i, ErrorKind::SeparatedList)
1993-
})));
1994-
}
1995-
// there is no combine() with 3 arguments, fake it with a tuple and two calls
1996-
let op_rhs = OM::Output::combine(op, rhs, |op, rhs| (op, rhs));
1997-
res = OM::Output::combine(res, op_rhs, |lhs, (op, rhs)| (self.builder)(lhs, op, rhs));
1998-
i = i2;
1999-
}
2000-
}
2001-
}
2002-
}
2003-
}
2004-
}
2005-
}

0 commit comments

Comments
 (0)