Make a new naive implementation of plain_list.
This commit is contained in:
		
							parent
							
								
									e5e5120a10
								
							
						
					
					
						commit
						72d5f8f35c
					
				@ -14,8 +14,6 @@ use nom::multi::many_till;
 | 
			
		||||
use nom::sequence::preceded;
 | 
			
		||||
use nom::sequence::terminated;
 | 
			
		||||
use nom::sequence::tuple;
 | 
			
		||||
#[cfg(feature = "tracing")]
 | 
			
		||||
use tracing::span;
 | 
			
		||||
 | 
			
		||||
use super::greater_element::PlainList;
 | 
			
		||||
use super::greater_element::PlainListItem;
 | 
			
		||||
@ -42,97 +40,28 @@ pub fn plain_list<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s
 | 
			
		||||
            class: ExitClass::Beta,
 | 
			
		||||
            exit_matcher: &plain_list_end,
 | 
			
		||||
        }));
 | 
			
		||||
    let without_consume_context =
 | 
			
		||||
        parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false));
 | 
			
		||||
    let with_consume_context =
 | 
			
		||||
        parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true));
 | 
			
		||||
    let without_consume_matcher = parser_with_context!(plain_list_item)(&without_consume_context);
 | 
			
		||||
    let with_consume_matcher = parser_with_context!(plain_list_item)(&with_consume_context);
 | 
			
		||||
    let exit_matcher = parser_with_context!(exit_matcher_parser)(&with_consume_context);
 | 
			
		||||
    let mut children = Vec::new();
 | 
			
		||||
    let mut first_item_indentation: Option<usize> = None;
 | 
			
		||||
    let mut remaining = input;
 | 
			
		||||
 | 
			
		||||
    loop {
 | 
			
		||||
        /*
 | 
			
		||||
        Trailing whitespace belongs to the plain list, not the plain list item
 | 
			
		||||
 | 
			
		||||
        Possible outcomes:
 | 
			
		||||
        Don't consume, yes exit matcher
 | 
			
		||||
        Don't consume, no additional item
 | 
			
		||||
        Consume, additional item
 | 
			
		||||
         */
 | 
			
		||||
        {
 | 
			
		||||
            // Don't consume, yes exit matcher
 | 
			
		||||
            #[cfg(feature = "tracing")]
 | 
			
		||||
            let span = span!(tracing::Level::DEBUG, "first");
 | 
			
		||||
            #[cfg(feature = "tracing")]
 | 
			
		||||
            let _enter = span.enter();
 | 
			
		||||
 | 
			
		||||
            let last_item_then_exit = tuple((without_consume_matcher, exit_matcher))(remaining);
 | 
			
		||||
            match last_item_then_exit {
 | 
			
		||||
                Ok((remain, (item, _exit)))
 | 
			
		||||
                    if item.indentation
 | 
			
		||||
                        == *first_item_indentation.get_or_insert(item.indentation) =>
 | 
			
		||||
                {
 | 
			
		||||
                    remaining = remain;
 | 
			
		||||
                    children.push(item);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                Ok(_) | Err(_) => {}
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            // Consume, additional item
 | 
			
		||||
            #[cfg(feature = "tracing")]
 | 
			
		||||
            let span = span!(tracing::Level::DEBUG, "second");
 | 
			
		||||
            #[cfg(feature = "tracing")]
 | 
			
		||||
            let _enter = span.enter();
 | 
			
		||||
 | 
			
		||||
            let not_last_item =
 | 
			
		||||
                tuple((with_consume_matcher, peek(without_consume_matcher)))(remaining);
 | 
			
		||||
            match not_last_item {
 | 
			
		||||
                Ok((remain, (item, future_item)))
 | 
			
		||||
                    if item.indentation
 | 
			
		||||
                        == *first_item_indentation.get_or_insert(item.indentation)
 | 
			
		||||
                        && future_item.indentation
 | 
			
		||||
                            == *first_item_indentation.get_or_insert(item.indentation) =>
 | 
			
		||||
                {
 | 
			
		||||
                    remaining = remain;
 | 
			
		||||
                    children.push(item);
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                Ok(_) | Err(_) => {}
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            // Don't consume, no additional item
 | 
			
		||||
            #[cfg(feature = "tracing")]
 | 
			
		||||
            let span = span!(tracing::Level::DEBUG, "third");
 | 
			
		||||
            #[cfg(feature = "tracing")]
 | 
			
		||||
            let _enter = span.enter();
 | 
			
		||||
 | 
			
		||||
            let last_item_then_exit = without_consume_matcher(remaining);
 | 
			
		||||
            match last_item_then_exit {
 | 
			
		||||
                Ok((remain, item))
 | 
			
		||||
                    if item.indentation
 | 
			
		||||
                        == *first_item_indentation.get_or_insert(item.indentation) =>
 | 
			
		||||
                {
 | 
			
		||||
                    remaining = remain;
 | 
			
		||||
                    children.push(item);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                Ok(_) | Err(_) => {
 | 
			
		||||
                    // TODO: Maybe this is reachable when there are no items at all.
 | 
			
		||||
                    return Err(nom::Err::Error(CustomError::MyError(MyError(
 | 
			
		||||
                        "Should be unreachable.",
 | 
			
		||||
                    ))));
 | 
			
		||||
                    // unreachable!();
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        let maybe_exit = parser_with_context!(exit_matcher_parser)(&parser_context)(remaining);
 | 
			
		||||
        if maybe_exit.is_ok() {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        let list_item = parser_with_context!(plain_list_item)(&parser_context)(remaining);
 | 
			
		||||
        match list_item {
 | 
			
		||||
            Ok((remain, item))
 | 
			
		||||
                if item.indentation == *first_item_indentation.get_or_insert(item.indentation) =>
 | 
			
		||||
            {
 | 
			
		||||
                remaining = remain;
 | 
			
		||||
                children.push(item);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            Ok(_) | Err(_) => {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if children.is_empty() {
 | 
			
		||||
@ -141,6 +70,8 @@ pub fn plain_list<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s
 | 
			
		||||
        ))));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO: trailing whitespace
 | 
			
		||||
 | 
			
		||||
    let source = get_consumed(input, remaining);
 | 
			
		||||
    Ok((remaining, PlainList { source, children }))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user