diff --git a/build.rs b/build.rs index d76733e..d920305 100644 --- a/build.rs +++ b/build.rs @@ -72,7 +72,7 @@ fn write_header(test_file: &mut File) { r#" #[feature(exit_status_error)] use organic::compare_document; -use organic::parser::document; +use organic::parser::parse; use organic::emacs_parse_anonymous_org_document; use organic::parser::sexp::sexp_with_padding; diff --git a/src/compare/diff.rs b/src/compare/diff.rs index 3f6e3d3..4402200 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -5,64 +5,64 @@ use super::util::assert_name; use super::util::get_property; use crate::parser::sexp::unquote; use crate::parser::sexp::Token; -use crate::parser::AngleLink; -use crate::parser::Bold; -use crate::parser::Citation; -use crate::parser::CitationReference; -use crate::parser::Clock; -use crate::parser::Code; -use crate::parser::Comment; -use crate::parser::CommentBlock; -use crate::parser::DiarySexp; -use crate::parser::Document; -use crate::parser::DocumentElement; -use crate::parser::Drawer; -use crate::parser::DynamicBlock; -use crate::parser::Element; -use crate::parser::Entity; -use crate::parser::ExampleBlock; -use crate::parser::ExportBlock; -use crate::parser::ExportSnippet; -use crate::parser::FixedWidthArea; -use crate::parser::FootnoteDefinition; -use crate::parser::FootnoteReference; -use crate::parser::GreaterBlock; -use crate::parser::Heading; -use crate::parser::HorizontalRule; -use crate::parser::InlineBabelCall; -use crate::parser::InlineSourceBlock; -use crate::parser::Italic; -use crate::parser::Keyword; -use crate::parser::LatexEnvironment; -use crate::parser::LatexFragment; -use crate::parser::LineBreak; -use crate::parser::Object; -use crate::parser::OrgMacro; -use crate::parser::Paragraph; -use crate::parser::PlainLink; -use crate::parser::PlainList; -use crate::parser::PlainListItem; -use crate::parser::PlainText; -use crate::parser::Planning; -use crate::parser::PropertyDrawer; -use crate::parser::RadioLink; -use crate::parser::RadioTarget; -use crate::parser::RegularLink; -use crate::parser::Section; -use crate::parser::Source; -use crate::parser::SrcBlock; -use crate::parser::StatisticsCookie; -use crate::parser::StrikeThrough; -use crate::parser::Subscript; -use crate::parser::Superscript; -use crate::parser::Table; -use crate::parser::TableCell; -use crate::parser::TableRow; -use crate::parser::Target; -use crate::parser::Timestamp; -use crate::parser::Underline; -use crate::parser::Verbatim; -use crate::parser::VerseBlock; +use crate::types::AngleLink; +use crate::types::Bold; +use crate::types::Citation; +use crate::types::CitationReference; +use crate::types::Clock; +use crate::types::Code; +use crate::types::Comment; +use crate::types::CommentBlock; +use crate::types::DiarySexp; +use crate::types::Document; +use crate::types::DocumentElement; +use crate::types::Drawer; +use crate::types::DynamicBlock; +use crate::types::Element; +use crate::types::Entity; +use crate::types::ExampleBlock; +use crate::types::ExportBlock; +use crate::types::ExportSnippet; +use crate::types::FixedWidthArea; +use crate::types::FootnoteDefinition; +use crate::types::FootnoteReference; +use crate::types::GreaterBlock; +use crate::types::Heading; +use crate::types::HorizontalRule; +use crate::types::InlineBabelCall; +use crate::types::InlineSourceBlock; +use crate::types::Italic; +use crate::types::Keyword; +use crate::types::LatexEnvironment; +use crate::types::LatexFragment; +use crate::types::LineBreak; +use crate::types::Object; +use crate::types::OrgMacro; +use crate::types::Paragraph; +use crate::types::PlainLink; +use crate::types::PlainList; +use crate::types::PlainListItem; +use crate::types::PlainText; +use crate::types::Planning; +use crate::types::PropertyDrawer; +use crate::types::RadioLink; +use crate::types::RadioTarget; +use crate::types::RegularLink; +use crate::types::Section; +use crate::types::Source; +use crate::types::SrcBlock; +use crate::types::StatisticsCookie; +use crate::types::StrikeThrough; +use crate::types::Subscript; +use crate::types::Superscript; +use crate::types::Table; +use crate::types::TableCell; +use crate::types::TableRow; +use crate::types::Target; +use crate::types::Timestamp; +use crate::types::Underline; +use crate::types::Verbatim; +use crate::types::VerseBlock; #[derive(Debug)] pub enum DiffEntry<'s> { diff --git a/src/compare/util.rs b/src/compare/util.rs index 94c7451..6367bf9 100644 --- a/src/compare/util.rs +++ b/src/compare/util.rs @@ -1,5 +1,5 @@ use crate::parser::sexp::Token; -use crate::parser::Source; +use crate::types::Source; /// Check if the child string slice is a slice of the parent string slice. fn is_slice_of(parent: &str, child: &str) -> bool { diff --git a/src/parser/exiting.rs b/src/context/exiting.rs similarity index 100% rename from src/parser/exiting.rs rename to src/context/exiting.rs diff --git a/src/context/global_settings.rs b/src/context/global_settings.rs new file mode 100644 index 0000000..b5f818b --- /dev/null +++ b/src/context/global_settings.rs @@ -0,0 +1,17 @@ +#[derive(Debug)] +pub struct GlobalSettings<'s> { + #[allow(dead_code)] + placeholder: Option<&'s str>, +} + +impl<'s> GlobalSettings<'s> { + pub fn new() -> Self { + GlobalSettings { placeholder: None } + } +} + +impl<'s> Default for GlobalSettings<'s> { + fn default() -> Self { + GlobalSettings::new() + } +} diff --git a/src/context/list.rs b/src/context/list.rs new file mode 100644 index 0000000..98ee212 --- /dev/null +++ b/src/context/list.rs @@ -0,0 +1,69 @@ +use std::fmt::Debug; + +#[derive(Debug, Clone)] +pub struct List<'parent, T> { + data: T, + parent: Link<'parent, T>, +} + +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) } + } + + pub fn iter_list(&self) -> IterList<'_, T> { + IterList { next: Some(self) } + } + + pub fn push(&'parent self, item: T) -> Self { + Self { + data: item, + parent: Some(self), + } + } +} + +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 ret = self.next.map(|link| link.get_data()); + self.next = self.next.map(|link| link.get_parent()).flatten(); + ret + } +} + +pub struct IterList<'a, T> { + next: Link<'a, T>, +} + +impl<'a, T> Iterator for IterList<'a, T> { + type Item = &'a List<'a, T>; + + fn next(&mut self) -> Option { + let ret = self.next; + self.next = self.next.map(|this| this.get_parent()).flatten(); + ret + } +} diff --git a/src/context/mod.rs b/src/context/mod.rs new file mode 100644 index 0000000..32e04f0 --- /dev/null +++ b/src/context/mod.rs @@ -0,0 +1,26 @@ +use crate::error::Res; +use crate::parser::OrgSource; + +mod exiting; +mod global_settings; +mod list; +mod parser_context; +mod parser_with_context; + +pub type RefContext<'b, 'g, 'r, 's> = &'b Context<'g, 'r, 's>; +pub trait ContextMatcher = for<'b, 'g, 'r, 's> Fn( + RefContext<'b, 'g, 'r, 's>, + OrgSource<'s>, +) -> Res, OrgSource<'s>>; +pub type DynContextMatcher<'c> = dyn ContextMatcher + 'c; +pub trait Matcher = for<'s> Fn(OrgSource<'s>) -> Res, OrgSource<'s>>; +#[allow(dead_code)] +pub type DynMatcher<'c> = dyn Matcher + 'c; + +pub use exiting::ExitClass; +pub use global_settings::GlobalSettings; +pub use list::List; +pub use parser_context::Context; +pub use parser_context::ContextElement; +pub use parser_context::ExitMatcherNode; +pub(crate) use parser_with_context::parser_with_context; diff --git a/src/parser/parser_context.rs b/src/context/parser_context.rs similarity index 54% rename from src/parser/parser_context.rs rename to src/context/parser_context.rs index f4e72d5..8b21c50 100644 --- a/src/parser/parser_context.rs +++ b/src/context/parser_context.rs @@ -1,76 +1,107 @@ -use std::rc::Rc; - use nom::combinator::eof; use nom::IResult; +use super::exiting::ExitClass; +use super::global_settings::GlobalSettings; use super::list::List; -use super::list::Node; -use super::org_source::OrgSource; -use super::Context; -use super::Object; +use super::DynContextMatcher; +use super::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::exiting::ExitClass; +use crate::parser::OrgSource; +use crate::types::Object; -type Matcher = - dyn for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>>; +#[derive(Debug)] +pub enum ContextElement<'r, 's> { + /// Stores a parser that indicates that children should exit upon matching an exit matcher. + ExitMatcherNode(ExitMatcherNode<'r>), -#[derive(Debug, Clone)] -pub struct ContextTree<'r, 's> { - tree: List>, + /// Stores the name of the current element to prevent directly nesting elements of the same type. + Context(&'r str), + + /// Indicates if elements should consume the whitespace after them. + ConsumeTrailingWhitespace(bool), + + /// The contents of a radio target. + /// + /// If any are found, this will force a 2nd parse through the + /// org-mode document since text needs to be re-parsed to look for + /// radio links matching the contents of radio targets. + RadioTarget(Vec<&'r Vec>>), } -impl<'r, 's> ContextTree<'r, 's> { - pub fn new() -> Self { - ContextTree { tree: List::new() } - } +pub struct ExitMatcherNode<'r> { + // TODO: Should this be "&'r DynContextMatcher<'c>" ? + pub exit_matcher: &'r DynContextMatcher<'r>, + pub class: ExitClass, +} - pub fn branch_from(trunk: &Rc>>) -> Self { - ContextTree { - tree: List::branch_from(trunk), +impl<'r> std::fmt::Debug for ExitMatcherNode<'r> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut formatter = f.debug_struct("ExitMatcherNode"); + formatter.field("class", &self.class.to_string()); + formatter.finish() + } +} + +#[derive(Debug)] +pub struct Context<'g, 'r, 's> { + global_settings: &'g GlobalSettings<'g>, + tree: List<'r, &'r ContextElement<'r, 's>>, +} + +impl<'g, 'r, 's> Context<'g, 'r, 's> { + pub fn new( + global_settings: &'g GlobalSettings<'g>, + tree: List<'r, &'r ContextElement<'r, 's>>, + ) -> Self { + Self { + global_settings, + 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(&'r self, new_element: &'r ContextElement<'r, 's>) -> Self { + let new_tree = self.tree.push(new_element); + Self::new(self.global_settings, new_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 iter(&self) -> impl Iterator>>> { + pub fn iter(&'r self) -> super::list::Iter<'r, &'r ContextElement<'r, 's>> { self.tree.iter() } + pub fn iter_context(&'r self) -> Iter<'g, 'r, 's> { + Iter { + next: self.tree.iter_list(), + global_settings: self.global_settings, + } + } + + pub fn get_parent(&'r self) -> Option { + self.tree.get_parent().map(|parent_tree| Self { + global_settings: self.global_settings, + tree: parent_tree.clone(), + }) + } + + pub fn get_data(&self) -> &ContextElement<'r, 's> { + self.tree.get_data() + } + #[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() { + for current_node in self.iter_context() { 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); + let local_result = (exit_matcher.exit_matcher)(¤t_node, i); if local_result.is_ok() { return local_result; } @@ -94,8 +125,7 @@ impl<'r, 's> ContextTree<'r, 's> { fn _should_consume_trailing_whitespace(&self) -> Option { for current_node in self.iter() { - let context_element = current_node.get_data(); - match context_element { + match current_node { ContextElement::ConsumeTrailingWhitespace(should) => { return Some(*should); } @@ -106,34 +136,35 @@ impl<'r, 's> ContextTree<'r, 's> { } } -#[derive(Debug)] -pub enum ContextElement<'r, 's> { - /// Stores a parser that indicates that children should exit upon matching an exit matcher. - ExitMatcherNode(ExitMatcherNode<'r>), - - /// Stores the name of the current element to prevent directly nesting elements of the same type. - Context(&'r str), - - /// Indicates if elements should consume the whitespace after them. - ConsumeTrailingWhitespace(bool), - - /// The contents of a radio target. - /// - /// If any are found, this will force a 2nd parse through the - /// org-mode document since text needs to be re-parsed to look for - /// radio links matching the contents of radio targets. - RadioTarget(Vec<&'r Vec>>), +#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] +fn document_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, + input: OrgSource<'s>, +) -> Res, OrgSource<'s>> { + eof(input) } -pub struct ExitMatcherNode<'r> { - pub exit_matcher: &'r Matcher, - pub class: ExitClass, +pub struct Iter<'g, 'r, 's> { + global_settings: &'g GlobalSettings<'g>, + next: super::list::IterList<'r, &'r ContextElement<'r, 's>>, } -impl<'r> std::fmt::Debug for ExitMatcherNode<'r> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut formatter = f.debug_struct("ExitMatcherNode"); - formatter.field("class", &self.class.to_string()); - formatter.finish() +impl<'g, 'r, 's> Iterator for Iter<'g, 'r, 's> { + type Item = Context<'g, 'r, 's>; + + fn next(&mut self) -> Option { + let next_tree = self.next.next(); + let ret = + next_tree.map(|parent_tree| Context::new(self.global_settings, parent_tree.clone())); + ret + } +} + +impl<'r, 's> ContextElement<'r, 's> { + pub fn document_context() -> Self { + Self::ExitMatcherNode(ExitMatcherNode { + exit_matcher: &document_end, + class: ExitClass::Document, + }) } } diff --git a/src/parser/parser_with_context.rs b/src/context/parser_with_context.rs similarity index 100% rename from src/parser/parser_with_context.rs rename to src/context/parser_with_context.rs diff --git a/src/lib.rs b/src/lib.rs index 513e5c9..c481b7d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![feature(round_char_boundary)] #![feature(exit_status_error)] +#![feature(trait_alias)] #[cfg(feature = "compare")] mod compare; @@ -14,5 +15,7 @@ pub use compare::get_emacs_version; #[cfg(feature = "compare")] pub use compare::get_org_mode_version; +mod context; mod error; pub mod parser; +pub mod types; diff --git a/src/main.rs b/src/main.rs index 968cd2d..edb1544 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ use std::io::Read; use std::path::Path; -use ::organic::parser::document; +use ::organic::parser::parse; #[cfg(feature = "compare")] use organic::compare_document; #[cfg(feature = "compare")] @@ -68,7 +68,7 @@ fn run_anonymous_parse>(org_contents: P) -> Result<(), Box>(org_contents: P) -> Result<(), Box>(org_contents: P) -> Result<(), Box>(org_path: P) -> Result<(), Box>(org_path: P) -> Result<(), Box>(org_path: P) -> Result<(), Box( - context: Context<'r, 's>, +pub fn angle_link<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, AngleLink<'s>> { let (remaining, _) = tag("<")(input)?; @@ -41,15 +41,15 @@ pub fn angle_link<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn path_angle<'r, 's>( - context: Context<'r, 's>, +fn path_angle<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &path_angle_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &path_angle_end, + }); + let parser_context = context.with_additional_node(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); @@ -58,8 +58,8 @@ fn path_angle<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn path_angle_end<'r, 's>( - _context: Context<'r, 's>, +fn path_angle_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { tag(">")(input) diff --git a/src/parser/citation.rs b/src/parser/citation.rs index c06813b..d1ebdb2 100644 --- a/src/parser/citation.rs +++ b/src/parser/citation.rs @@ -14,24 +14,25 @@ use super::citation_reference::must_balance_bracket; use super::org_source::BracketDepth; use super::org_source::OrgSource; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ContextMatcher; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::Res; use crate::parser::citation_reference::citation_reference; use crate::parser::citation_reference::citation_reference_key; -use crate::parser::exiting::ExitClass; -use crate::parser::object::Citation; use crate::parser::object_parser::standard_set_object; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; -use crate::parser::Object; +use crate::types::Citation; +use crate::types::Object; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn citation<'r, 's>( - context: Context<'r, 's>, +pub fn citation<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Citation<'s>> { // TODO: Despite being a standard object, citations cannot exist inside the global prefix/suffix for other citations because citations must contain something that matches @key which is forbidden inside the global prefix/suffix. This TODO is to evaluate if its worth putting in an explicit check for this (which can be easily accomplished by checking the output of `get_bracket_depth()`). I suspect its not worth it because I expect, outside of intentionally crafted inputs, this parser will exit immediately inside a citation since it is unlikely to find the "[cite" substring inside a citation global prefix/suffix. @@ -60,7 +61,7 @@ pub fn citation<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn citestyle<'r, 's>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { +fn citestyle<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { let (remaining, _) = tuple((tag("/"), style))(input)?; let (remaining, _) = opt(tuple((tag("/"), variant)))(remaining)?; let source = get_consumed(input, remaining); @@ -68,30 +69,30 @@ fn citestyle<'r, 's>(input: OrgSource<'s>) -> Res, OrgSource<'s>> } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn style<'r, 's>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { +fn style<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { recognize(many1(verify(anychar, |c| { c.is_alphanumeric() || "_-".contains(*c) })))(input) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn variant<'r, 's>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { +fn variant<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { recognize(many1(verify(anychar, |c| { c.is_alphanumeric() || "_-/".contains(*c) })))(input) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn global_prefix<'r, 's>( - context: Context<'r, 's>, +fn global_prefix<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Vec>> { let exit_with_depth = global_prefix_end(input.get_bracket_depth()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &exit_with_depth, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &exit_with_depth, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, (children, _exit_contents)) = verify( many_till( parser_with_context!(standard_set_object)(&parser_context), @@ -103,17 +104,13 @@ fn global_prefix<'r, 's>( Ok((remaining, children)) } -fn global_prefix_end( - starting_bracket_depth: BracketDepth, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - move |context: Context, input: OrgSource<'_>| { - _global_prefix_end(context, input, starting_bracket_depth) - } +fn global_prefix_end(starting_bracket_depth: BracketDepth) -> impl ContextMatcher { + move |context, input: OrgSource<'_>| _global_prefix_end(context, input, starting_bracket_depth) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _global_prefix_end<'r, 's>( - context: Context<'r, 's>, +fn _global_prefix_end<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, starting_bracket_depth: BracketDepth, ) -> Res, OrgSource<'s>> { @@ -135,16 +132,16 @@ fn _global_prefix_end<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn global_suffix<'r, 's>( - context: Context<'r, 's>, +fn global_suffix<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Vec>> { let exit_with_depth = global_suffix_end(input.get_bracket_depth()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &exit_with_depth, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &exit_with_depth, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, (children, _exit_contents)) = verify( many_till( parser_with_context!(standard_set_object)(&parser_context), @@ -155,17 +152,13 @@ fn global_suffix<'r, 's>( Ok((remaining, children)) } -fn global_suffix_end( - starting_bracket_depth: BracketDepth, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - move |context: Context, input: OrgSource<'_>| { - _global_suffix_end(context, input, starting_bracket_depth) - } +fn global_suffix_end(starting_bracket_depth: BracketDepth) -> impl ContextMatcher { + move |context, input: OrgSource<'_>| _global_suffix_end(context, input, starting_bracket_depth) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _global_suffix_end<'r, 's>( - context: Context<'r, 's>, +fn _global_suffix_end<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, starting_bracket_depth: BracketDepth, ) -> Res, OrgSource<'s>> { @@ -189,19 +182,23 @@ fn _global_suffix_end<'r, 's>( #[cfg(test)] mod tests { use super::*; + use crate::context::Context; + use crate::context::GlobalSettings; + use crate::context::List; use crate::parser::element_parser::element; - use crate::parser::parser_context::ContextTree; - use crate::parser::parser_with_context::parser_with_context; - use crate::parser::source::Source; + use crate::types::Element; + use crate::types::Source; #[test] fn citation_simple() { let input = OrgSource::new("[cite:@foo]"); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let paragraph_matcher = parser_with_context!(element(true))(&initial_context); let (remaining, first_paragraph) = paragraph_matcher(input).expect("Parse first paragraph"); let first_paragraph = match first_paragraph { - crate::parser::Element::Paragraph(paragraph) => paragraph, + Element::Paragraph(paragraph) => paragraph, _ => panic!("Should be a paragraph!"), }; assert_eq!(Into::<&str>::into(remaining), ""); diff --git a/src/parser/citation_reference.rs b/src/parser/citation_reference.rs index 0024fc3..50697e2 100644 --- a/src/parser/citation_reference.rs +++ b/src/parser/citation_reference.rs @@ -12,24 +12,25 @@ use nom::sequence::tuple; use super::org_source::BracketDepth; use super::org_source::OrgSource; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ContextMatcher; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::object::CitationReference; use crate::parser::object_parser::minimal_set_object; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::WORD_CONSTITUENT_CHARACTERS; -use crate::parser::Object; +use crate::types::CitationReference; +use crate::types::Object; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn citation_reference<'r, 's>( - context: Context<'r, 's>, +pub fn citation_reference<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, CitationReference<'s>> { let (remaining, _prefix) = @@ -48,8 +49,8 @@ pub fn citation_reference<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn citation_reference_key<'r, 's>( - context: Context<'r, 's>, +pub fn citation_reference_key<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, source) = recognize(tuple(( @@ -68,16 +69,16 @@ pub fn citation_reference_key<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn key_prefix<'r, 's>( - context: Context<'r, 's>, +fn key_prefix<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Vec>> { let exit_with_depth = key_prefix_end(input.get_bracket_depth()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &exit_with_depth, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &exit_with_depth, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, (children, _exit_contents)) = verify( many_till( parser_with_context!(minimal_set_object)(&parser_context), @@ -89,16 +90,16 @@ fn key_prefix<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn key_suffix<'r, 's>( - context: Context<'r, 's>, +fn key_suffix<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Vec>> { let exit_with_depth = key_suffix_end(input.get_bracket_depth()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &exit_with_depth, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &exit_with_depth, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, (children, _exit_contents)) = verify( many_till( parser_with_context!(minimal_set_object)(&parser_context), @@ -109,17 +110,13 @@ fn key_suffix<'r, 's>( Ok((remaining, children)) } -fn key_prefix_end( - starting_bracket_depth: BracketDepth, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - move |context: Context, input: OrgSource<'_>| { - _key_prefix_end(context, input, starting_bracket_depth) - } +fn key_prefix_end(starting_bracket_depth: BracketDepth) -> impl ContextMatcher { + move |context, input: OrgSource<'_>| _key_prefix_end(context, input, starting_bracket_depth) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _key_prefix_end<'r, 's>( - context: Context<'r, 's>, +fn _key_prefix_end<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, starting_bracket_depth: BracketDepth, ) -> Res, OrgSource<'s>> { @@ -140,17 +137,13 @@ fn _key_prefix_end<'r, 's>( ))(input) } -fn key_suffix_end( - starting_bracket_depth: BracketDepth, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - move |context: Context, input: OrgSource<'_>| { - _key_suffix_end(context, input, starting_bracket_depth) - } +fn key_suffix_end(starting_bracket_depth: BracketDepth) -> impl ContextMatcher { + move |context, input: OrgSource<'_>| _key_suffix_end(context, input, starting_bracket_depth) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _key_suffix_end<'r, 's>( - _context: Context<'r, 's>, +fn _key_suffix_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, starting_bracket_depth: BracketDepth, ) -> Res, OrgSource<'s>> { diff --git a/src/parser/clock.rs b/src/parser/clock.rs index 7731a0c..7f13d25 100644 --- a/src/parser/clock.rs +++ b/src/parser/clock.rs @@ -12,16 +12,16 @@ use nom::combinator::verify; use nom::sequence::tuple; use super::org_source::OrgSource; -use super::Context; +use crate::context::parser_with_context; +use crate::context::RefContext; use crate::error::Res; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::get_consumed; use crate::parser::util::start_of_line; -use crate::parser::Clock; +use crate::types::Clock; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn clock<'r, 's>( - context: Context<'r, 's>, +pub fn clock<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Clock<'s>> { start_of_line(input)?; @@ -44,8 +44,8 @@ pub fn clock<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn inactive_timestamp_range_duration<'r, 's>( - _context: Context<'r, 's>, +fn inactive_timestamp_range_duration<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(tuple(( @@ -66,8 +66,8 @@ fn inactive_timestamp_range_duration<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn inactive_timestamp<'r, 's>( - _context: Context<'r, 's>, +fn inactive_timestamp<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(tuple(( diff --git a/src/parser/comment.rs b/src/parser/comment.rs index d336721..a6d539c 100644 --- a/src/parser/comment.rs +++ b/src/parser/comment.rs @@ -13,20 +13,20 @@ use nom::sequence::tuple; use super::org_source::OrgSource; use super::util::get_consumed; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::immediate_in_section; use crate::parser::util::start_of_line; -use crate::parser::Comment; +use crate::types::Comment; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn comment<'r, 's>( - context: Context<'r, 's>, +pub fn comment<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Comment<'s>> { if immediate_in_section(context, "comment") { @@ -34,7 +34,8 @@ pub fn comment<'r, 's>( "Cannot nest objects of the same element".into(), )))); } - let parser_context = context.with_additional_node(ContextElement::Context("comment")); + let parser_context = ContextElement::Context("comment"); + let parser_context = context.with_additional_node(&parser_context); let comment_line_matcher = parser_with_context!(comment_line)(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); let (remaining, _first_line) = comment_line_matcher(input)?; @@ -51,8 +52,8 @@ pub fn comment<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn comment_line<'r, 's>( - _context: Context<'r, 's>, +fn comment_line<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { start_of_line(input)?; @@ -69,8 +70,10 @@ fn comment_line<'r, 's>( #[cfg(test)] mod tests { use super::*; - use crate::parser::parser_context::ContextTree; - use crate::parser::parser_with_context::parser_with_context; + use crate::context::Context; + use crate::context::ContextElement; + use crate::context::GlobalSettings; + use crate::context::List; #[test] fn require_space_after_hash() { @@ -79,7 +82,9 @@ mod tests { #not a comment # Comment again", ); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let comment_matcher = parser_with_context!(comment)(&initial_context); let (remaining, first_comment) = comment_matcher(input).expect("Parse first comment"); assert_eq!( diff --git a/src/parser/diary_sexp.rs b/src/parser/diary_sexp.rs index 691f990..abadd4d 100644 --- a/src/parser/diary_sexp.rs +++ b/src/parser/diary_sexp.rs @@ -11,15 +11,15 @@ use nom::sequence::tuple; use super::org_source::OrgSource; use super::sexp::sexp; -use super::Context; +use crate::context::RefContext; use crate::error::Res; use crate::parser::util::get_consumed; use crate::parser::util::start_of_line; -use crate::parser::DiarySexp; +use crate::types::DiarySexp; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn diary_sexp<'r, 's>( - _context: Context<'r, 's>, +pub fn diary_sexp<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, DiarySexp<'s>> { start_of_line(input)?; diff --git a/src/parser/document.rs b/src/parser/document.rs index 760c6dc..3b467a2 100644 --- a/src/parser/document.rs +++ b/src/parser/document.rs @@ -4,6 +4,7 @@ use nom::character::complete::anychar; use nom::character::complete::line_ending; use nom::character::complete::space0; use nom::character::complete::space1; +use nom::combinator::all_consuming; use nom::combinator::eof; use nom::combinator::map; use nom::combinator::not; @@ -17,96 +18,56 @@ use nom::multi::many_till; use nom::multi::separated_list1; use nom::sequence::tuple; -use super::element::Element; -use super::object::Object; -use super::org_source::convert_error; use super::org_source::OrgSource; -use super::parser_with_context::parser_with_context; -use super::source::Source; use super::token::AllTokensIterator; use super::token::Token; use super::util::exit_matcher_parser; use super::util::get_consumed; use super::util::start_of_line; -use super::Context; +use crate::context::parser_with_context; +use crate::context::Context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::GlobalSettings; +use crate::context::List; +use crate::context::RefContext; use crate::error::Res; use crate::parser::comment::comment; use crate::parser::element_parser::element; -use crate::parser::exiting::ExitClass; use crate::parser::object_parser::standard_set_object; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ContextTree; -use crate::parser::parser_context::ExitMatcherNode; use crate::parser::planning::planning; use crate::parser::property_drawer::property_drawer; use crate::parser::util::blank_line; use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; +use crate::types::Document; +use crate::types::DocumentElement; +use crate::types::Element; +use crate::types::Heading; +use crate::types::Object; +use crate::types::Section; -#[derive(Debug)] -pub struct Document<'s> { - pub source: &'s str, - pub zeroth_section: Option>, - pub children: Vec>, -} - -#[derive(Debug)] -pub struct Heading<'s> { - pub source: &'s str, - pub stars: usize, - pub todo_keyword: Option<&'s str>, - // TODO: add todo-type enum - pub title: Vec>, - pub tags: Vec<&'s str>, - pub children: Vec>, -} - -#[derive(Debug)] -pub struct Section<'s> { - pub source: &'s str, - pub children: Vec>, -} - -#[derive(Debug)] -pub enum DocumentElement<'s> { - Heading(Heading<'s>), - Section(Section<'s>), -} - -impl<'s> Source<'s> for Document<'s> { - fn get_source(&'s self) -> &'s str { - self.source - } -} - -impl<'s> Source<'s> for DocumentElement<'s> { - fn get_source(&'s self) -> &'s str { - match self { - DocumentElement::Heading(obj) => obj.source, - DocumentElement::Section(obj) => obj.source, - } - } -} - -impl<'s> Source<'s> for Section<'s> { - fn get_source(&'s self) -> &'s str { - self.source - } -} - -impl<'s> Source<'s> for Heading<'s> { - fn get_source(&'s self) -> &'s str { - self.source - } +#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] +#[allow(dead_code)] +pub fn parse<'s>(input: &'s str) -> Result, String> { + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); + let wrapped_input = OrgSource::new(input); + let ret = all_consuming(parser_with_context!(document)(&initial_context))(wrapped_input) + .map_err(|err| err.to_string()) + .map(|(_remaining, parsed_document)| parsed_document); + ret } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[allow(dead_code)] -pub fn document(input: &str) -> Res<&str, Document> { - let initial_context: ContextTree<'_, '_> = ContextTree::new(); - let wrapped_input = OrgSource::new(input); - let (remaining, document) = _document(&initial_context, wrapped_input) - .map(|(rem, out)| (Into::<&str>::into(rem), out)) - .map_err(convert_error)?; +pub fn document<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, + input: OrgSource<'s>, +) -> Res, Document<'s>> { + let (remaining, document) = + _document(context, input).map(|(rem, out)| (Into::<&str>::into(rem), out))?; { // If there are radio targets in this document then we need to parse the entire document again with the knowledge of the radio targets. let all_radio_targets: Vec<&Vec>> = document @@ -122,11 +83,10 @@ pub fn document(input: &str) -> Res<&str, Document> { .map(|rt| &rt.children) .collect(); if !all_radio_targets.is_empty() { - let initial_context = initial_context - .with_additional_node(ContextElement::RadioTarget(all_radio_targets)); - let (remaining, document) = _document(&initial_context, wrapped_input) - .map(|(rem, out)| (Into::<&str>::into(rem), out)) - .map_err(convert_error)?; + let parser_context = ContextElement::RadioTarget(all_radio_targets); + let parser_context = context.with_additional_node(&parser_context); + let (remaining, document) = _document(&parser_context, input) + .map(|(rem, out)| (Into::<&str>::into(rem), out))?; return Ok((remaining.into(), document)); } } @@ -134,8 +94,8 @@ pub fn document(input: &str) -> Res<&str, Document> { } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _document<'r, 's>( - context: Context<'r, 's>, +fn _document<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Document<'s>> { let zeroth_section_matcher = parser_with_context!(zeroth_section)(context); @@ -155,20 +115,25 @@ fn _document<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn zeroth_section<'r, 's>( - context: Context<'r, 's>, +fn zeroth_section<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Section<'s>> { // TODO: The zeroth section is specialized so it probably needs its own parser - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context("section")) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context("section"), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Document, exit_matcher: §ion_end, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); + let without_consuming_whitespace_context = ContextElement::ConsumeTrailingWhitespace(false); let without_consuming_whitespace_context = - parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false)); + parser_context.with_additional_node(&without_consuming_whitespace_context); let element_matcher = parser_with_context!(element(true))(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); @@ -209,18 +174,22 @@ fn zeroth_section<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn section<'r, 's>( - context: Context<'r, 's>, +fn section<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, mut input: OrgSource<'s>, ) -> Res, Section<'s>> { // TODO: The zeroth section is specialized so it probably needs its own parser - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context("section")) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context("section"), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Document, exit_matcher: §ion_end, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); let element_matcher = parser_with_context!(element(true))(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); let (mut remaining, (planning_element, property_drawer_element)) = tuple(( @@ -259,8 +228,8 @@ fn section<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn section_end<'r, 's>( - _context: Context<'r, 's>, +fn section_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(detect_headline)(input) @@ -268,13 +237,16 @@ fn section_end<'r, 's>( const fn heading( parent_stars: usize, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, Heading<'s>> { - move |context: Context, input: OrgSource<'_>| _heading(context, input, parent_stars) +) -> impl for<'b, 'g, 'r, 's> Fn( + RefContext<'b, 'g, 'r, 's>, + OrgSource<'s>, +) -> Res, Heading<'s>> { + move |context, input: OrgSource<'_>| _heading(context, input, parent_stars) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _heading<'r, 's>( - context: Context<'r, 's>, +fn _heading<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, parent_stars: usize, ) -> Res, Heading<'s>> { @@ -320,8 +292,8 @@ fn detect_headline<'s>(input: OrgSource<'s>) -> Res, ()> { } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn headline<'r, 's>( - context: Context<'r, 's>, +fn headline<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, parent_stars: usize, ) -> Res< @@ -334,11 +306,11 @@ fn headline<'r, 's>( Vec<&'s str>, ), > { - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Document, - exit_matcher: &headline_title_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Document, + exit_matcher: &headline_title_end, + }); + let parser_context = context.with_additional_node(&parser_context); let standard_set_object_matcher = parser_with_context!(standard_set_object)(&parser_context); let ( @@ -375,8 +347,8 @@ fn headline<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn headline_title_end<'r, 's>( - _context: Context<'r, 's>, +fn headline_title_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(tuple(( diff --git a/src/parser/drawer.rs b/src/parser/drawer.rs index 213cc5e..1cdabe2 100644 --- a/src/parser/drawer.rs +++ b/src/parser/drawer.rs @@ -11,29 +11,29 @@ use nom::multi::many_till; use nom::sequence::tuple; use super::org_source::OrgSource; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; use crate::parser::element_parser::element; -use crate::parser::exiting::ExitClass; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; -use crate::parser::source::SetSource; use crate::parser::util::blank_line; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::immediate_in_section; use crate::parser::util::start_of_line; use crate::parser::util::WORD_CONSTITUENT_CHARACTERS; -use crate::parser::Drawer; -use crate::parser::Element; -use crate::parser::Paragraph; +use crate::types::Drawer; +use crate::types::Element; +use crate::types::Paragraph; +use crate::types::SetSource; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn drawer<'r, 's>( - context: Context<'r, 's>, +pub fn drawer<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Drawer<'s>> { if immediate_in_section(context, "drawer") { @@ -50,13 +50,17 @@ pub fn drawer<'r, 's>( recognize(tuple((space0, line_ending))), ))(remaining)?; - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context("drawer")) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context("drawer"), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Alpha, exit_matcher: &drawer_end, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); let element_matcher = parser_with_context!(element(true))(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); @@ -98,8 +102,8 @@ fn name<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn drawer_end<'r, 's>( - _context: Context<'r, 's>, +fn drawer_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { start_of_line(input)?; diff --git a/src/parser/dynamic_block.rs b/src/parser/dynamic_block.rs index 679a701..083b26c 100644 --- a/src/parser/dynamic_block.rs +++ b/src/parser/dynamic_block.rs @@ -12,28 +12,28 @@ use nom::multi::many_till; use nom::sequence::tuple; use super::org_source::OrgSource; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; use crate::parser::element_parser::element; -use crate::parser::exiting::ExitClass; -use crate::parser::greater_element::DynamicBlock; -use crate::parser::lesser_element::Paragraph; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; -use crate::parser::source::SetSource; use crate::parser::util::blank_line; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::immediate_in_section; use crate::parser::util::start_of_line; -use crate::parser::Element; +use crate::types::DynamicBlock; +use crate::types::Element; +use crate::types::Paragraph; +use crate::types::SetSource; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn dynamic_block<'r, 's>( - context: Context<'r, 's>, +pub fn dynamic_block<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, DynamicBlock<'s>> { // TODO: Do I need to differentiate between different dynamic block types. @@ -50,13 +50,17 @@ pub fn dynamic_block<'r, 's>( opt(tuple((space1, parameters))), line_ending, ))(remaining)?; - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context("dynamic block")) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context("dynamic block"), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Alpha, exit_matcher: &dynamic_block_end, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); let parameters = match parameters { Some((_ws, parameters)) => Some(parameters), None => None, @@ -106,8 +110,8 @@ fn parameters<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn dynamic_block_end<'r, 's>( - _context: Context<'r, 's>, +fn dynamic_block_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { start_of_line(input)?; diff --git a/src/parser/element_parser.rs b/src/parser/element_parser.rs index f9451ca..fe20fa1 100644 --- a/src/parser/element_parser.rs +++ b/src/parser/element_parser.rs @@ -7,7 +7,6 @@ use super::comment::comment; use super::diary_sexp::diary_sexp; use super::drawer::drawer; use super::dynamic_block::dynamic_block; -use super::element::Element; use super::fixed_width_area::fixed_width_area; use super::footnote_definition::footnote_definition; use super::greater_block::greater_block; @@ -24,25 +23,29 @@ use super::org_source::OrgSource; use super::paragraph::paragraph; use super::plain_list::detect_plain_list; use super::plain_list::plain_list; -use super::source::SetSource; use super::util::get_consumed; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::parser_with_context; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::table::org_mode_table; +use crate::types::Element; +use crate::types::SetSource; pub const fn element( can_be_paragraph: bool, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, Element<'s>> { - move |context: Context, input: OrgSource<'_>| _element(context, input, can_be_paragraph) +) -> impl for<'b, 'g, 'r, 's> Fn( + RefContext<'b, 'g, 'r, 's>, + OrgSource<'s>, +) -> Res, Element<'s>> { + move |context, input: OrgSource<'_>| _element(context, input, can_be_paragraph) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _element<'r, 's>( - context: Context<'r, 's>, +fn _element<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, can_be_paragraph: bool, ) -> Res, Element<'s>> { @@ -118,13 +121,14 @@ fn _element<'r, 's>( pub const fn detect_element( can_be_paragraph: bool, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, ()> { - move |context: Context, input: OrgSource<'_>| _detect_element(context, input, can_be_paragraph) +) -> impl for<'b, 'g, 'r, 's> Fn(RefContext<'b, 'g, 'r, 's>, OrgSource<'s>) -> Res, ()> +{ + move |context, input: OrgSource<'_>| _detect_element(context, input, can_be_paragraph) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _detect_element<'r, 's>( - context: Context<'r, 's>, +fn _detect_element<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, can_be_paragraph: bool, ) -> Res, ()> { diff --git a/src/parser/entity.rs b/src/parser/entity.rs index 4683e1c..ca8403a 100644 --- a/src/parser/entity.rs +++ b/src/parser/entity.rs @@ -8,12 +8,12 @@ use nom::combinator::recognize; use super::org_source::OrgSource; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::object::Entity; use crate::parser::util::get_consumed; +use crate::types::Entity; // TODO: Make this a user-provided variable corresponding to elisp's org-entities const ORG_ENTITIES: [&'static str; 413] = [ @@ -433,8 +433,8 @@ const ORG_ENTITIES: [&'static str; 413] = [ ]; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn entity<'r, 's>( - context: Context<'r, 's>, +pub fn entity<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Entity<'s>> { let (remaining, _) = tag("\\")(input)?; @@ -454,8 +454,8 @@ pub fn entity<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn name<'r, 's>( - _context: Context<'r, 's>, +fn name<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { // TODO: This should be defined by org-entities and optionally org-entities-user diff --git a/src/parser/export_snippet.rs b/src/parser/export_snippet.rs index 85ef51b..2b40619 100644 --- a/src/parser/export_snippet.rs +++ b/src/parser/export_snippet.rs @@ -9,28 +9,28 @@ use nom::sequence::tuple; use super::org_source::OrgSource; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; -use crate::parser::ExportSnippet; +use crate::types::ExportSnippet; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn export_snippet<'r, 's>( - context: Context<'r, 's>, +pub fn export_snippet<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, ExportSnippet<'s>> { let (remaining, _) = tag("@@")(input)?; let (remaining, backend_name) = backend(context, remaining)?; - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &export_snippet_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &export_snippet_end, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, backend_contents) = opt(tuple(( tag(":"), parser_with_context!(contents)(&parser_context), @@ -50,8 +50,8 @@ pub fn export_snippet<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn backend<'r, 's>( - _context: Context<'r, 's>, +fn backend<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, backend_name) = @@ -61,8 +61,8 @@ fn backend<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn contents<'r, 's>( - context: Context<'r, 's>, +fn contents<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, source) = recognize(verify( @@ -73,8 +73,8 @@ fn contents<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn export_snippet_end<'r, 's>( - _context: Context<'r, 's>, +fn export_snippet_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { tag("@@")(input) diff --git a/src/parser/fixed_width_area.rs b/src/parser/fixed_width_area.rs index 3660069..b579ced 100644 --- a/src/parser/fixed_width_area.rs +++ b/src/parser/fixed_width_area.rs @@ -12,17 +12,17 @@ use nom::sequence::preceded; use nom::sequence::tuple; use super::org_source::OrgSource; -use super::Context; +use crate::context::parser_with_context; +use crate::context::RefContext; use crate::error::Res; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::start_of_line; -use crate::parser::FixedWidthArea; +use crate::types::FixedWidthArea; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn fixed_width_area<'r, 's>( - context: Context<'r, 's>, +pub fn fixed_width_area<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, FixedWidthArea<'s>> { let fixed_width_area_line_matcher = parser_with_context!(fixed_width_area_line)(context); @@ -41,8 +41,8 @@ pub fn fixed_width_area<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn fixed_width_area_line<'r, 's>( - _context: Context<'r, 's>, +fn fixed_width_area_line<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { start_of_line(input)?; diff --git a/src/parser/footnote_definition.rs b/src/parser/footnote_definition.rs index 310620d..e413d9d 100644 --- a/src/parser/footnote_definition.rs +++ b/src/parser/footnote_definition.rs @@ -12,26 +12,26 @@ use nom::sequence::tuple; use super::org_source::OrgSource; use super::util::WORD_CONSTITUENT_CHARACTERS; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; use crate::parser::element_parser::element; -use crate::parser::exiting::ExitClass; -use crate::parser::greater_element::FootnoteDefinition; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::blank_line; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::immediate_in_section; use crate::parser::util::maybe_consume_trailing_whitespace; use crate::parser::util::start_of_line; +use crate::types::FootnoteDefinition; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn footnote_definition<'r, 's>( - context: Context<'r, 's>, +pub fn footnote_definition<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, FootnoteDefinition<'s>> { if immediate_in_section(context, "footnote definition") { @@ -43,13 +43,17 @@ pub fn footnote_definition<'r, 's>( // Cannot be indented. let (remaining, (_lead_in, lbl, _lead_out, _ws)) = tuple((tag_no_case("[fn:"), label, tag("]"), space0))(input)?; - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context("footnote definition")) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context("footnote definition"), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Alpha, exit_matcher: &footnote_definition_end, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); // TODO: The problem is we are not accounting for trailing whitespace like we do in section. Maybe it would be easier if we passed down whether or not to parse trailing whitespace into the element matcher similar to how tag takes in parameters. let element_matcher = parser_with_context!(element(true))(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); @@ -76,8 +80,8 @@ pub fn label<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn footnote_definition_end<'r, 's>( - context: Context<'r, 's>, +fn footnote_definition_end<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, source) = alt(( @@ -105,9 +109,10 @@ fn detect_footnote_definition<'s>(input: OrgSource<'s>) -> Res, () #[cfg(test)] mod tests { use super::*; - use crate::parser::parser_context::ContextTree; - use crate::parser::parser_with_context::parser_with_context; - use crate::parser::Source; + use crate::context::Context; + use crate::context::GlobalSettings; + use crate::context::List; + use crate::types::Source; #[test] fn two_paragraphs() { @@ -118,7 +123,9 @@ mod tests { line footnote.", ); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let footnote_definition_matcher = parser_with_context!(element(true))(&initial_context); let (remaining, first_footnote_definition) = footnote_definition_matcher(input).expect("Parse first footnote_definition"); @@ -149,7 +156,9 @@ line footnote. not in the footnote.", ); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let footnote_definition_matcher = parser_with_context!(element(true))(&initial_context); let (remaining, first_footnote_definition) = footnote_definition_matcher(input).expect("Parse first footnote_definition"); diff --git a/src/parser/footnote_reference.rs b/src/parser/footnote_reference.rs index d82f514..0f3738c 100644 --- a/src/parser/footnote_reference.rs +++ b/src/parser/footnote_reference.rs @@ -6,24 +6,25 @@ use nom::multi::many_till; use super::org_source::BracketDepth; use super::org_source::OrgSource; -use super::parser_context::ContextElement; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ContextMatcher; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::exiting::ExitClass; use crate::parser::footnote_definition::label; use crate::parser::object_parser::standard_set_object; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; -use crate::parser::FootnoteReference; +use crate::types::FootnoteReference; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn footnote_reference<'r, 's>( - context: Context<'r, 's>, +pub fn footnote_reference<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, FootnoteReference<'s>> { alt(( @@ -34,17 +35,17 @@ pub fn footnote_reference<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn anonymous_footnote<'r, 's>( - context: Context<'r, 's>, +fn anonymous_footnote<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, FootnoteReference<'s>> { let (remaining, _) = tag_no_case("[fn::")(input)?; let exit_with_depth = footnote_definition_end(remaining.get_bracket_depth()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Beta, - exit_matcher: &exit_with_depth, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &exit_with_depth, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, (children, _exit_contents)) = verify( many_till( parser_with_context!(standard_set_object)(&parser_context), @@ -68,19 +69,19 @@ fn anonymous_footnote<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn inline_footnote<'r, 's>( - context: Context<'r, 's>, +fn inline_footnote<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, FootnoteReference<'s>> { let (remaining, _) = tag_no_case("[fn:")(input)?; let (remaining, label_contents) = label(remaining)?; let (remaining, _) = tag(":")(remaining)?; let exit_with_depth = footnote_definition_end(remaining.get_bracket_depth()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Beta, - exit_matcher: &exit_with_depth, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &exit_with_depth, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, (children, _exit_contents)) = verify( many_till( parser_with_context!(standard_set_object)(&parser_context), @@ -104,8 +105,8 @@ fn inline_footnote<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn footnote_reference_only<'r, 's>( - context: Context<'r, 's>, +fn footnote_reference_only<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, FootnoteReference<'s>> { let (remaining, _) = tag_no_case("[fn:")(input)?; @@ -124,17 +125,15 @@ fn footnote_reference_only<'r, 's>( )) } -fn footnote_definition_end( - starting_bracket_depth: BracketDepth, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - move |context: Context, input: OrgSource<'_>| { +fn footnote_definition_end(starting_bracket_depth: BracketDepth) -> impl ContextMatcher { + move |context, input: OrgSource<'_>| { _footnote_definition_end(context, input, starting_bracket_depth) } } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _footnote_definition_end<'r, 's>( - _context: Context<'r, 's>, +fn _footnote_definition_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, starting_bracket_depth: BracketDepth, ) -> Res, OrgSource<'s>> { diff --git a/src/parser/greater_block.rs b/src/parser/greater_block.rs index 99ff850..8e973de 100644 --- a/src/parser/greater_block.rs +++ b/src/parser/greater_block.rs @@ -13,27 +13,28 @@ use nom::sequence::tuple; use super::org_source::OrgSource; use super::util::in_section; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ContextMatcher; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; use crate::parser::element_parser::element; -use crate::parser::exiting::ExitClass; -use crate::parser::greater_element::GreaterBlock; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; -use crate::parser::source::SetSource; use crate::parser::util::blank_line; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::start_of_line; -use crate::parser::Element; -use crate::parser::Paragraph; +use crate::types::Element; +use crate::types::GreaterBlock; +use crate::types::Paragraph; +use crate::types::SetSource; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn greater_block<'r, 's>( - context: Context<'r, 's>, +pub fn greater_block<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, GreaterBlock<'s>> { // TODO: Do I need to differentiate between different greater block types. @@ -61,13 +62,17 @@ pub fn greater_block<'r, 's>( let exit_with_name = greater_block_end(name.into()); let (remaining, parameters) = opt(tuple((space1, parameters)))(remaining)?; let (remaining, _nl) = line_ending(remaining)?; - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context(context_name.as_str())) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context(context_name.as_str()), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Alpha, exit_matcher: &exit_with_name, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); let parameters = match parameters { Some((_ws, parameters)) => Some(parameters), None => None, @@ -120,19 +125,16 @@ fn parameters<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { is_not("\r\n")(input) } -fn greater_block_end<'x>( - name: &'x str, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { +fn greater_block_end<'c>(name: &'c str) -> impl ContextMatcher + 'c { // TODO: Can this be done without making an owned copy? - let name = name.to_owned(); - move |context: Context, input: OrgSource<'_>| _greater_block_end(context, input, name.as_str()) + move |context, input: OrgSource<'_>| _greater_block_end(context, input, name) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _greater_block_end<'r, 's, 'x>( - _context: Context<'r, 's>, +fn _greater_block_end<'b, 'g, 'r, 's, 'c>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, - name: &'x str, + name: &'c str, ) -> Res, OrgSource<'s>> { start_of_line(input)?; let (remaining, _leading_whitespace) = space0(input)?; diff --git a/src/parser/horizontal_rule.rs b/src/parser/horizontal_rule.rs index acf4775..c4c054a 100644 --- a/src/parser/horizontal_rule.rs +++ b/src/parser/horizontal_rule.rs @@ -9,14 +9,14 @@ use nom::multi::many1_count; use nom::sequence::tuple; use super::org_source::OrgSource; -use super::Context; +use crate::context::RefContext; use crate::error::Res; use crate::parser::util::start_of_line; -use crate::parser::HorizontalRule; +use crate::types::HorizontalRule; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn horizontal_rule<'r, 's>( - _context: Context<'r, 's>, +pub fn horizontal_rule<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, HorizontalRule<'s>> { start_of_line(input)?; diff --git a/src/parser/inline_babel_call.rs b/src/parser/inline_babel_call.rs index 6f3479e..78cc953 100644 --- a/src/parser/inline_babel_call.rs +++ b/src/parser/inline_babel_call.rs @@ -12,21 +12,22 @@ use nom::multi::many_till; use super::org_source::BracketDepth; use super::org_source::OrgSource; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ContextMatcher; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; -use crate::parser::InlineBabelCall; +use crate::types::InlineBabelCall; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn inline_babel_call<'r, 's>( - context: Context<'r, 's>, +pub fn inline_babel_call<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, InlineBabelCall<'s>> { let (remaining, _) = tag_no_case("call_")(input)?; @@ -46,15 +47,15 @@ pub fn inline_babel_call<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn name<'r, 's>( - context: Context<'r, 's>, +fn name<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &name_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &name_end, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, name) = recognize(many_till( verify(anychar, |c| !(c.is_whitespace() || "[]()".contains(*c))), parser_with_context!(exit_matcher_parser)(&parser_context), @@ -63,26 +64,26 @@ fn name<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn name_end<'r, 's>( - _context: Context<'r, 's>, +fn name_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(one_of("[("))(input) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn header<'r, 's>( - context: Context<'r, 's>, +fn header<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, _) = tag("[")(input)?; let exit_with_depth = header_end(remaining.get_bracket_depth()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &exit_with_depth, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &exit_with_depth, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, name) = recognize(many_till( anychar, @@ -92,17 +93,13 @@ fn header<'r, 's>( Ok((remaining, name)) } -fn header_end( - starting_bracket_depth: BracketDepth, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - move |context: Context, input: OrgSource<'_>| { - _header_end(context, input, starting_bracket_depth) - } +fn header_end(starting_bracket_depth: BracketDepth) -> impl ContextMatcher { + move |context, input: OrgSource<'_>| _header_end(context, input, starting_bracket_depth) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _header_end<'r, 's>( - _context: Context<'r, 's>, +fn _header_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, starting_bracket_depth: BracketDepth, ) -> Res, OrgSource<'s>> { @@ -121,18 +118,18 @@ fn _header_end<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn argument<'r, 's>( - context: Context<'r, 's>, +fn argument<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, _) = tag("(")(input)?; let exit_with_depth = argument_end(remaining.get_parenthesis_depth()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &exit_with_depth, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &exit_with_depth, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, name) = recognize(many_till( anychar, @@ -142,17 +139,13 @@ fn argument<'r, 's>( Ok((remaining, name)) } -fn argument_end( - starting_parenthesis_depth: BracketDepth, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - move |context: Context, input: OrgSource<'_>| { - _argument_end(context, input, starting_parenthesis_depth) - } +fn argument_end(starting_parenthesis_depth: BracketDepth) -> impl ContextMatcher { + move |context, input: OrgSource<'_>| _argument_end(context, input, starting_parenthesis_depth) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _argument_end<'r, 's>( - _context: Context<'r, 's>, +fn _argument_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, starting_parenthesis_depth: BracketDepth, ) -> Res, OrgSource<'s>> { diff --git a/src/parser/inline_source_block.rs b/src/parser/inline_source_block.rs index e61bea0..4589124 100644 --- a/src/parser/inline_source_block.rs +++ b/src/parser/inline_source_block.rs @@ -14,21 +14,22 @@ use tracing::span; use super::org_source::BracketDepth; use super::org_source::OrgSource; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ContextMatcher; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; -use crate::parser::InlineSourceBlock; +use crate::types::InlineSourceBlock; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn inline_source_block<'r, 's>( - context: Context<'r, 's>, +pub fn inline_source_block<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, InlineSourceBlock<'s>> { let (remaining, _) = tag_no_case("src_")(input)?; @@ -47,15 +48,15 @@ pub fn inline_source_block<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn lang<'r, 's>( - context: Context<'r, 's>, +fn lang<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Beta, - exit_matcher: &lang_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &lang_end, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, lang) = recognize(many_till( verify(anychar, |c| !(c.is_whitespace() || "[{".contains(*c))), parser_with_context!(exit_matcher_parser)(&parser_context), @@ -64,26 +65,26 @@ fn lang<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn lang_end<'r, 's>( - _context: Context<'r, 's>, +fn lang_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(one_of("[{"))(input) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn header<'r, 's>( - context: Context<'r, 's>, +fn header<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, _) = tag("[")(input)?; let exit_with_depth = header_end(remaining.get_bracket_depth()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Beta, - exit_matcher: &exit_with_depth, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &exit_with_depth, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, header_contents) = recognize(many_till( anychar, @@ -93,17 +94,13 @@ fn header<'r, 's>( Ok((remaining, header_contents)) } -fn header_end( - starting_bracket_depth: BracketDepth, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - move |context: Context, input: OrgSource<'_>| { - _header_end(context, input, starting_bracket_depth) - } +fn header_end(starting_bracket_depth: BracketDepth) -> impl ContextMatcher { + move |context, input: OrgSource<'_>| _header_end(context, input, starting_bracket_depth) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _header_end<'r, 's>( - _context: Context<'r, 's>, +fn _header_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, starting_bracket_depth: BracketDepth, ) -> Res, OrgSource<'s>> { @@ -122,18 +119,18 @@ fn _header_end<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn body<'r, 's>( - context: Context<'r, 's>, +fn body<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, _) = tag("{")(input)?; let exit_with_depth = body_end(remaining.get_brace_depth()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Beta, - exit_matcher: &exit_with_depth, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &exit_with_depth, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, body_contents) = recognize(many_till( anychar, @@ -153,15 +150,13 @@ fn body<'r, 's>( Ok((remaining, body_contents)) } -fn body_end( - starting_brace_depth: BracketDepth, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - move |context: Context, input: OrgSource<'_>| _body_end(context, input, starting_brace_depth) +fn body_end(starting_brace_depth: BracketDepth) -> impl ContextMatcher { + move |context, input: OrgSource<'_>| _body_end(context, input, starting_brace_depth) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _body_end<'r, 's>( - _context: Context<'r, 's>, +fn _body_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, starting_brace_depth: BracketDepth, ) -> Res, OrgSource<'s>> { diff --git a/src/parser/keyword.rs b/src/parser/keyword.rs index 6e32be1..ee7a22d 100644 --- a/src/parser/keyword.rs +++ b/src/parser/keyword.rs @@ -16,12 +16,12 @@ use nom::sequence::tuple; use super::org_source::BracketDepth; use super::org_source::OrgSource; -use super::Context; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; use crate::parser::util::start_of_line; -use crate::parser::Keyword; +use crate::types::Keyword; const ORG_ELEMENT_AFFILIATED_KEYWORDS: [&'static str; 13] = [ "caption", "data", "header", "headers", "label", "name", "plot", "resname", "result", @@ -30,8 +30,8 @@ const ORG_ELEMENT_AFFILIATED_KEYWORDS: [&'static str; 13] = [ const ORG_ELEMENT_DUAL_KEYWORDS: [&'static str; 2] = ["caption", "results"]; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn keyword<'r, 's>( - _context: Context<'r, 's>, +pub fn keyword<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Keyword<'s>> { start_of_line(input)?; @@ -55,8 +55,8 @@ pub fn keyword<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn affiliated_keyword<'r, 's>( - _context: Context<'r, 's>, +pub fn affiliated_keyword<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Keyword<'s>> { start_of_line(input)?; diff --git a/src/parser/latex_environment.rs b/src/parser/latex_environment.rs index 4697e9d..a5d379a 100644 --- a/src/parser/latex_environment.rs +++ b/src/parser/latex_environment.rs @@ -13,19 +13,20 @@ use nom::sequence::tuple; use super::org_source::OrgSource; use super::util::get_consumed; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ContextMatcher; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::start_of_line; -use crate::parser::LatexEnvironment; +use crate::types::LatexEnvironment; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn latex_environment<'r, 's>( - context: Context<'r, 's>, +pub fn latex_environment<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, LatexEnvironment<'s>> { start_of_line(input)?; @@ -39,13 +40,13 @@ pub fn latex_environment<'r, 's>( ))(remaining)?; let latex_environment_end_specialized = latex_environment_end(name.into()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Beta, - exit_matcher: &latex_environment_end_specialized, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &latex_environment_end_specialized, + }); + let parser_context = context.with_additional_node(&parser_context); - let (remaining, _contents) = contents(&latex_environment_end_specialized, context, remaining)?; + let (remaining, _contents) = contents(&latex_environment_end_specialized)(context, remaining)?; let (remaining, _end) = latex_environment_end_specialized(&parser_context, remaining)?; let source = get_consumed(input, remaining); @@ -62,44 +63,42 @@ fn name<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { take_while1(|c: char| c.is_alphanumeric() || c == '*')(input) } +fn contents(end_matcher: F) -> impl ContextMatcher { + move |context, input| _contents(&end_matcher, context, input) +} + #[cfg_attr( feature = "tracing", tracing::instrument(ret, level = "debug", skip(end_matcher)) )] -pub fn contents< - 'r, - 's, - F: Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>>, ->( +fn _contents<'b, 'g, 'r, 's, F: ContextMatcher>( end_matcher: F, - context: Context<'r, 's>, + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, source) = recognize(many_till( anychar, peek(alt(( parser_with_context!(exit_matcher_parser)(context), - parser_with_context!(end_matcher)(context), + parser_with_context!(&end_matcher)(context), ))), ))(input)?; Ok((remaining, source)) } -fn latex_environment_end( - current_name: &str, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { +fn latex_environment_end(current_name: &str) -> impl ContextMatcher { let current_name_lower = current_name.to_lowercase(); - move |context: Context, input: OrgSource<'_>| { + move |context, input: OrgSource<'_>| { _latex_environment_end(context, input, current_name_lower.as_str()) } } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _latex_environment_end<'r, 's, 'x>( - _context: Context<'r, 's>, +fn _latex_environment_end<'b, 'g, 'r, 's, 'c>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, - current_name_lower: &'x str, + current_name_lower: &'c str, ) -> Res, OrgSource<'s>> { start_of_line(input)?; let (remaining, _leading_whitespace) = space0(input)?; diff --git a/src/parser/latex_fragment.rs b/src/parser/latex_fragment.rs index 4be6a0e..7a142d2 100644 --- a/src/parser/latex_fragment.rs +++ b/src/parser/latex_fragment.rs @@ -14,18 +14,18 @@ use nom::sequence::tuple; use super::org_source::OrgSource; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::parser_with_context; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; -use crate::parser::LatexFragment; +use crate::types::LatexFragment; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn latex_fragment<'r, 's>( - context: Context<'r, 's>, +pub fn latex_fragment<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, LatexFragment<'s>> { let (remaining, _) = alt(( @@ -48,8 +48,8 @@ pub fn latex_fragment<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn raw_latex_fragment<'r, 's>( - context: Context<'r, 's>, +fn raw_latex_fragment<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, _) = tag("\\")(input)?; @@ -61,16 +61,16 @@ fn raw_latex_fragment<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn name<'r, 's>( - _context: Context<'r, 's>, +fn name<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { alpha1(input) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn brackets<'r, 's>( - context: Context<'r, 's>, +fn brackets<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, body) = alt(( @@ -101,8 +101,8 @@ fn brackets<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn escaped_parenthesis_fragment<'r, 's>( - context: Context<'r, 's>, +fn escaped_parenthesis_fragment<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, _) = tag("\\(")(input)?; @@ -120,8 +120,8 @@ fn escaped_parenthesis_fragment<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn escaped_bracket_fragment<'r, 's>( - context: Context<'r, 's>, +fn escaped_bracket_fragment<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, _) = tag("\\[")(input)?; @@ -139,8 +139,8 @@ fn escaped_bracket_fragment<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn double_dollar_fragment<'r, 's>( - context: Context<'r, 's>, +fn double_dollar_fragment<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { // TODO: The documentation on the dollar sign versions is incomplete. Test to figure out what the real requirements are. For example, can this span more than 3 lines and can this contain a single $ since its terminated by $$? @@ -159,8 +159,8 @@ fn double_dollar_fragment<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn dollar_char_fragment<'r, 's>( - context: Context<'r, 's>, +fn dollar_char_fragment<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (_, _) = pre(context, input)?; @@ -174,7 +174,10 @@ fn dollar_char_fragment<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res, ()> { +pub fn pre<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, + input: OrgSource<'s>, +) -> Res, ()> { let preceding_character = input.get_preceding_character(); if let Some('$') = preceding_character { return Err(nom::Err::Error(CustomError::MyError(MyError( @@ -185,7 +188,10 @@ pub fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res, ()> { +pub fn post<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, + input: OrgSource<'s>, +) -> Res, ()> { // TODO: What about eof? Test to find out. // TODO: Figure out which punctuation characters should be included. @@ -194,8 +200,8 @@ pub fn post<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res( - context: Context<'r, 's>, +fn bordered_dollar_fragment<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (_, _) = pre(context, input)?; @@ -220,16 +226,16 @@ fn bordered_dollar_fragment<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn open_border<'r, 's>( - _context: Context<'r, 's>, +pub fn open_border<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(verify(none_of(".,;$"), |c| !c.is_whitespace()))(input) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn close_border<'r, 's>( - _context: Context<'r, 's>, +pub fn close_border<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, ()> { let preceding_character = input.get_preceding_character(); diff --git a/src/parser/lesser_block.rs b/src/parser/lesser_block.rs index 9615727..0caaca0 100644 --- a/src/parser/lesser_block.rs +++ b/src/parser/lesser_block.rs @@ -12,42 +12,47 @@ use nom::multi::many_till; use nom::sequence::tuple; use super::org_source::OrgSource; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ContextMatcher; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::lesser_element::CommentBlock; -use crate::parser::lesser_element::ExampleBlock; -use crate::parser::lesser_element::ExportBlock; -use crate::parser::lesser_element::SrcBlock; -use crate::parser::lesser_element::VerseBlock; -use crate::parser::object::Object; -use crate::parser::object::PlainText; use crate::parser::object_parser::standard_set_object; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::blank_line; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::start_of_line; use crate::parser::util::text_until_exit; +use crate::types::CommentBlock; +use crate::types::ExampleBlock; +use crate::types::ExportBlock; +use crate::types::Object; +use crate::types::PlainText; +use crate::types::SrcBlock; +use crate::types::VerseBlock; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn verse_block<'r, 's>( - context: Context<'r, 's>, +pub fn verse_block<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, VerseBlock<'s>> { let (remaining, name) = lesser_block_begin("verse")(context, input)?; let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; let (remaining, _nl) = line_ending(remaining)?; let lesser_block_end_specialized = lesser_block_end("verse"); - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context("lesser block")) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context("lesser block"), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Beta, exit_matcher: &lesser_block_end_specialized, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); let parameters = match parameters { Some((_ws, parameters)) => Some(parameters), None => None, @@ -84,21 +89,25 @@ pub fn verse_block<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn comment_block<'r, 's>( - context: Context<'r, 's>, +pub fn comment_block<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, CommentBlock<'s>> { let (remaining, name) = lesser_block_begin("comment")(context, input)?; let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; let (remaining, _nl) = line_ending(remaining)?; let lesser_block_end_specialized = lesser_block_end("comment"); - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context("lesser block")) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context("lesser block"), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Beta, exit_matcher: &lesser_block_end_specialized, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); let parameters = match parameters { Some((_ws, parameters)) => Some(parameters), None => None, @@ -120,21 +129,25 @@ pub fn comment_block<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn example_block<'r, 's>( - context: Context<'r, 's>, +pub fn example_block<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, ExampleBlock<'s>> { let (remaining, _name) = lesser_block_begin("example")(context, input)?; let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; let (remaining, _nl) = line_ending(remaining)?; let lesser_block_end_specialized = lesser_block_end("example"); - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context("lesser block")) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context("lesser block"), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Beta, exit_matcher: &lesser_block_end_specialized, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); let parameters = match parameters { Some((_ws, parameters)) => Some(parameters), None => None, @@ -156,8 +169,8 @@ pub fn example_block<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn export_block<'r, 's>( - context: Context<'r, 's>, +pub fn export_block<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, ExportBlock<'s>> { let (remaining, name) = lesser_block_begin("export")(context, input)?; @@ -165,13 +178,17 @@ pub fn export_block<'r, 's>( let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; let (remaining, _nl) = line_ending(remaining)?; let lesser_block_end_specialized = lesser_block_end("export"); - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context("lesser block")) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context("lesser block"), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Beta, exit_matcher: &lesser_block_end_specialized, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); let parameters = match parameters { Some((_ws, parameters)) => Some(parameters), None => None, @@ -193,8 +210,8 @@ pub fn export_block<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn src_block<'r, 's>( - context: Context<'r, 's>, +pub fn src_block<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, SrcBlock<'s>> { let (remaining, name) = lesser_block_begin("src")(context, input)?; @@ -202,13 +219,17 @@ pub fn src_block<'r, 's>( let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; let (remaining, _nl) = line_ending(remaining)?; let lesser_block_end_specialized = lesser_block_end("src"); - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context("lesser block")) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context("lesser block"), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Alpha, exit_matcher: &lesser_block_end_specialized, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); let parameters = match parameters { Some((_ws, parameters)) => Some(parameters), None => None, @@ -239,20 +260,18 @@ fn data<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { is_not("\r\n")(input) } -fn lesser_block_end( - current_name: &str, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { +fn lesser_block_end(current_name: &str) -> impl ContextMatcher { let current_name_lower = current_name.to_lowercase(); - move |context: Context, input: OrgSource<'_>| { + move |context, input: OrgSource<'_>| { _lesser_block_end(context, input, current_name_lower.as_str()) } } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _lesser_block_end<'r, 's, 'x>( - _context: Context<'r, 's>, +fn _lesser_block_end<'b, 'g, 'r, 's, 'c>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, - current_name_lower: &'x str, + current_name_lower: &'c str, ) -> Res, OrgSource<'s>> { start_of_line(input)?; let (remaining, _leading_whitespace) = space0(input)?; @@ -268,18 +287,16 @@ fn _lesser_block_end<'r, 's, 'x>( /// Parser for the beginning of a lesser block /// /// current_name MUST be lowercase. We do not do the conversion ourselves because it is not allowed in a const fn. -const fn lesser_block_begin( - current_name: &'static str, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { +const fn lesser_block_begin<'c>(current_name: &'c str) -> impl ContextMatcher + 'c { // TODO: Since this is a const fn, is there ANY way to "generate" functions at compile time? - move |context: Context, input: OrgSource<'_>| _lesser_block_begin(context, input, current_name) + move |context, input: OrgSource<'_>| _lesser_block_begin(context, input, current_name) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _lesser_block_begin<'r, 's, 'x>( - _context: Context<'r, 's>, +fn _lesser_block_begin<'b, 'g, 'r, 's, 'c>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, - current_name_lower: &'x str, + current_name_lower: &'c str, ) -> Res, OrgSource<'s>> { start_of_line(input)?; let (remaining, _leading_whitespace) = space0(input)?; diff --git a/src/parser/line_break.rs b/src/parser/line_break.rs index c38f3e0..a0c721a 100644 --- a/src/parser/line_break.rs +++ b/src/parser/line_break.rs @@ -5,16 +5,16 @@ use nom::combinator::recognize; use nom::multi::many0; use super::org_source::OrgSource; -use super::Context; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; use crate::parser::util::get_consumed; -use crate::parser::LineBreak; +use crate::types::LineBreak; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn line_break<'r, 's>( - context: Context<'r, 's>, +pub fn line_break<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, LineBreak<'s>> { let (remaining, _) = pre(context, input)?; @@ -31,7 +31,10 @@ pub fn line_break<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res, ()> { +fn pre<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, + input: OrgSource<'s>, +) -> Res, ()> { let preceding_character = input.get_preceding_character(); match preceding_character { // If None, we are at the start of the file diff --git a/src/parser/list.rs b/src/parser/list.rs deleted file mode 100644 index 3266ca0..0000000 --- a/src/parser/list.rs +++ /dev/null @@ -1,183 +0,0 @@ -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 { - data: T, - parent: Option>>, -} - -impl Node { - pub fn get_data(&self) -> &T { - &self.data - } -} - -impl List { - pub fn new() -> Self { - List { head: None } - } - - 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, - } - } -} - -pub struct NodeIter<'a, T> { - position: &'a Option>>, -} - -impl<'a, T> Iterator for NodeIter<'a, T> { - type Item = &'a Rc>; - - 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 - } -} diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 639af9a..eae8a04 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -7,16 +7,13 @@ mod diary_sexp; mod document; mod drawer; mod dynamic_block; -mod element; mod element_parser; mod entity; -mod exiting; mod export_snippet; mod fixed_width_area; mod footnote_definition; mod footnote_reference; mod greater_block; -mod greater_element; mod horizontal_rule; mod inline_babel_call; mod inline_source_block; @@ -24,16 +21,11 @@ mod keyword; mod latex_environment; mod latex_fragment; mod lesser_block; -mod lesser_element; mod line_break; -mod list; -mod object; mod object_parser; mod org_macro; mod org_source; mod paragraph; -mod parser_context; -mod parser_with_context; mod plain_link; mod plain_list; mod plain_text; @@ -42,7 +34,6 @@ mod property_drawer; mod radio_link; mod regular_link; pub mod sexp; -mod source; mod statistics_cookie; mod subscript_and_superscript; mod table; @@ -52,62 +43,5 @@ mod timestamp; mod token; mod util; pub use document::document; -pub use document::Document; -pub use document::DocumentElement; -pub use document::Heading; -pub use document::Section; -pub use element::Element; -pub use greater_element::Drawer; -pub use greater_element::DynamicBlock; -pub use greater_element::FootnoteDefinition; -pub use greater_element::GreaterBlock; -pub use greater_element::PlainList; -pub use greater_element::PlainListItem; -pub use greater_element::PropertyDrawer; -pub use greater_element::Table; -pub use greater_element::TableRow; -pub use lesser_element::Clock; -pub use lesser_element::Comment; -pub use lesser_element::CommentBlock; -pub use lesser_element::DiarySexp; -pub use lesser_element::ExampleBlock; -pub use lesser_element::ExportBlock; -pub use lesser_element::FixedWidthArea; -pub use lesser_element::HorizontalRule; -pub use lesser_element::Keyword; -pub use lesser_element::LatexEnvironment; -pub use lesser_element::Paragraph; -pub use lesser_element::Planning; -pub use lesser_element::SrcBlock; -pub use lesser_element::TableCell; -pub use lesser_element::VerseBlock; -pub use object::AngleLink; -pub use object::Bold; -pub use object::Citation; -pub use object::CitationReference; -pub use object::Code; -pub use object::Entity; -pub use object::ExportSnippet; -pub use object::FootnoteReference; -pub use object::InlineBabelCall; -pub use object::InlineSourceBlock; -pub use object::Italic; -pub use object::LatexFragment; -pub use object::LineBreak; -pub use object::Object; -pub use object::OrgMacro; -pub use object::PlainLink; -pub use object::PlainText; -pub use object::RadioLink; -pub use object::RadioTarget; -pub use object::RegularLink; -pub use object::StatisticsCookie; -pub use object::StrikeThrough; -pub use object::Subscript; -pub use object::Superscript; -pub use object::Target; -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>; +pub use document::parse; +pub use org_source::OrgSource; diff --git a/src/parser/object_parser.rs b/src/parser/object_parser.rs index 18faf11..e3db553 100644 --- a/src/parser/object_parser.rs +++ b/src/parser/object_parser.rs @@ -2,10 +2,10 @@ use nom::branch::alt; use nom::combinator::map; use super::org_source::OrgSource; -use super::parser_with_context::parser_with_context; use super::plain_text::plain_text; use super::regular_link::regular_link; -use super::Context; +use crate::context::parser_with_context; +use crate::context::RefContext; use crate::error::Res; use crate::parser::angle_link::angle_link; use crate::parser::citation::citation; @@ -16,7 +16,6 @@ use crate::parser::inline_babel_call::inline_babel_call; use crate::parser::inline_source_block::inline_source_block; use crate::parser::latex_fragment::latex_fragment; use crate::parser::line_break::line_break; -use crate::parser::object::Object; use crate::parser::org_macro::org_macro; use crate::parser::plain_link::plain_link; use crate::parser::radio_link::radio_link; @@ -27,10 +26,11 @@ use crate::parser::subscript_and_superscript::superscript; use crate::parser::target::target; use crate::parser::text_markup::text_markup; use crate::parser::timestamp::timestamp; +use crate::types::Object; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn standard_set_object<'r, 's>( - context: Context<'r, 's>, +pub fn standard_set_object<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Object<'s>> { let (remaining, object) = alt(( @@ -87,8 +87,8 @@ pub fn standard_set_object<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn minimal_set_object<'r, 's>( - context: Context<'r, 's>, +pub fn minimal_set_object<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Object<'s>> { let (remaining, object) = alt(( @@ -109,8 +109,8 @@ pub fn minimal_set_object<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn any_object_except_plain_text<'r, 's>( - context: Context<'r, 's>, +pub fn any_object_except_plain_text<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Object<'s>> { let (remaining, object) = alt(( @@ -166,8 +166,8 @@ pub fn any_object_except_plain_text<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn regular_link_description_object_set<'r, 's>( - context: Context<'r, 's>, +pub fn regular_link_description_object_set<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Object<'s>> { // TODO: It can also contain another link, but only when it is a plain or angle link. It can contain square brackets, but not ]] @@ -195,8 +195,8 @@ pub fn regular_link_description_object_set<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn table_cell_set_object<'r, 's>( - context: Context<'r, 's>, +pub fn table_cell_set_object<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Object<'s>> { let (remaining, object) = alt(( diff --git a/src/parser/org_macro.rs b/src/parser/org_macro.rs index 65a86c4..cf89c3b 100644 --- a/src/parser/org_macro.rs +++ b/src/parser/org_macro.rs @@ -9,17 +9,17 @@ use nom::multi::separated_list0; use super::org_source::OrgSource; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::parser_with_context; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::Res; -use crate::parser::object::OrgMacro; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; +use crate::types::OrgMacro; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn org_macro<'r, 's>( - context: Context<'r, 's>, +pub fn org_macro<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgMacro<'s>> { let (remaining, _) = tag("{{{")(input)?; @@ -45,8 +45,8 @@ pub fn org_macro<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn org_macro_name<'r, 's>( - _context: Context<'r, 's>, +fn org_macro_name<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, _) = verify(anychar, |c| c.is_alphabetic())(input)?; @@ -58,8 +58,8 @@ fn org_macro_name<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn org_macro_args<'r, 's>( - context: Context<'r, 's>, +fn org_macro_args<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Vec>> { let (remaining, _) = tag("(")(input)?; @@ -71,8 +71,8 @@ fn org_macro_args<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn org_macro_arg<'r, 's>( - context: Context<'r, 's>, +fn org_macro_arg<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let mut remaining = input; diff --git a/src/parser/org_source.rs b/src/parser/org_source.rs index 231cb10..dc2bf0c 100644 --- a/src/parser/org_source.rs +++ b/src/parser/org_source.rs @@ -27,7 +27,7 @@ pub struct OrgSource<'s> { impl<'s> std::fmt::Debug for OrgSource<'s> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("OrgSource") + f.debug_tuple("Org") .field(&Into::<&str>::into(self)) .finish() } diff --git a/src/parser/paragraph.rs b/src/parser/paragraph.rs index 9cfda4d..2f7345a 100644 --- a/src/parser/paragraph.rs +++ b/src/parser/paragraph.rs @@ -7,30 +7,30 @@ use nom::multi::many_till; use nom::sequence::tuple; use super::element_parser::detect_element; -use super::lesser_element::Paragraph; use super::org_source::OrgSource; use super::util::blank_line; use super::util::get_consumed; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::Res; -use crate::parser::exiting::ExitClass; use crate::parser::object_parser::standard_set_object; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::start_of_line; +use crate::types::Paragraph; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn paragraph<'r, 's>( - context: Context<'r, 's>, +pub fn paragraph<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Paragraph<'s>> { - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: ¶graph_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: ¶graph_end, + }); + let parser_context = context.with_additional_node(&parser_context); let standard_set_object_matcher = parser_with_context!(standard_set_object)(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); @@ -53,8 +53,8 @@ pub fn paragraph<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn paragraph_end<'r, 's>( - context: Context<'r, 's>, +fn paragraph_end<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let non_paragraph_element_matcher = parser_with_context!(detect_element(false))(context); @@ -67,16 +67,21 @@ fn paragraph_end<'r, 's>( #[cfg(test)] mod tests { + use crate::context::parser_with_context; + use crate::context::Context; + use crate::context::ContextElement; + use crate::context::GlobalSettings; + use crate::context::List; use crate::parser::element_parser::element; use crate::parser::org_source::OrgSource; - use crate::parser::parser_context::ContextTree; - use crate::parser::parser_with_context::parser_with_context; - use crate::parser::source::Source; + use crate::types::Source; #[test] fn two_paragraphs() { let input = OrgSource::new("foo bar baz\n\nlorem ipsum"); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let paragraph_matcher = parser_with_context!(element(true))(&initial_context); let (remaining, first_paragraph) = paragraph_matcher(input).expect("Parse first paragraph"); let (remaining, second_paragraph) = diff --git a/src/parser/plain_link.rs b/src/parser/plain_link.rs index 387f788..0c7735a 100644 --- a/src/parser/plain_link.rs +++ b/src/parser/plain_link.rs @@ -11,18 +11,18 @@ use nom::combinator::verify; use nom::multi::many_till; use super::org_source::OrgSource; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::object::PlainLink; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::WORD_CONSTITUENT_CHARACTERS; +use crate::types::PlainLink; // TODO: Make this a user-provided variable corresponding to elisp's org-link-parameters const ORG_LINK_PARAMETERS: [&'static str; 23] = [ @@ -52,8 +52,8 @@ const ORG_LINK_PARAMETERS: [&'static str; 23] = [ ]; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn plain_link<'r, 's>( - context: Context<'r, 's>, +pub fn plain_link<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, PlainLink<'s>> { let (remaining, _) = pre(context, input)?; @@ -73,7 +73,10 @@ pub fn plain_link<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res, ()> { +fn pre<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, + input: OrgSource<'s>, +) -> Res, ()> { let preceding_character = input.get_preceding_character(); match preceding_character { // If None, we are at the start of the file which is fine @@ -90,14 +93,17 @@ fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res, ()> { +fn post<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, + input: OrgSource<'s>, +) -> Res, ()> { let (remaining, _) = alt((eof, recognize(none_of(WORD_CONSTITUENT_CHARACTERS))))(input)?; Ok((remaining, ())) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn protocol<'r, 's>( - _context: Context<'r, 's>, +pub fn protocol<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { // TODO: This should be defined by org-link-parameters @@ -117,16 +123,16 @@ pub fn protocol<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn path_plain<'r, 's>( - context: Context<'r, 's>, +fn path_plain<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { // TODO: "optionally containing parenthesis-wrapped non-whitespace non-bracket substrings up to a depth of two. The string must end with either a non-punctation non-whitespace character, a forwards slash, or a parenthesis-wrapped substring" - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &path_plain_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &path_plain_end, + }); + let parser_context = context.with_additional_node(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); @@ -139,8 +145,8 @@ fn path_plain<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn path_plain_end<'r, 's>( - _context: Context<'r, 's>, +fn path_plain_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(many_till( diff --git a/src/parser/plain_list.rs b/src/parser/plain_list.rs index 8773008..f387951 100644 --- a/src/parser/plain_list.rs +++ b/src/parser/plain_list.rs @@ -16,26 +16,27 @@ use nom::multi::many1; use nom::multi::many_till; use nom::sequence::tuple; -use super::greater_element::PlainList; -use super::greater_element::PlainListItem; +use super::element_parser::element; use super::object_parser::standard_set_object; use super::org_source::OrgSource; -use super::parser_with_context::parser_with_context; use super::util::non_whitespace_character; -use super::Context; -use super::Object; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ContextMatcher; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::element_parser::element; -use crate::parser::exiting::ExitClass; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; use crate::parser::util::blank_line; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; use crate::parser::util::start_of_line; +use crate::types::Object; +use crate::types::PlainList; +use crate::types::PlainListItem; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] pub fn detect_plain_list<'s>(input: OrgSource<'s>) -> Res, ()> { @@ -60,17 +61,22 @@ pub fn detect_plain_list<'s>(input: OrgSource<'s>) -> Res, ()> { } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn plain_list<'r, 's>( - context: Context<'r, 's>, +pub fn plain_list<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, PlainList<'s>> { - let parser_context = context - .with_additional_node(ContextElement::Context("plain list")) - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::Context("plain list"), + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Beta, exit_matcher: &plain_list_end, - })); + }), + ]; + + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); // children stores tuple of (input string, parsed object) so we can re-parse the final item let mut children = Vec::new(); let mut first_item_indentation: Option = None; @@ -112,8 +118,8 @@ pub fn plain_list<'r, 's>( )))); } }; - let final_item_context = - parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false)); + let final_item_context = ContextElement::ConsumeTrailingWhitespace(false); + let final_item_context = parser_context.with_additional_node(&final_item_context); let (remaining, reparsed_final_item) = parser_with_context!(plain_list_item)(&final_item_context)(final_child_start)?; children.push((final_child_start, reparsed_final_item)); @@ -129,8 +135,8 @@ pub fn plain_list<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn plain_list_item<'r, 's>( - context: Context<'r, 's>, +pub fn plain_list_item<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, PlainListItem<'s>> { start_of_line(input)?; @@ -169,12 +175,15 @@ pub fn plain_list_item<'r, 's>( }; let (remaining, _ws) = item_tag_post_gap(context, remaining)?; let exit_matcher = plain_list_item_end(indent_level); - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Beta, exit_matcher: &exit_matcher, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); let (mut remaining, (mut children, _exit_contents)) = many_till( include_input(parser_with_context!(element(true))(&parser_context)), @@ -182,8 +191,8 @@ pub fn plain_list_item<'r, 's>( )(remaining)?; if !children.is_empty() && !context.should_consume_trailing_whitespace() { - let final_item_context = - parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false)); + let final_item_context = ContextElement::ConsumeTrailingWhitespace(false); + let final_item_context = parser_context.with_additional_node(&final_item_context); let (final_child_start, _original_final_child) = children .pop() .expect("if-statement already checked that children was non-empty."); @@ -240,8 +249,8 @@ fn counter<'s>(i: OrgSource<'s>) -> Res, OrgSource<'s>> { } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn plain_list_end<'r, 's>( - _context: Context<'r, 's>, +fn plain_list_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(tuple(( @@ -252,11 +261,9 @@ fn plain_list_end<'r, 's>( )))(input) } -const fn plain_list_item_end( - indent_level: usize, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { +const fn plain_list_item_end(indent_level: usize) -> impl ContextMatcher { let line_indented_lte_matcher = line_indented_lte(indent_level); - move |context: Context, input: OrgSource<'_>| { + move |context, input: OrgSource<'_>| { _plain_list_item_end(context, input, &line_indented_lte_matcher) } } @@ -265,13 +272,10 @@ const fn plain_list_item_end( feature = "tracing", tracing::instrument(ret, level = "debug", skip(line_indented_lte_matcher)) )] -fn _plain_list_item_end<'r, 's>( - context: Context<'r, 's>, +fn _plain_list_item_end<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, - line_indented_lte_matcher: impl for<'rr, 'ss> Fn( - Context<'rr, 'ss>, - OrgSource<'ss>, - ) -> Res, OrgSource<'ss>>, + line_indented_lte_matcher: impl ContextMatcher, ) -> Res, OrgSource<'s>> { start_of_line(input)?; recognize(tuple(( @@ -280,15 +284,13 @@ fn _plain_list_item_end<'r, 's>( )))(input) } -const fn line_indented_lte( - indent_level: usize, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - move |context: Context, input: OrgSource<'_>| _line_indented_lte(context, input, indent_level) +const fn line_indented_lte(indent_level: usize) -> impl ContextMatcher { + move |context, input: OrgSource<'_>| _line_indented_lte(context, input, indent_level) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _line_indented_lte<'r, 's>( - _context: Context<'r, 's>, +fn _line_indented_lte<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, indent_level: usize, ) -> Res, OrgSource<'s>> { @@ -302,15 +304,15 @@ fn _line_indented_lte<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn item_tag<'r, 's>( - context: Context<'r, 's>, +fn item_tag<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Vec>> { - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &item_tag_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &item_tag_end, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, (children, _exit_contents)) = verify( many_till( // TODO: Should this be using a different set like the minimal set? @@ -323,8 +325,8 @@ fn item_tag<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn item_tag_end<'r, 's>( - _context: Context<'r, 's>, +fn item_tag_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(alt(( @@ -335,8 +337,8 @@ fn item_tag_end<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn item_tag_post_gap<'r, 's>( - context: Context<'r, 's>, +fn item_tag_post_gap<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { verify( @@ -358,14 +360,17 @@ fn item_tag_post_gap<'r, 's>( #[cfg(test)] mod tests { use super::*; - use crate::parser::parser_context::ContextTree; - use crate::parser::parser_with_context::parser_with_context; - use crate::parser::Source; + use crate::context::Context; + use crate::context::GlobalSettings; + use crate::context::List; + use crate::types::Source; #[test] fn plain_list_item_empty() { let input = OrgSource::new("1."); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let plain_list_item_matcher = parser_with_context!(plain_list_item)(&initial_context); let (remaining, result) = plain_list_item_matcher(input).unwrap(); assert_eq!(Into::<&str>::into(remaining), ""); @@ -375,7 +380,9 @@ mod tests { #[test] fn plain_list_item_simple() { let input = OrgSource::new("1. foo"); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let plain_list_item_matcher = parser_with_context!(plain_list_item)(&initial_context); let (remaining, result) = plain_list_item_matcher(input).unwrap(); assert_eq!(Into::<&str>::into(remaining), ""); @@ -385,7 +392,9 @@ mod tests { #[test] fn plain_list_empty() { let input = OrgSource::new("1."); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let plain_list_matcher = parser_with_context!(plain_list)(&initial_context); let (remaining, result) = plain_list_matcher(input).unwrap(); assert_eq!(Into::<&str>::into(remaining), ""); @@ -395,7 +404,9 @@ mod tests { #[test] fn plain_list_simple() { let input = OrgSource::new("1. foo"); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let plain_list_matcher = parser_with_context!(plain_list)(&initial_context); let (remaining, result) = plain_list_matcher(input).unwrap(); assert_eq!(Into::<&str>::into(remaining), ""); @@ -406,7 +417,9 @@ mod tests { fn plain_list_cant_start_line_with_asterisk() { // Plain lists with an asterisk bullet must be indented or else they would be a headline let input = OrgSource::new("* foo"); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let plain_list_matcher = parser_with_context!(plain_list)(&initial_context); let result = plain_list_matcher(input); assert!(result.is_err()); @@ -416,7 +429,9 @@ mod tests { fn indented_can_start_line_with_asterisk() { // Plain lists with an asterisk bullet must be indented or else they would be a headline let input = OrgSource::new(" * foo"); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let plain_list_matcher = parser_with_context!(plain_list)(&initial_context); let result = plain_list_matcher(input); assert!(result.is_ok()); @@ -434,7 +449,9 @@ mod tests { ipsum "#, ); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let plain_list_matcher = parser_with_context!(element(true))(&initial_context); let (remaining, result) = plain_list_matcher(input).expect("Should parse the plain list successfully."); @@ -460,7 +477,9 @@ mod tests { baz"#, ); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let plain_list_matcher = parser_with_context!(element(true))(&initial_context); let (remaining, result) = plain_list_matcher(input).expect("Should parse the plain list successfully."); @@ -491,7 +510,9 @@ baz"#, dolar"#, ); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let plain_list_matcher = parser_with_context!(element(true))(&initial_context); let (remaining, result) = plain_list_matcher(input).expect("Should parse the plain list successfully."); diff --git a/src/parser/plain_text.rs b/src/parser/plain_text.rs index 7d0423d..1dbc295 100644 --- a/src/parser/plain_text.rs +++ b/src/parser/plain_text.rs @@ -7,19 +7,19 @@ use nom::combinator::recognize; use nom::combinator::verify; use nom::multi::many_till; -use super::object::PlainText; +use super::object_parser::any_object_except_plain_text; use super::org_source::OrgSource; use super::radio_link::RematchObject; -use super::Context; -use super::Object; +use super::util::exit_matcher_parser; +use crate::context::parser_with_context; +use crate::context::RefContext; use crate::error::Res; -use crate::parser::object_parser::any_object_except_plain_text; -use crate::parser::parser_with_context::parser_with_context; -use crate::parser::util::exit_matcher_parser; +use crate::types::Object; +use crate::types::PlainText; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn plain_text<'r, 's>( - context: Context<'r, 's>, +pub fn plain_text<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, PlainText<'s>> { let (remaining, source) = recognize(verify( @@ -42,8 +42,8 @@ pub fn plain_text<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn plain_text_end<'r, 's>( - context: Context<'r, 's>, +fn plain_text_end<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(parser_with_context!(any_object_except_plain_text)(context))(input) @@ -51,9 +51,9 @@ fn plain_text_end<'r, 's>( impl<'x> RematchObject<'x> for PlainText<'x> { #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] - fn rematch_object<'r, 's>( + fn rematch_object<'b, 'g, 'r, 's>( &'x self, - _context: Context<'r, 's>, + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Object<'s>> { map(tag(self.source), |s| { @@ -69,14 +69,18 @@ mod tests { use nom::combinator::map; use super::*; - use crate::parser::parser_context::ContextTree; - use crate::parser::parser_with_context::parser_with_context; - use crate::parser::source::Source; + use crate::context::Context; + use crate::context::ContextElement; + use crate::context::GlobalSettings; + use crate::context::List; + use crate::types::Source; #[test] fn plain_text_simple() { let input = OrgSource::new("foobarbaz"); - let initial_context: ContextTree<'_, '_> = ContextTree::new(); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); let plain_text_matcher = parser_with_context!(plain_text)(&initial_context); let (remaining, result) = map(plain_text_matcher, Object::PlainText)(input).unwrap(); assert_eq!(Into::<&str>::into(remaining), ""); diff --git a/src/parser/planning.rs b/src/parser/planning.rs index e6ea8e3..77e70c1 100644 --- a/src/parser/planning.rs +++ b/src/parser/planning.rs @@ -10,15 +10,15 @@ use nom::multi::separated_list1; use nom::sequence::tuple; use super::org_source::OrgSource; -use super::Context; +use crate::context::RefContext; use crate::error::Res; -use crate::parser::lesser_element::Planning; use crate::parser::util::get_consumed; use crate::parser::util::start_of_line; +use crate::types::Planning; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn planning<'r, 's>( - _context: Context<'r, 's>, +pub fn planning<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Planning<'s>> { start_of_line(input)?; diff --git a/src/parser/property_drawer.rs b/src/parser/property_drawer.rs index 8e73ba3..ca0938f 100644 --- a/src/parser/property_drawer.rs +++ b/src/parser/property_drawer.rs @@ -14,25 +14,25 @@ use nom::multi::many_till; use nom::sequence::tuple; use super::org_source::OrgSource; -use super::Context; +use super::util::exit_matcher_parser; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::greater_element::NodeProperty; -use crate::parser::greater_element::PropertyDrawer; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; -use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::immediate_in_section; use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; use crate::parser::util::start_of_line; +use crate::types::NodeProperty; +use crate::types::PropertyDrawer; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn property_drawer<'r, 's>( - context: Context<'r, 's>, +pub fn property_drawer<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, PropertyDrawer<'s>> { if immediate_in_section(context, "property-drawer") { @@ -51,13 +51,17 @@ pub fn property_drawer<'r, 's>( line_ending, ))(input)?; - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context("property-drawer")) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context("property-drawer"), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Alpha, exit_matcher: &property_drawer_end, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); let node_property_matcher = parser_with_context!(node_property)(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); @@ -79,8 +83,8 @@ pub fn property_drawer<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn property_drawer_end<'r, 's>( - _context: Context<'r, 's>, +fn property_drawer_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(tuple(( @@ -93,8 +97,8 @@ fn property_drawer_end<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn node_property<'r, 's>( - context: Context<'r, 's>, +fn node_property<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, NodeProperty<'s>> { let (remaining, (_start_of_line, _leading_whitespace, _open_colon, _name, _close_colon)) = @@ -136,15 +140,15 @@ fn node_property<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn node_property_name<'r, 's>( - context: Context<'r, 's>, +fn node_property_name<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Beta, - exit_matcher: &node_property_name_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &node_property_name_end, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, name) = recognize(tuple(( verify( @@ -161,8 +165,8 @@ fn node_property_name<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn node_property_name_end<'r, 's>( - _context: Context<'r, 's>, +fn node_property_name_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { alt((tag("+:"), tag(":")))(input) diff --git a/src/parser/radio_link.rs b/src/parser/radio_link.rs index bbe8f07..ec1e444 100644 --- a/src/parser/radio_link.rs +++ b/src/parser/radio_link.rs @@ -5,31 +5,31 @@ use nom::character::complete::space0; use nom::combinator::verify; use nom::multi::many_till; +use super::object_parser::minimal_set_object; use super::org_source::OrgSource; +use super::util::exit_matcher_parser; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; -use super::Object; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::object_parser::minimal_set_object; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; -use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; -use crate::parser::RadioLink; -use crate::parser::RadioTarget; +use crate::types::Object; +use crate::types::RadioLink; +use crate::types::RadioTarget; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn radio_link<'r, 's>( - context: Context<'r, 's>, +pub fn radio_link<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, RadioLink<'s>> { let radio_targets = context .iter() - .filter_map(|context_element| match context_element.get_data() { + .filter_map(|context_element| match context_element { ContextElement::RadioTarget(targets) => Some(targets), _ => None, }) @@ -54,8 +54,8 @@ pub fn radio_link<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn rematch_target<'x, 'r, 's>( - context: Context<'r, 's>, +pub fn rematch_target<'x, 'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, target: &'x Vec>, input: OrgSource<'s>, ) -> Res, Vec>> { @@ -85,16 +85,16 @@ pub fn rematch_target<'x, 'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn radio_target<'r, 's>( - context: Context<'r, 's>, +pub fn radio_target<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, RadioTarget<'s>> { let (remaining, _opening) = tag("<<<")(input)?; - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &radio_target_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &radio_target_end, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, (children, _exit_contents)) = verify( many_till( @@ -118,17 +118,17 @@ pub fn radio_target<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn radio_target_end<'r, 's>( - _context: Context<'r, 's>, +fn radio_target_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { alt((tag("<"), tag(">"), line_ending))(input) } pub trait RematchObject<'x> { - fn rematch_object<'r, 's>( + fn rematch_object<'b, 'g, 'r, 's>( &'x self, - context: Context<'r, 's>, + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Object<'s>>; } @@ -136,25 +136,28 @@ pub trait RematchObject<'x> { #[cfg(test)] mod tests { use super::*; + use crate::context::Context; + use crate::context::GlobalSettings; + use crate::context::List; use crate::parser::element_parser::element; - use crate::parser::parser_context::ContextElement; - use crate::parser::parser_context::ContextTree; - use crate::parser::parser_with_context::parser_with_context; - use crate::parser::source::Source; - use crate::parser::Bold; - use crate::parser::PlainText; + use crate::types::Bold; + use crate::types::Element; + use crate::types::PlainText; + use crate::types::Source; #[test] fn plain_text_radio_target() { let input = OrgSource::new("foo bar baz"); let radio_target_match = vec![Object::PlainText(PlainText { source: "bar" })]; - let initial_context: ContextTree<'_, '_> = ContextTree::new(); - let document_context = initial_context - .with_additional_node(ContextElement::RadioTarget(vec![&radio_target_match])); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); + let document_context = ContextElement::RadioTarget(vec![&radio_target_match]); + let document_context = initial_context.with_additional_node(&document_context); let paragraph_matcher = parser_with_context!(element(true))(&document_context); let (remaining, first_paragraph) = paragraph_matcher(input).expect("Parse first paragraph"); let first_paragraph = match first_paragraph { - crate::parser::Element::Paragraph(paragraph) => paragraph, + Element::Paragraph(paragraph) => paragraph, _ => panic!("Should be a paragraph!"), }; assert_eq!(Into::<&str>::into(remaining), ""); @@ -179,14 +182,16 @@ mod tests { source: "*bar*", children: vec![Object::PlainText(PlainText { source: "bar" })], })]; - let initial_context: ContextTree<'_, '_> = ContextTree::new(); - let document_context = initial_context - .with_additional_node(ContextElement::RadioTarget(vec![&radio_target_match])); + let global_settings = GlobalSettings::default(); + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(&global_settings, List::new(&initial_context)); + let document_context = ContextElement::RadioTarget(vec![&radio_target_match]); + let document_context = initial_context.with_additional_node(&document_context); let paragraph_matcher = parser_with_context!(element(true))(&document_context); let (remaining, first_paragraph) = paragraph_matcher(input.into()).expect("Parse first paragraph"); let first_paragraph = match first_paragraph { - crate::parser::Element::Paragraph(paragraph) => paragraph, + Element::Paragraph(paragraph) => paragraph, _ => panic!("Should be a paragraph!"), }; assert_eq!(Into::<&str>::into(remaining), ""); diff --git a/src/parser/regular_link.rs b/src/parser/regular_link.rs index 9a36d09..615e77f 100644 --- a/src/parser/regular_link.rs +++ b/src/parser/regular_link.rs @@ -6,23 +6,23 @@ use nom::character::complete::one_of; use nom::combinator::verify; use nom::multi::many_till; +use super::object_parser::regular_link_description_object_set; use super::org_source::OrgSource; -use super::parser_with_context::parser_with_context; +use super::util::exit_matcher_parser; use super::util::get_consumed; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; -use super::Object; -use super::RegularLink; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::object_parser::regular_link_description_object_set; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::util::exit_matcher_parser; +use crate::types::Object; +use crate::types::RegularLink; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn regular_link<'r, 's>( - context: Context<'r, 's>, +pub fn regular_link<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, RegularLink<'s>> { alt(( @@ -32,8 +32,8 @@ pub fn regular_link<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn regular_link_without_description<'r, 's>( - context: Context<'r, 's>, +pub fn regular_link_without_description<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, RegularLink<'s>> { let (remaining, _opening_bracket) = tag("[[")(input)?; @@ -51,8 +51,8 @@ pub fn regular_link_without_description<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn regular_link_with_description<'r, 's>( - context: Context<'r, 's>, +pub fn regular_link_with_description<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, RegularLink<'s>> { let (remaining, _opening_bracket) = tag("[[")(input)?; @@ -72,8 +72,8 @@ pub fn regular_link_with_description<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn pathreg<'r, 's>( - _context: Context<'r, 's>, +pub fn pathreg<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, path) = escaped( @@ -88,15 +88,15 @@ pub fn pathreg<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn description<'r, 's>( - context: Context<'r, 's>, +pub fn description<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Vec>> { - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Beta, - exit_matcher: &description_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &description_end, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, (children, _exit_contents)) = verify( many_till( parser_with_context!(regular_link_description_object_set)(&parser_context), @@ -109,8 +109,8 @@ pub fn description<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn description_end<'r, 's>( - _context: Context<'r, 's>, +fn description_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { tag("]]")(input) diff --git a/src/parser/statistics_cookie.rs b/src/parser/statistics_cookie.rs index cae0de3..22ec3f5 100644 --- a/src/parser/statistics_cookie.rs +++ b/src/parser/statistics_cookie.rs @@ -5,14 +5,14 @@ use nom::sequence::tuple; use super::org_source::OrgSource; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::parser_with_context; +use crate::context::RefContext; use crate::error::Res; -use crate::parser::parser_with_context::parser_with_context; -use crate::parser::StatisticsCookie; +use crate::types::StatisticsCookie; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn statistics_cookie<'r, 's>( - context: Context<'r, 's>, +pub fn statistics_cookie<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, StatisticsCookie<'s>> { alt(( @@ -22,8 +22,8 @@ pub fn statistics_cookie<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn percent_statistics_cookie<'r, 's>( - context: Context<'r, 's>, +pub fn percent_statistics_cookie<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, StatisticsCookie<'s>> { let (remaining, source) = @@ -39,8 +39,8 @@ pub fn percent_statistics_cookie<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn fraction_statistics_cookie<'r, 's>( - context: Context<'r, 's>, +pub fn fraction_statistics_cookie<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, StatisticsCookie<'s>> { let (remaining, source) = recognize(tuple(( diff --git a/src/parser/subscript_and_superscript.rs b/src/parser/subscript_and_superscript.rs index 91d4274..9ad8906 100644 --- a/src/parser/subscript_and_superscript.rs +++ b/src/parser/subscript_and_superscript.rs @@ -10,27 +10,28 @@ use nom::combinator::recognize; use nom::combinator::verify; use nom::multi::many_till; +use super::object_parser::standard_set_object; use super::org_source::BracketDepth; use super::org_source::OrgSource; +use super::util::exit_matcher_parser; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; -use super::Object; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ContextMatcher; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::object_parser::standard_set_object; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; -use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; -use crate::parser::Subscript; -use crate::parser::Superscript; +use crate::types::Object; +use crate::types::Subscript; +use crate::types::Superscript; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn subscript<'r, 's>( - context: Context<'r, 's>, +pub fn subscript<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Subscript<'s>> { // We check for the underscore first before checking the pre-character as a minor optimization to avoid walking up the context tree to find the document root unnecessarily. @@ -49,8 +50,8 @@ pub fn subscript<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn superscript<'r, 's>( - context: Context<'r, 's>, +pub fn superscript<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Superscript<'s>> { // We check for the circumflex first before checking the pre-character as a minor optimization to avoid walking up the context tree to find the document root unnecessarily. @@ -69,7 +70,10 @@ pub fn superscript<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res, ()> { +fn pre<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, + input: OrgSource<'s>, +) -> Res, ()> { let preceding_character = input.get_preceding_character(); match preceding_character { Some(c) if !c.is_whitespace() => {} @@ -89,8 +93,8 @@ enum ScriptBody<'s> { } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn script_body<'r, 's>( - context: Context<'r, 's>, +fn script_body<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, ScriptBody<'s>> { alt(( @@ -107,16 +111,16 @@ fn script_body<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn script_asterisk<'r, 's>( - _context: Context<'r, 's>, +fn script_asterisk<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { tag("*")(input) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn script_alphanum<'r, 's>( - context: Context<'r, 's>, +fn script_alphanum<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, _sign) = opt(recognize(one_of("+-")))(input)?; @@ -129,8 +133,8 @@ fn script_alphanum<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn script_alphanum_character<'r, 's>( - _context: Context<'r, 's>, +fn script_alphanum_character<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(verify(anychar, |c| { @@ -139,8 +143,8 @@ fn script_alphanum_character<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn end_script_alphanum_character<'r, 's>( - context: Context<'r, 's>, +fn end_script_alphanum_character<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, final_char) = recognize(verify(anychar, |c| c.is_alphanumeric()))(input)?; @@ -151,17 +155,17 @@ fn end_script_alphanum_character<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn script_with_braces<'r, 's>( - context: Context<'r, 's>, +fn script_with_braces<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Vec>> { let (remaining, _) = tag("{")(input)?; let exit_with_depth = script_with_braces_end(remaining.get_brace_depth()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &exit_with_depth, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &exit_with_depth, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, (children, _exit_contents)) = many_till( parser_with_context!(standard_set_object)(&parser_context), @@ -172,17 +176,15 @@ fn script_with_braces<'r, 's>( Ok((remaining, children)) } -fn script_with_braces_end( - starting_brace_depth: BracketDepth, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - move |context: Context, input: OrgSource<'_>| { +fn script_with_braces_end(starting_brace_depth: BracketDepth) -> impl ContextMatcher { + move |context, input: OrgSource<'_>| { _script_with_braces_end(context, input, starting_brace_depth) } } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _script_with_braces_end<'r, 's>( - _context: Context<'r, 's>, +fn _script_with_braces_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, starting_brace_depth: BracketDepth, ) -> Res, OrgSource<'s>> { diff --git a/src/parser/table.rs b/src/parser/table.rs index eb45ea8..2dbe014 100644 --- a/src/parser/table.rs +++ b/src/parser/table.rs @@ -14,37 +14,41 @@ use nom::sequence::tuple; use super::object_parser::table_cell_set_object; use super::org_source::OrgSource; -use super::Context; +use super::util::exit_matcher_parser; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::greater_element::TableRow; -use crate::parser::lesser_element::TableCell; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; -use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::start_of_line; -use crate::parser::Table; +use crate::types::Table; +use crate::types::TableCell; +use crate::types::TableRow; /// Parse an org-mode-style table /// /// This is not the table.el style. #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn org_mode_table<'r, 's>( - context: Context<'r, 's>, +pub fn org_mode_table<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Table<'s>> { start_of_line(input)?; peek(tuple((space0, tag("|"))))(input)?; - let parser_context = context - .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) - .with_additional_node(ContextElement::Context("table")) - .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + let contexts = [ + ContextElement::ConsumeTrailingWhitespace(true), + ContextElement::Context("table"), + ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Alpha, exit_matcher: &table_end, - })); + }), + ]; + let parser_context = context.with_additional_node(&contexts[0]); + let parser_context = parser_context.with_additional_node(&contexts[1]); + let parser_context = parser_context.with_additional_node(&contexts[2]); let org_mode_table_row_matcher = parser_with_context!(org_mode_table_row)(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); @@ -65,8 +69,8 @@ pub fn org_mode_table<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn table_end<'r, 's>( - _context: Context<'r, 's>, +fn table_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { start_of_line(input)?; @@ -74,8 +78,8 @@ fn table_end<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn org_mode_table_row<'r, 's>( - context: Context<'r, 's>, +pub fn org_mode_table_row<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, TableRow<'s>> { alt(( @@ -85,8 +89,8 @@ pub fn org_mode_table_row<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn org_mode_table_row_rule<'r, 's>( - _context: Context<'r, 's>, +pub fn org_mode_table_row_rule<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, TableRow<'s>> { start_of_line(input)?; @@ -102,8 +106,8 @@ pub fn org_mode_table_row_rule<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn org_mode_table_row_regular<'r, 's>( - context: Context<'r, 's>, +pub fn org_mode_table_row_regular<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, TableRow<'s>> { start_of_line(input)?; @@ -122,15 +126,15 @@ pub fn org_mode_table_row_regular<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn org_mode_table_cell<'r, 's>( - context: Context<'r, 's>, +pub fn org_mode_table_cell<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, TableCell<'s>> { - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Beta, - exit_matcher: &org_mode_table_cell_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &org_mode_table_cell_end, + }); + let parser_context = context.with_additional_node(&parser_context); let table_cell_set_object_matcher = parser_with_context!(table_cell_set_object)(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); @@ -155,8 +159,8 @@ pub fn org_mode_table_cell<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn org_mode_table_cell_end<'r, 's>( - _context: Context<'r, 's>, +fn org_mode_table_cell_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(tuple((space0, alt((tag("|"), peek(line_ending))))))(input) diff --git a/src/parser/target.rs b/src/parser/target.rs index fd6b040..b978966 100644 --- a/src/parser/target.rs +++ b/src/parser/target.rs @@ -7,22 +7,22 @@ use nom::combinator::verify; use nom::multi::many_till; use super::org_source::OrgSource; +use super::util::exit_matcher_parser; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; -use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; -use crate::parser::Target; +use crate::types::Target; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn target<'r, 's>( - context: Context<'r, 's>, +pub fn target<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Target<'s>> { let (remaining, _) = tag("<<")(input)?; @@ -30,11 +30,11 @@ pub fn target<'r, 's>( !c.is_whitespace() && !"<>\n".contains(*c) }))(remaining)?; - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Beta, - exit_matcher: &target_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &target_end, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, _body) = recognize(many_till( anychar, parser_with_context!(exit_matcher_parser)(&parser_context), @@ -62,8 +62,8 @@ pub fn target<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn target_end<'r, 's>( - _context: Context<'r, 's>, +fn target_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(one_of("<>\n"))(input) diff --git a/src/parser/text_markup.rs b/src/parser/text_markup.rs index 8ad438c..f339fdd 100644 --- a/src/parser/text_markup.rs +++ b/src/parser/text_markup.rs @@ -15,33 +15,34 @@ use nom::sequence::terminated; #[cfg(feature = "tracing")] use tracing::span; +use super::object_parser::standard_set_object; use super::org_source::OrgSource; use super::radio_link::RematchObject; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ContextMatcher; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::object_parser::standard_set_object; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; use crate::parser::radio_link::rematch_target; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::preceded_by_whitespace; -use crate::parser::Bold; -use crate::parser::Code; -use crate::parser::Italic; -use crate::parser::Object; -use crate::parser::StrikeThrough; -use crate::parser::Underline; -use crate::parser::Verbatim; +use crate::types::Bold; +use crate::types::Code; +use crate::types::Italic; +use crate::types::Object; +use crate::types::StrikeThrough; +use crate::types::Underline; +use crate::types::Verbatim; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn text_markup<'r, 's>( - context: Context<'r, 's>, +pub fn text_markup<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Object<'s>> { alt(( @@ -58,8 +59,8 @@ pub fn text_markup<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn bold<'r, 's>( - context: Context<'r, 's>, +pub fn bold<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Bold<'s>> { let text_markup_object_specialized = text_markup_object("*"); @@ -75,8 +76,8 @@ pub fn bold<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn italic<'r, 's>( - context: Context<'r, 's>, +pub fn italic<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Italic<'s>> { let text_markup_object_specialized = text_markup_object("/"); @@ -92,8 +93,8 @@ pub fn italic<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn underline<'r, 's>( - context: Context<'r, 's>, +pub fn underline<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Underline<'s>> { let text_markup_object_specialized = text_markup_object("_"); @@ -109,8 +110,8 @@ pub fn underline<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn strike_through<'r, 's>( - context: Context<'r, 's>, +pub fn strike_through<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, StrikeThrough<'s>> { let text_markup_object_specialized = text_markup_object("+"); @@ -126,8 +127,8 @@ pub fn strike_through<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn verbatim<'r, 's>( - context: Context<'r, 's>, +pub fn verbatim<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Verbatim<'s>> { let text_markup_string_specialized = text_markup_string("="); @@ -143,8 +144,8 @@ pub fn verbatim<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn code<'r, 's>( - context: Context<'r, 's>, +pub fn code<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Code<'s>> { let text_markup_string_specialized = text_markup_string("~"); @@ -159,30 +160,32 @@ pub fn code<'r, 's>( )) } -fn text_markup_object( - marker_symbol: &str, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, Vec>> { +fn text_markup_object<'c>( + marker_symbol: &'c str, +) -> impl for<'b, 'g, 'r, 's> Fn( + RefContext<'b, 'g, 'r, 's>, + OrgSource<'s>, +) -> Res, Vec>> + + 'c { let marker_symbol = marker_symbol.to_owned(); - move |context: Context, input: OrgSource<'_>| { - _text_markup_object(context, input, marker_symbol.as_str()) - } + move |context, input: OrgSource<'_>| _text_markup_object(context, input, marker_symbol.as_str()) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _text_markup_object<'r, 's, 'x>( - context: Context<'r, 's>, +fn _text_markup_object<'b, 'g, 'r, 's, 'c>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, - marker_symbol: &'x str, + marker_symbol: &'c str, ) -> Res, Vec>> { let (remaining, _) = pre(context, input)?; let (remaining, open) = tag(marker_symbol)(remaining)?; let (remaining, _peek_not_whitespace) = peek(not(multispace1))(remaining)?; let text_markup_end_specialized = text_markup_end(open.into()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &text_markup_end_specialized, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &text_markup_end_specialized, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, (children, _exit_contents)) = verify( many_till( @@ -210,30 +213,31 @@ fn _text_markup_object<'r, 's, 'x>( Ok((remaining, children)) } -fn text_markup_string( - marker_symbol: &str, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - let marker_symbol = marker_symbol.to_owned(); - move |context: Context, input: OrgSource<'_>| { - _text_markup_string(context, input, marker_symbol.as_str()) - } +fn text_markup_string<'c>( + marker_symbol: &'c str, +) -> impl for<'b, 'g, 'r, 's> Fn( + RefContext<'b, 'g, 'r, 's>, + OrgSource<'s>, +) -> Res, OrgSource<'s>> + + 'c { + move |context, input: OrgSource<'_>| _text_markup_string(context, input, marker_symbol) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _text_markup_string<'r, 's, 'x>( - context: Context<'r, 's>, +fn _text_markup_string<'b, 'g, 'r, 's, 'c>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, - marker_symbol: &'x str, + marker_symbol: &'c str, ) -> Res, OrgSource<'s>> { let (remaining, _) = pre(context, input)?; let (remaining, open) = tag(marker_symbol)(remaining)?; let (remaining, _peek_not_whitespace) = peek(not(multispace1))(remaining)?; let text_markup_end_specialized = text_markup_end(open.into()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &text_markup_end_specialized, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &text_markup_end_specialized, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, contents) = recognize(verify( many_till( @@ -262,7 +266,10 @@ fn _text_markup_string<'r, 's, 'x>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res, ()> { +pub fn pre<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, + input: OrgSource<'s>, +) -> Res, ()> { let preceding_character = input.get_preceding_character(); match preceding_character { // If None, we are at the start of the file which is technically the beginning of a line. @@ -279,25 +286,23 @@ pub fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res, ()> { +pub fn post<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, + input: OrgSource<'s>, +) -> Res, ()> { let (remaining, _) = alt((recognize(one_of(" \r\n\t-.,;:!?')}[\"")), line_ending))(input)?; Ok((remaining, ())) } -fn text_markup_end( - marker_symbol: &str, -) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res, OrgSource<'s>> { - let marker_symbol = marker_symbol.to_owned(); - move |context: Context, input: OrgSource<'_>| { - _text_markup_end(context, input, marker_symbol.as_str()) - } +fn text_markup_end<'c>(marker_symbol: &'c str) -> impl ContextMatcher + 'c { + move |context, input: OrgSource<'_>| _text_markup_end(context, input, marker_symbol) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _text_markup_end<'r, 's, 'x>( - context: Context<'r, 's>, +fn _text_markup_end<'b, 'g, 'r, 's, 'c>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, - marker_symbol: &'x str, + marker_symbol: &'c str, ) -> Res, OrgSource<'s>> { not(preceded_by_whitespace)(input)?; let (remaining, _marker) = terminated( @@ -310,9 +315,9 @@ fn _text_markup_end<'r, 's, 'x>( impl<'x> RematchObject<'x> for Bold<'x> { #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] - fn rematch_object<'r, 's>( + fn rematch_object<'b, 'g, 'r, 's>( &'x self, - _context: Context<'r, 's>, + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Object<'s>> { let (remaining, children) = @@ -329,8 +334,8 @@ impl<'x> RematchObject<'x> for Bold<'x> { } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn _rematch_text_markup_object<'r, 's, 'x>( - context: Context<'r, 's>, +fn _rematch_text_markup_object<'b, 'g, 'r, 's, 'x>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, marker_symbol: &'static str, original_match_children: &'x Vec>, @@ -339,11 +344,11 @@ fn _rematch_text_markup_object<'r, 's, 'x>( let (remaining, open) = tag(marker_symbol)(remaining)?; let (remaining, _peek_not_whitespace) = peek(not(multispace1))(remaining)?; let text_markup_end_specialized = text_markup_end(open.into()); - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &text_markup_end_specialized, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &text_markup_end_specialized, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, children) = // TODO: This doesn't really check the exit matcher between each object. I think it may be possible to construct an org document that parses incorrectly with the current code. diff --git a/src/parser/timestamp.rs b/src/parser/timestamp.rs index 55a6be1..a1fff17 100644 --- a/src/parser/timestamp.rs +++ b/src/parser/timestamp.rs @@ -11,21 +11,20 @@ use nom::multi::many_till; use nom::sequence::tuple; use super::org_source::OrgSource; +use super::util::exit_matcher_parser; use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::ExitClass; +use crate::context::ExitMatcherNode; +use crate::context::RefContext; use crate::error::Res; -use crate::parser::exiting::ExitClass; -use crate::parser::parser_context::ContextElement; -use crate::parser::parser_context::ContextTree; -use crate::parser::parser_context::ExitMatcherNode; -use crate::parser::parser_with_context::parser_with_context; -use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; -use crate::parser::Timestamp; +use crate::types::Timestamp; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn timestamp<'r, 's>( - context: Context<'r, 's>, +pub fn timestamp<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Timestamp<'s>> { // TODO: This would be more efficient if we didn't throw away the parse result of the first half of an active/inactive date range timestamp if the parse fails (as in, the first thing active_date_range_timestamp parses is a active_timestamp but then we throw that away if it doesn't turn out to be a full active_date_range_timestamp despite the active_timestamp parse being completely valid). I am going with the simplest/cleanest approach for the first implementation. @@ -42,8 +41,8 @@ pub fn timestamp<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn diary_timestamp<'r, 's>( - context: Context<'r, 's>, +fn diary_timestamp<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Timestamp<'s>> { let (remaining, _) = tag("<%%(")(input)?; @@ -62,15 +61,15 @@ fn diary_timestamp<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn sexp<'r, 's>( - context: Context<'r, 's>, +fn sexp<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &sexp_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &sexp_end, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, body) = recognize(verify( many_till( @@ -84,25 +83,25 @@ fn sexp<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn sexp_end<'r, 's>( - _context: Context<'r, 's>, +fn sexp_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { alt((tag(")>"), recognize(one_of(">\n"))))(input) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn active_timestamp<'r, 's>( - context: Context<'r, 's>, +fn active_timestamp<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Timestamp<'s>> { let (remaining, _) = tag("<")(input)?; let (remaining, _date) = date(context, remaining)?; - let time_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &active_time_rest_end, - })); + let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &active_time_rest_end, + }); + let time_context = context.with_additional_node(&time_context); let (remaining, _time) = opt(tuple((space1, parser_with_context!(time)(&time_context))))(remaining)?; let (remaining, _repeater) = @@ -126,17 +125,17 @@ fn active_timestamp<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn inactive_timestamp<'r, 's>( - context: Context<'r, 's>, +fn inactive_timestamp<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Timestamp<'s>> { let (remaining, _) = tag("[")(input)?; let (remaining, _date) = date(context, remaining)?; - let time_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &inactive_time_rest_end, - })); + let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &inactive_time_rest_end, + }); + let time_context = context.with_additional_node(&time_context); let (remaining, _time) = opt(tuple((space1, parser_with_context!(time)(&time_context))))(remaining)?; let (remaining, _repeater) = @@ -160,8 +159,8 @@ fn inactive_timestamp<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn active_date_range_timestamp<'r, 's>( - context: Context<'r, 's>, +fn active_date_range_timestamp<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Timestamp<'s>> { let (remaining, _first_timestamp) = active_timestamp(context, input)?; @@ -182,22 +181,22 @@ fn active_date_range_timestamp<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn active_time_range_timestamp<'r, 's>( - context: Context<'r, 's>, +fn active_time_range_timestamp<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Timestamp<'s>> { let (remaining, _) = tag("<")(input)?; let (remaining, _date) = date(context, remaining)?; - let time_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &active_time_rest_end, - })); - let first_time_context = - time_context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &time_range_rest_end, - })); + let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &active_time_rest_end, + }); + let time_context = context.with_additional_node(&time_context); + let first_time_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &time_range_rest_end, + }); + let first_time_context = time_context.with_additional_node(&first_time_context); let (remaining, _first_time) = tuple((space1, parser_with_context!(time)(&first_time_context)))(remaining)?; let (remaining, _) = tag("-")(remaining)?; @@ -223,8 +222,8 @@ fn active_time_range_timestamp<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn inactive_date_range_timestamp<'r, 's>( - context: Context<'r, 's>, +fn inactive_date_range_timestamp<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Timestamp<'s>> { let (remaining, _first_timestamp) = inactive_timestamp(context, input)?; @@ -245,22 +244,22 @@ fn inactive_date_range_timestamp<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn inactive_time_range_timestamp<'r, 's>( - context: Context<'r, 's>, +fn inactive_time_range_timestamp<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Timestamp<'s>> { let (remaining, _) = tag("[")(input)?; let (remaining, _date) = date(context, remaining)?; - let time_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &inactive_time_rest_end, - })); - let first_time_context = - time_context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &time_range_rest_end, - })); + let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &inactive_time_rest_end, + }); + let time_context = context.with_additional_node(&time_context); + let first_time_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &time_range_rest_end, + }); + let first_time_context = time_context.with_additional_node(&first_time_context); let (remaining, _first_time) = tuple((space1, parser_with_context!(time)(&first_time_context)))(remaining)?; let (remaining, _) = tag("-")(remaining)?; @@ -286,8 +285,8 @@ fn inactive_time_range_timestamp<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn date<'r, 's>( - context: Context<'r, 's>, +fn date<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, _year) = verify(digit1, |year: &OrgSource<'_>| year.len() == 4)(input)?; @@ -304,15 +303,15 @@ fn date<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn dayname<'r, 's>( - context: Context<'r, 's>, +fn dayname<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { - let parser_context = - context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &dayname_end, - })); + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Gamma, + exit_matcher: &dayname_end, + }); + let parser_context = context.with_additional_node(&parser_context); let (remaining, body) = recognize(verify( many_till( @@ -326,8 +325,8 @@ fn dayname<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn dayname_end<'r, 's>( - _context: Context<'r, 's>, +fn dayname_end<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(verify(anychar, |c| { @@ -336,8 +335,8 @@ fn dayname_end<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn time<'r, 's>( - context: Context<'r, 's>, +fn time<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, _hour) = verify(digit1, |hour: &OrgSource<'_>| { @@ -352,8 +351,8 @@ fn time<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn time_rest<'r, 's>( - context: Context<'r, 's>, +fn time_rest<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { let (remaining, body) = recognize(verify( @@ -365,8 +364,8 @@ fn time_rest<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn active_time_rest_end<'r, 's>( - context: Context<'r, 's>, +fn active_time_rest_end<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { alt(( @@ -380,8 +379,8 @@ fn active_time_rest_end<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn inactive_time_rest_end<'r, 's>( - context: Context<'r, 's>, +fn inactive_time_rest_end<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { alt(( @@ -395,21 +394,20 @@ fn inactive_time_rest_end<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn time_range_rest_end<'r, 's>( - context: Context<'r, 's>, +fn time_range_rest_end<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { // We pop off the most recent context element to get a context tree with just the active/inactive_time_rest_end exit matcher (removing this function from the exit matcher chain) because the 2nd time in the range does not end when a "-TIME" pattern is found. - let parent_node = context.iter().next().expect("Two context elements are added to the tree when adding this exit matcher, so it should be impossible for this to return None."); - let parent_tree = ContextTree::branch_from(parent_node); + let parent_node = context.get_parent().expect("Two context elements are added to the tree when adding this exit matcher, so it should be impossible for this to return None."); let exit_contents = - recognize(tuple((tag("-"), parser_with_context!(time)(&parent_tree))))(input); + recognize(tuple((tag("-"), parser_with_context!(time)(&parent_node))))(input); exit_contents } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn repeater<'r, 's>( - _context: Context<'r, 's>, +fn repeater<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { // + for cumulative type @@ -424,8 +422,8 @@ fn repeater<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -fn warning_delay<'r, 's>( - _context: Context<'r, 's>, +fn warning_delay<'b, 'g, 'r, 's>( + _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { // - for all type diff --git a/src/parser/token.rs b/src/parser/token.rs index cc62562..ea9ea8f 100644 --- a/src/parser/token.rs +++ b/src/parser/token.rs @@ -1,14 +1,14 @@ use std::collections::VecDeque; -use super::Document; -use super::Element; -use super::Heading; -use super::Object; -use super::PlainListItem; -use super::Section; -use super::TableCell; -use super::TableRow; -use crate::parser::DocumentElement; +use crate::types::Document; +use crate::types::DocumentElement; +use crate::types::Element; +use crate::types::Heading; +use crate::types::Object; +use crate::types::PlainListItem; +use crate::types::Section; +use crate::types::TableCell; +use crate::types::TableRow; pub enum Token<'r, 's> { Document(&'r Document<'s>), diff --git a/src/parser/util.rs b/src/parser/util.rs index e59eadd..ba84ae1 100644 --- a/src/parser/util.rs +++ b/src/parser/util.rs @@ -14,21 +14,24 @@ use nom::multi::many_till; use nom::sequence::tuple; use super::org_source::OrgSource; -use super::parser_context::ContextElement; -use super::Context; +use crate::context::parser_with_context; +use crate::context::ContextElement; +use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; -use crate::parser::parser_with_context::parser_with_context; pub const WORD_CONSTITUENT_CHARACTERS: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; /// Check if we are below a section of the given section type regardless of depth #[allow(dead_code)] -pub fn in_section<'r, 's, 'x>(context: Context<'r, 's>, section_name: &'x str) -> bool { +pub fn in_section<'b, 'g, 'r, 's, 'x>( + context: RefContext<'b, 'g, 'r, 's>, + section_name: &'x str, +) -> bool { for thing in context.iter() { - match thing.get_data() { + match thing { ContextElement::Context(name) if *name == section_name => return true, _ => {} } @@ -37,9 +40,12 @@ pub fn in_section<'r, 's, 'x>(context: Context<'r, 's>, section_name: &'x str) - } /// Checks if we are currently an immediate child of the given section type -pub fn immediate_in_section<'r, 's, 'x>(context: Context<'r, 's>, section_name: &'x str) -> bool { +pub fn immediate_in_section<'b, 'g, 'r, 's, 'x>( + context: RefContext<'b, 'g, 'r, 's>, + section_name: &'x str, +) -> bool { for thing in context.iter() { - match thing.get_data() { + match thing { ContextElement::Context(name) if *name == section_name => return true, ContextElement::Context(name) if *name != section_name => return false, _ => {} @@ -69,8 +75,8 @@ pub fn element_trailing_whitespace<'s>(input: OrgSource<'s>) -> Res( - context: Context<'r, 's>, +pub fn maybe_consume_object_trailing_whitespace_if_not_exiting<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Option>> { if exit_matcher_parser(context, input).is_err() { @@ -81,8 +87,8 @@ pub fn maybe_consume_object_trailing_whitespace_if_not_exiting<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn maybe_consume_trailing_whitespace_if_not_exiting<'r, 's>( - context: Context<'r, 's>, +pub fn maybe_consume_trailing_whitespace_if_not_exiting<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Option>> { if context.should_consume_trailing_whitespace() && exit_matcher_parser(context, input).is_err() @@ -94,8 +100,8 @@ pub fn maybe_consume_trailing_whitespace_if_not_exiting<'r, 's>( } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn maybe_consume_trailing_whitespace<'r, 's>( - context: Context<'r, 's>, +pub fn maybe_consume_trailing_whitespace<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Option>> { if context.should_consume_trailing_whitespace() { @@ -143,16 +149,16 @@ pub fn non_whitespace_character(input: OrgSource<'_>) -> Res, char /// Check that we are at the start of a line #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn exit_matcher_parser<'r, 's>( - context: Context<'r, 's>, +pub fn exit_matcher_parser<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { peek(|i| context.check_exit_matcher(i))(input) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] -pub fn text_until_exit<'r, 's>( - context: Context<'r, 's>, +pub fn text_until_exit<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { recognize(verify( diff --git a/src/types/document.rs b/src/types/document.rs new file mode 100644 index 0000000..957d7b9 --- /dev/null +++ b/src/types/document.rs @@ -0,0 +1,60 @@ +use super::Element; +use super::Object; +use super::Source; + +#[derive(Debug)] +pub struct Document<'s> { + pub source: &'s str, + pub zeroth_section: Option>, + pub children: Vec>, +} + +#[derive(Debug)] +pub struct Heading<'s> { + pub source: &'s str, + pub stars: usize, + pub todo_keyword: Option<&'s str>, + // TODO: add todo-type enum + pub title: Vec>, + pub tags: Vec<&'s str>, + pub children: Vec>, +} + +#[derive(Debug)] +pub struct Section<'s> { + pub source: &'s str, + pub children: Vec>, +} + +#[derive(Debug)] +pub enum DocumentElement<'s> { + Heading(Heading<'s>), + Section(Section<'s>), +} + +impl<'s> Source<'s> for Document<'s> { + fn get_source(&'s self) -> &'s str { + self.source + } +} + +impl<'s> Source<'s> for DocumentElement<'s> { + fn get_source(&'s self) -> &'s str { + match self { + DocumentElement::Heading(obj) => obj.source, + DocumentElement::Section(obj) => obj.source, + } + } +} + +impl<'s> Source<'s> for Section<'s> { + fn get_source(&'s self) -> &'s str { + self.source + } +} + +impl<'s> Source<'s> for Heading<'s> { + fn get_source(&'s self) -> &'s str { + self.source + } +} diff --git a/src/parser/element.rs b/src/types/element.rs similarity index 98% rename from src/parser/element.rs rename to src/types/element.rs index 9795ec6..c279657 100644 --- a/src/parser/element.rs +++ b/src/types/element.rs @@ -18,9 +18,9 @@ use super::lesser_element::Paragraph; use super::lesser_element::Planning; use super::lesser_element::SrcBlock; use super::lesser_element::VerseBlock; -use super::source::SetSource; -use super::source::Source; use super::Drawer; +use super::SetSource; +use super::Source; #[derive(Debug)] pub enum Element<'s> { diff --git a/src/parser/greater_element.rs b/src/types/greater_element.rs similarity index 98% rename from src/parser/greater_element.rs rename to src/types/greater_element.rs index 5a46284..2aed91e 100644 --- a/src/parser/greater_element.rs +++ b/src/types/greater_element.rs @@ -1,7 +1,7 @@ use super::element::Element; use super::lesser_element::TableCell; -use super::source::Source; use super::Object; +use super::Source; #[derive(Debug)] pub struct PlainList<'s> { diff --git a/src/parser/lesser_element.rs b/src/types/lesser_element.rs similarity index 99% rename from src/parser/lesser_element.rs rename to src/types/lesser_element.rs index cac3adf..33f6529 100644 --- a/src/parser/lesser_element.rs +++ b/src/types/lesser_element.rs @@ -1,6 +1,6 @@ use super::object::Object; -use super::source::Source; use super::PlainText; +use super::Source; #[derive(Debug)] pub struct Paragraph<'s> { diff --git a/src/types/mod.rs b/src/types/mod.rs new file mode 100644 index 0000000..4ab8c17 --- /dev/null +++ b/src/types/mod.rs @@ -0,0 +1,66 @@ +mod document; +mod element; +mod greater_element; +mod lesser_element; +mod object; +mod source; +pub use document::Document; +pub use document::DocumentElement; +pub use document::Heading; +pub use document::Section; +pub use element::Element; +pub use greater_element::Drawer; +pub use greater_element::DynamicBlock; +pub use greater_element::FootnoteDefinition; +pub use greater_element::GreaterBlock; +pub use greater_element::NodeProperty; +pub use greater_element::PlainList; +pub use greater_element::PlainListItem; +pub use greater_element::PropertyDrawer; +pub use greater_element::Table; +pub use greater_element::TableRow; +pub use lesser_element::Clock; +pub use lesser_element::Comment; +pub use lesser_element::CommentBlock; +pub use lesser_element::DiarySexp; +pub use lesser_element::ExampleBlock; +pub use lesser_element::ExportBlock; +pub use lesser_element::FixedWidthArea; +pub use lesser_element::HorizontalRule; +pub use lesser_element::Keyword; +pub use lesser_element::LatexEnvironment; +pub use lesser_element::Paragraph; +pub use lesser_element::Planning; +pub use lesser_element::SrcBlock; +pub use lesser_element::TableCell; +pub use lesser_element::VerseBlock; +pub use object::AngleLink; +pub use object::Bold; +pub use object::Citation; +pub use object::CitationReference; +pub use object::Code; +pub use object::Entity; +pub use object::ExportSnippet; +pub use object::FootnoteReference; +pub use object::InlineBabelCall; +pub use object::InlineSourceBlock; +pub use object::Italic; +pub use object::LatexFragment; +pub use object::LineBreak; +pub use object::Object; +pub use object::OrgMacro; +pub use object::PlainLink; +pub use object::PlainText; +pub use object::RadioLink; +pub use object::RadioTarget; +pub use object::RegularLink; +pub use object::StatisticsCookie; +pub use object::StrikeThrough; +pub use object::Subscript; +pub use object::Superscript; +pub use object::Target; +pub use object::Timestamp; +pub use object::Underline; +pub use object::Verbatim; +pub use source::SetSource; +pub use source::Source; diff --git a/src/parser/object.rs b/src/types/object.rs similarity index 99% rename from src/parser/object.rs rename to src/types/object.rs index 9064a6f..7e5da11 100644 --- a/src/parser/object.rs +++ b/src/types/object.rs @@ -1,4 +1,4 @@ -use super::source::Source; +use super::Source; #[derive(Debug, PartialEq)] pub enum Object<'s> { diff --git a/src/parser/source.rs b/src/types/source.rs similarity index 100% rename from src/parser/source.rs rename to src/types/source.rs diff --git a/tests/test_template b/tests/test_template index 2dd2ed4..776ebbe 100644 --- a/tests/test_template +++ b/tests/test_template @@ -6,7 +6,7 @@ fn {name}() {{ let org_sexp = emacs_parse_anonymous_org_document(org_contents.as_str()).expect("Use emacs to parse org file."); println!("{{}}", org_sexp); let (_remaining, parsed_sexp) = sexp_with_padding(org_sexp.as_str()).expect("Sexp Parse failure"); - let (remaining, rust_parsed) = document(org_contents.as_str()).expect("Org Parse failure"); + let rust_parsed = parse(org_contents.as_str()).expect("Org Parse failure"); println!("{{:#?}}", rust_parsed); let diff_result = compare_document(&parsed_sexp, &rust_parsed).expect("Compare parsed documents."); @@ -14,5 +14,4 @@ fn {name}() {{ .print(org_contents.as_str()) .expect("Print document parse tree diff."); assert!(!diff_result.is_bad()); - assert_eq!(remaining, ""); }}