use super::parser_context::ContextElement; use super::parser_context::PreviousElementNode; use super::token::Token; use super::Context; use nom::error::ErrorKind; use nom::error::ParseError; use nom::IResult; use nom::InputLength; pub fn context_many1<'r, 's, I, O, E, M>( context: Context<'r, 's>, mut many_matcher: M, ) -> impl FnMut(I) -> IResult>, E> + 'r where I: Clone + InputLength, E: ParseError, M: for<'x> Fn(Context<'x, 's>, I) -> IResult + 'r, O: Into>, { move |mut i: I| { let mut err = None; // TODO: Can I eliminate the clone? I think this is incrementing the reference count let mut current_context = context.clone(); // Despite the clone, the Rc should still point to the same value. assert!(current_context.ptr_eq(context)); loop { match many_matcher(¤t_context, i.clone()) { Ok((remaining, many_elem)) => { current_context = current_context.with_additional_node( ContextElement::PreviousElementNode(PreviousElementNode { element: many_elem.into(), }), ); i = remaining; } the_error @ Err(_) => { err = Some(the_error); break; } } } let mut elements: Vec> = current_context .into_iter_until(context) .filter_map(|context_element| match context_element { ContextElement::PreviousElementNode(elem) => Some(elem.element), ContextElement::ExitMatcherNode(_) => None, ContextElement::Context(_) => None, ContextElement::StartOfParagraph => None, ContextElement::ListItem(_) => None, }) .collect(); if elements.is_empty() { if let Some(err) = err { err?; } } elements.reverse(); Ok((i, elements)) } } pub fn context_many_till<'r, 's, I, O, E, F, M, T>( context: Context<'r, 's>, mut many_matcher: M, mut till_matcher: T, ) -> impl FnMut(I) -> IResult>, F), E> + 'r where I: Clone + InputLength, E: ParseError, M: for<'x> Fn(Context<'x, 's>, I) -> IResult + 'r, T: for<'x> Fn(Context<'x, 's>, I) -> IResult + 'r, O: Into>, { move |mut i: I| { // TODO: Can I eliminate the clone? I think this is incrementing the reference count let mut current_context = context.clone(); // Despite the clone, the Rc should still point to the same value, otherwise we'll get stuck in an endless loop. assert!(current_context.ptr_eq(context)); loop { let len = i.input_len(); match till_matcher(¤t_context, i.clone()) { Ok((remaining, finish)) => { let mut ret = Vec::new(); while !current_context.ptr_eq(context) { let (context_element, next_context) = current_context.pop_front(); let context_element = context_element.expect("We only pop off context elements created in this function, so they are all Some()"); current_context = next_context; match context_element { ContextElement::ExitMatcherNode(_) => {} ContextElement::StartOfParagraph => {} ContextElement::Context(_) => {} ContextElement::PreviousElementNode(PreviousElementNode { element: token, }) => { ret.push(token); } ContextElement::ListItem(_) => {} }; } ret.reverse(); return Ok((remaining, (ret, finish))); } Err(nom::Err::Error(_)) => { match many_matcher(¤t_context, i.clone()) { Err(nom::Err::Error(err)) => { return Err(nom::Err::Error(E::append(i, ErrorKind::ManyTill, err))) } Err(e) => return Err(e), Ok((remaining, many_elem)) => { // infinite loop check: the parser must always consume if remaining.input_len() == len { return Err(nom::Err::Error(E::from_error_kind( remaining, ErrorKind::ManyTill, ))); } current_context = current_context.with_additional_node( ContextElement::PreviousElementNode(PreviousElementNode { element: many_elem.into(), }), ); i = remaining; } } } Err(e) => return Err(e), }; } } }