pub fn left_rec<L: LexIt + Clone, T: Clone>(
state: &mut ParserState<'_, L>,
memo: &Memo<Cursor, Option<T>>,
parser: impl FnMut(&mut ParserState<'_, L>) -> Result<T, Error>,
) -> Result<T, Error>Expand description
Left recursion support.
Wrapping a parser in left_rec allows it to be left-recursive. This is
crucial for parsing left-recursive grammars, as recursive descent
parsers often fail to handle them.
The left_rec function solves this problem by employing memoization.
The algorithm used is based on this blog post.
fn parse(
state: &mut ParserState<CharLexer>,
memo: &Memo<Cursor, Option<String>>,
) -> Result<String, Error> {
left_rec(state, memo, |state| {
let fork = &mut state.fork();
if let Ok(mut s) = parse(fork, memo) {
state.advance_to(fork);
s.push(state.parse_char('b')?);
Ok(s)
} else {
state.parse_char('a').map(|_| String::from("a"))
}
})
}
let mut state = ParserState::new("abbbb");
assert_eq!(parse(&mut state, &Memo::default()).unwrap(), "abbbb");