diff --git a/src/parser/list.rs b/src/parser/list.rs index 3266ca0..27bc998 100644 --- a/src/parser/list.rs +++ b/src/parser/list.rs @@ -1,183 +1,66 @@ use std::fmt::Debug; -use std::rc::Rc; - -#[derive(Debug)] -pub struct List { - head: Option>>, -} - -impl Clone for List { - fn clone(&self) -> Self { - List { - head: self.head.clone(), - } - } -} #[derive(Debug, Clone)] -pub struct Node { +pub struct List<'parent, T> { data: T, - parent: Option>>, + parent: Link<'parent, T>, } -impl Node { +type Link<'parent, T> = Option<&'parent List<'parent, T>>; + +impl<'parent, T> List<'parent, T> { + pub fn new(first_item: T) -> Self { + Self { + data: first_item, + parent: None, + } + } + pub fn get_data(&self) -> &T { &self.data } + + pub fn get_parent(&'parent self) -> Link<'parent, T> { + self.parent + } + + pub fn iter(&self) -> Iter<'_, T> { + Iter { next: Some(self) } + } } -impl List { - pub fn new() -> Self { - List { head: None } - } +pub trait ListType<'parent, T> { + fn push(&'parent self, item: T) -> List<'parent, T>; +} - pub fn branch_from(trunk: &Rc>) -> Self { - List { - head: Some(trunk.clone()), - } - } - - pub fn push_front(&self, data: T) -> List { - List { - head: Some(Rc::new(Node { - data: data, - parent: self.head.clone(), - })), - } - } - - pub fn pop_front(&mut self) -> (Option, List) { - match self.head.take() { - None => (None, List::new()), - Some(popped_node) => { - let extracted_node = match Rc::try_unwrap(popped_node) { - Ok(node) => node, - Err(_) => panic!("try_unwrap failed on Rc in pop_front on List."), - }; - ( - Some(extracted_node.data), - List { - head: extracted_node.parent, - }, - ) - } - } - } - - #[allow(dead_code)] - pub fn without_front(&self) -> List { - List { - head: self.head.as_ref().map(|node| node.parent.clone()).flatten(), - } - } - - #[allow(dead_code)] - pub fn get_data(&self) -> Option<&T> { - self.head.as_ref().map(|rc_node| &rc_node.data) - } - - #[allow(dead_code)] - pub fn is_empty(&self) -> bool { - self.head.is_none() - } - - pub fn ptr_eq(&self, other: &List) -> bool { - match (self.head.as_ref(), other.head.as_ref()) { - (None, None) => true, - (None, Some(_)) | (Some(_), None) => false, - (Some(me), Some(them)) => Rc::ptr_eq(me, them), - } - } - - pub fn iter(&self) -> impl Iterator>> { - NodeIter { - position: &self.head, - } - } - - #[allow(dead_code)] - pub fn iter_until<'a>(&'a self, other: &'a List) -> impl Iterator>> { - NodeIterUntil { - position: &self.head, - stop: &other.head, - } - } - - #[allow(dead_code)] - pub fn into_iter_until<'a>(self, other: &'a List) -> impl Iterator + 'a { - NodeIntoIterUntil { - position: self, - stop: &other, +impl<'parent, T> ListType<'parent, T> for List<'parent, T> { + fn push(&'parent self, item: T) -> Self { + Self { + data: item, + parent: Some(self), } } } -pub struct NodeIter<'a, T> { - position: &'a Option>>, +impl<'parent, T> ListType<'parent, T> for Link<'parent, T> { + fn push(&'parent self, item: T) -> List<'parent, T> { + List { + data: item, + parent: *self, + } + } } -impl<'a, T> Iterator for NodeIter<'a, T> { - type Item = &'a Rc>; +pub struct Iter<'a, T> { + next: Link<'a, T>, +} + +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; fn next(&mut self) -> Option { - let (return_value, next_position) = match &self.position { - None => return None, - Some(rc_node) => { - let next_position = &rc_node.parent; - let return_value = rc_node; - (return_value, next_position) - } - }; - self.position = next_position; - Some(return_value) - } -} - -pub struct NodeIterUntil<'a, T> { - position: &'a Option>>, - stop: &'a Option>>, -} - -impl<'a, T> Iterator for NodeIterUntil<'a, T> { - type Item = &'a Rc>; - - fn next(&mut self) -> Option { - match (self.position, self.stop) { - (_, None) => {} - (None, _) => {} - (Some(this_rc), Some(stop_rc)) => { - if Rc::ptr_eq(this_rc, stop_rc) { - return None; - } - } - }; - let (return_value, next_position) = match &self.position { - None => return None, - Some(rc_node) => { - let next_position = &rc_node.parent; - let return_value = rc_node; - (return_value, next_position) - } - }; - self.position = next_position; - Some(return_value) - } -} - -pub struct NodeIntoIterUntil<'a, T> { - position: List, - stop: &'a List, -} - -impl<'a, T> Iterator for NodeIntoIterUntil<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - if self.position.ptr_eq(self.stop) { - return None; - } - let (popped_element, new_position) = self.position.pop_front(); - self.position = new_position; - popped_element + let ret = self.next.map(|link| link.get_data()); + self.next = self.next.map(|link| link.get_parent()).flatten(); + ret } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 639af9a..abd42ab 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -110,4 +110,14 @@ pub use object::Timestamp; pub use object::Underline; pub use object::Verbatim; pub use source::Source; -type Context<'r, 's> = &'r parser_context::ContextTree<'r, 's>; + +use self::org_source::OrgSource; +use self::parser_context::Context; +use crate::error::Res; + +type RefContext<'r, 's> = &'r Context<'r, 's>; +trait ContextMatcher = + for<'r, 's> Fn(RefContext<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>>; +type DynContextMatcher<'c> = dyn ContextMatcher + 'c; +trait Matcher = for<'s> Fn(OrgSource<'s>) -> Res, OrgSource<'s>>; +type DynMatcher<'c> = dyn Matcher + 'c; diff --git a/src/parser/parser_context.rs b/src/parser/parser_context.rs index f4e72d5..670e99d 100644 --- a/src/parser/parser_context.rs +++ b/src/parser/parser_context.rs @@ -1,110 +1,96 @@ -use std::rc::Rc; - -use nom::combinator::eof; -use nom::IResult; - use super::list::List; -use super::list::Node; -use super::org_source::OrgSource; -use super::Context; +use super::DynContextMatcher; use super::Object; -use crate::error::CustomError; -use crate::error::MyError; -use crate::error::Res; use crate::parser::exiting::ExitClass; +use crate::parser::list::ListType; -type Matcher = - dyn for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>>; +// type Matcher = +// dyn for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>>; -#[derive(Debug, Clone)] -pub struct ContextTree<'r, 's> { - tree: List>, -} +// #[derive(Debug, Clone)] +// pub struct ContextTree<'r, 's> { +// tree: List>, +// } -impl<'r, 's> ContextTree<'r, 's> { - pub fn new() -> Self { - ContextTree { tree: List::new() } - } +// impl<'r, 's> ContextTree<'r, 's> { +// pub fn new() -> Self { +// ContextTree { tree: List::new() } +// } - pub fn branch_from(trunk: &Rc>>) -> Self { - ContextTree { - tree: List::branch_from(trunk), - } - } +// pub fn branch_from(trunk: &Rc>>) -> Self { +// ContextTree { +// tree: List::branch_from(trunk), +// } +// } - #[allow(dead_code)] - pub fn ptr_eq<'x, 'y>(&self, other: &ContextTree<'x, 'y>) -> bool { - self.tree.ptr_eq(&other.tree) - } +// #[allow(dead_code)] +// pub fn ptr_eq<'x, 'y>(&self, other: &ContextTree<'x, 'y>) -> bool { +// self.tree.ptr_eq(&other.tree) +// } - pub fn with_additional_node(&self, data: ContextElement<'r, 's>) -> ContextTree<'r, 's> { - let new_list = self.tree.push_front(data); - ContextTree { tree: new_list } - } +// pub fn with_additional_node(&self, data: ContextElement<'r, 's>) -> ContextTree<'r, 's> { +// let new_list = self.tree.push_front(data); +// ContextTree { tree: new_list } +// } - pub fn iter(&self) -> impl Iterator>>> { - self.tree.iter() - } +// pub fn iter(&self) -> impl Iterator>>> { +// self.tree.iter() +// } - #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] - pub fn check_exit_matcher( - &'r self, - i: OrgSource<'s>, - ) -> IResult, OrgSource<'s>, CustomError>> { - // Special check for EOF. We don't just make this a document-level exit matcher since the IgnoreParent ChainBehavior could cause early exit matchers to not run. - let at_end_of_file = eof(i); - if at_end_of_file.is_ok() { - return at_end_of_file; - } +// #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] +// pub fn check_exit_matcher( +// &'r self, +// i: OrgSource<'s>, +// ) -> IResult, OrgSource<'s>, CustomError>> { +// // Special check for EOF. We don't just make this a document-level exit matcher since the IgnoreParent ChainBehavior could cause early exit matchers to not run. +// let at_end_of_file = eof(i); +// if at_end_of_file.is_ok() { +// return at_end_of_file; +// } - // let blocked_context = - // self.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - // exit_matcher: ChainBehavior::IgnoreParent(Some(&always_fail)), - // })); +// let mut current_class_filter = ExitClass::Gamma; +// for current_node in self.iter() { +// let context_element = current_node.get_data(); +// match context_element { +// ContextElement::ExitMatcherNode(exit_matcher) => { +// if exit_matcher.class as u32 <= current_class_filter as u32 { +// current_class_filter = exit_matcher.class; +// let local_context = ContextTree::branch_from(current_node); +// let local_result = (exit_matcher.exit_matcher)(&local_context, i); +// if local_result.is_ok() { +// return local_result; +// } +// } +// } +// _ => {} +// }; +// } +// // TODO: Make this a specific error instead of just a generic MyError +// return Err(nom::Err::Error(CustomError::MyError(MyError( +// "NoExit".into(), +// )))); +// } - let mut current_class_filter = ExitClass::Gamma; - for current_node in self.iter() { - let context_element = current_node.get_data(); - match context_element { - ContextElement::ExitMatcherNode(exit_matcher) => { - if exit_matcher.class as u32 <= current_class_filter as u32 { - current_class_filter = exit_matcher.class; - let local_context = ContextTree::branch_from(current_node); - let local_result = (exit_matcher.exit_matcher)(&local_context, i); - if local_result.is_ok() { - return local_result; - } - } - } - _ => {} - }; - } - // TODO: Make this a specific error instead of just a generic MyError - return Err(nom::Err::Error(CustomError::MyError(MyError( - "NoExit".into(), - )))); - } +// /// Indicates if elements should consume the whitespace after them. +// /// +// /// Defaults to true. +// pub fn should_consume_trailing_whitespace(&self) -> bool { +// self._should_consume_trailing_whitespace().unwrap_or(true) +// } - /// Indicates if elements should consume the whitespace after them. - /// - /// Defaults to true. - pub fn should_consume_trailing_whitespace(&self) -> bool { - self._should_consume_trailing_whitespace().unwrap_or(true) - } - - fn _should_consume_trailing_whitespace(&self) -> Option { - for current_node in self.iter() { - let context_element = current_node.get_data(); - match context_element { - ContextElement::ConsumeTrailingWhitespace(should) => { - return Some(*should); - } - _ => {} - } - } - None - } -} +// fn _should_consume_trailing_whitespace(&self) -> Option { +// for current_node in self.iter() { +// let context_element = current_node.get_data(); +// match context_element { +// ContextElement::ConsumeTrailingWhitespace(should) => { +// return Some(*should); +// } +// _ => {} +// } +// } +// None +// } +// } #[derive(Debug)] pub enum ContextElement<'r, 's> { @@ -126,7 +112,8 @@ pub enum ContextElement<'r, 's> { } pub struct ExitMatcherNode<'r> { - pub exit_matcher: &'r Matcher, + // TODO: Should this be "&'r DynContextMatcher<'c>" ? + pub exit_matcher: &'r DynContextMatcher<'r>, pub class: ExitClass, } @@ -137,3 +124,38 @@ impl<'r> std::fmt::Debug for ExitMatcherNode<'r> { formatter.finish() } } + +pub struct GlobalSettings<'s> { + placeholder: Option<&'s str>, +} + +impl<'s> GlobalSettings<'s> { + pub fn new() -> Self { + GlobalSettings { placeholder: None } + } +} + +pub struct Context<'r, 's> { + global_settings: &'s GlobalSettings<'s>, + tree: List<'r, ContextElement<'r, 's>>, +} + +impl<'r, 's> Context<'r, 's> { + pub fn new( + global_settings: &'s GlobalSettings<'s>, + tree: List<'r, ContextElement<'r, 's>>, + ) -> Self { + Context { + global_settings, + tree, + } + } + + pub fn push(&self, data: ContextElement<'r, 's>) -> Self { + let new_tree = self.tree.push(data); + Self { + global_settings: self.global_settings, + tree: new_tree, + } + } +}