Wrote a plain list item parser.

This commit is contained in:
Tom Alexander 2023-03-25 14:23:52 -04:00
parent e6752b9d83
commit 422535fbe4
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
2 changed files with 39 additions and 4 deletions

View File

@ -0,0 +1,3 @@
1.
2.
3.

View File

@ -1,20 +1,26 @@
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::character::complete::digit1;
use nom::character::complete::one_of;
use nom::character::complete::space0; use nom::character::complete::space0;
use nom::combinator::eof; use nom::combinator::eof;
use nom::combinator::not; use nom::combinator::not;
use nom::combinator::recognize; use nom::combinator::recognize;
use nom::combinator::verify; use nom::combinator::verify;
use nom::multi::many0;
use nom::sequence::tuple; use nom::sequence::tuple;
use crate::parser::element::element;
use crate::parser::parser_context::ChainBehavior; use crate::parser::parser_context::ChainBehavior;
use crate::parser::parser_context::ContextElement; use crate::parser::parser_context::ContextElement;
use crate::parser::parser_context::ExitMatcherNode; use crate::parser::parser_context::ExitMatcherNode;
use crate::parser::util::get_consumed;
use crate::parser::util::start_of_line; use crate::parser::util::start_of_line;
use super::error::CustomError; use super::error::CustomError;
use super::error::MyError; use super::error::MyError;
use super::error::Res; use super::error::Res;
use super::lesser_element::Paragraph; use super::greater_element::PlainListItem;
use super::parser_with_context::parser_with_context; use super::parser_with_context::parser_with_context;
use super::util::non_whitespace_character; use super::util::non_whitespace_character;
use super::Context; use super::Context;
@ -23,18 +29,44 @@ use super::Context;
pub fn plain_list_item<'r, 's>( pub fn plain_list_item<'r, 's>(
context: Context<'r, 's>, context: Context<'r, 's>,
input: &'s str, input: &'s str,
) -> Res<&'s str, Paragraph<'s>> { ) -> Res<&'s str, PlainListItem<'s>> {
not(|i| context.check_exit_matcher(i))(input)?; not(|i| context.check_exit_matcher(i))(input)?;
start_of_line(context, input)?; start_of_line(context, input)?;
let (remaining, leading_whitespace) = space0(input)?; let (remaining, leading_whitespace) = space0(input)?;
// It is fine that we get the indent level using the number of bytes rather than the number of characters because nom's space0 only matches space and tab (0x20 and 0x09) // It is fine that we get the indent level using the number of bytes rather than the number of characters because nom's space0 only matches space and tab (0x20 and 0x09)
let indent_level = leading_whitespace.len(); let indent_level = leading_whitespace.len();
let list_item_context = context let parser_context = context
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
exit_matcher: ChainBehavior::AndParent(Some(&plain_list_item_end)), exit_matcher: ChainBehavior::AndParent(Some(&plain_list_item_end)),
})) }))
.with_additional_node(ContextElement::ListItem(indent_level)); .with_additional_node(ContextElement::ListItem(indent_level));
todo!()
let element_matcher = parser_with_context!(element)(&parser_context);
let (remaining, (bull, _ws)) = tuple((bullet, space0))(remaining)?;
let (remaining, contents) = many0(element_matcher)(remaining)?;
let source = get_consumed(input, remaining);
Ok((
remaining,
PlainListItem {
source,
bullet: bull,
contents,
},
))
}
fn bullet<'s>(i: &'s str) -> Res<&'s str, &'s str> {
alt((
tag("*"),
tag("-"),
tag("+"),
recognize(tuple((counter, alt((tag("."), tag(")")))))),
))(i)
}
fn counter<'s>(i: &'s str) -> Res<&'s str, &'s str> {
alt((recognize(one_of("abcdefghijklmnopqrstuvwxyz")), digit1))(i)
} }
fn plain_list_item_end<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { fn plain_list_item_end<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> {