diff --git a/src/parser/list.rs b/src/parser/list.rs index e15e8da2..d976f625 100644 --- a/src/parser/list.rs +++ b/src/parser/list.rs @@ -20,6 +20,12 @@ pub struct Node { parent: Option>>, } +impl Node { + pub fn get_data(&self) -> &T { + &self.data + } +} + // TODO: This Debug is only needed because of the try_unwrap+expect impl List { pub fn new() -> Self { @@ -72,6 +78,12 @@ impl List { (Some(me), Some(them)) => Rc::ptr_eq(me, them), } } + + pub fn iter(&self) -> impl Iterator>> { + NodeIter { + position: &self.head, + } + } } pub struct NodeIter<'a, T> { diff --git a/src/parser/nom_context.rs b/src/parser/nom_context.rs index 5fa6f978..e1bc2beb 100644 --- a/src/parser/nom_context.rs +++ b/src/parser/nom_context.rs @@ -1,9 +1,12 @@ +use std::rc::Rc; + use nom::bytes::complete::take; use nom::combinator::not; use nom::error::VerboseError; use nom::IResult; use super::list::List; +use super::list::Node; use super::token::Token; type Matcher = dyn for<'s> Fn(&'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>>; @@ -32,6 +35,10 @@ impl<'r, 's> ContextTree<'r, 's> { (popped_element, ContextTree { tree: remaining }) } + pub fn iter(&self) -> impl Iterator>>> { + self.tree.iter() + } + pub fn check_fail_matcher<'b>( &'r self, i: &'b str, diff --git a/src/parser/text_element_parser.rs b/src/parser/text_element_parser.rs index 5ba26c54..c0eae4ea 100644 --- a/src/parser/text_element_parser.rs +++ b/src/parser/text_element_parser.rs @@ -22,6 +22,8 @@ use super::text::TextElement; use super::token::Token; use super::Context; use nom::branch::alt; +use nom::bytes::complete::take; +use nom::combinator::cond; use nom::combinator::eof; use nom::combinator::map; use nom::combinator::not; @@ -118,11 +120,49 @@ pub fn context_paragraph_end<'s, 'r>( paragraph_end(input) } +fn can_start_bold<'s, 'r>(context: Context<'r, 's>) -> bool { + let mut context_iterator = context.iter().enumerate(); + loop { + if let Some((i, ctx)) = context_iterator.next() { + match ctx.get_data() { + ContextElement::FailMatcherNode(_) => {}, + ContextElement::PreviousElementNode(previous_element_node) => { + // TODO okay if previous element is a space but not if its text + match &previous_element_node.element { + Token::TextElement(text_element) => { + match text_element { + TextElement::Span(_) => return false, + TextElement::Space(_) => return true, + TextElement::LineBreak(_) => return true, + TextElement::Symbol(_) => return false, + TextElement::Bold(_) => return false, + TextElement::Link(_) => return false, + }; + }, + }; + }, + ContextElement::StartOfParagraph => { + return true; + }, + } + } else { + break; + } + } + false +} + pub fn context_bold_start<'s, 'r>( context: Context<'r, 's>, input: &'s str, ) -> Res<&'s str, &'s str> { - recognize(bold_start)(input) + if can_start_bold(context) { + recognize(bold_start)(input) + } else { + // TODO: Make this a custom error + not(take(0usize))(input)?; + unreachable!() + } } pub fn context_bold_end<'s, 'r>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> {