From 35f058a3545a240bb09dce974daabff1c7b23586 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 13:48:17 -0400 Subject: [PATCH 01/18] Starting a new iteration implementation. This implementation will reduce the use of heap by elimininating Box<> from the individual iterators but it will still need heap for maintaining a vector of iterators from nodes. --- src/iter/ast_node.rs | 1 + src/iter/ast_node_iter.rs | 5 +++++ src/iter/mod.rs | 2 ++ src/lib.rs | 1 + 4 files changed, 9 insertions(+) create mode 100644 src/iter/ast_node.rs create mode 100644 src/iter/ast_node_iter.rs create mode 100644 src/iter/mod.rs diff --git a/src/iter/ast_node.rs b/src/iter/ast_node.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/iter/ast_node.rs @@ -0,0 +1 @@ + diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs new file mode 100644 index 0000000..136814a --- /dev/null +++ b/src/iter/ast_node_iter.rs @@ -0,0 +1,5 @@ +use crate::types::Object; + +pub struct BoldIter<'s> { + next: std::slice::Iter<'s, Object<'s>>, +} diff --git a/src/iter/mod.rs b/src/iter/mod.rs new file mode 100644 index 0000000..b59a57f --- /dev/null +++ b/src/iter/mod.rs @@ -0,0 +1,2 @@ +mod ast_node; +mod ast_node_iter; diff --git a/src/lib.rs b/src/lib.rs index bbcaf1f..c522cf6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ pub mod compare; mod context; mod error; +mod iter; pub mod parser; pub mod types; From 9111408d837b0a4f046ec7ef1dcea74a0e40772a Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 14:24:08 -0400 Subject: [PATCH 02/18] Introduce AstNode and AstNodeIter enums. --- src/iter/ast_node.rs | 109 ++++++++++++++++++++++++++++++++++++++ src/iter/ast_node_iter.rs | 58 ++++++++++++++++++++ 2 files changed, 167 insertions(+) diff --git a/src/iter/ast_node.rs b/src/iter/ast_node.rs index 8b13789..da38bc2 100644 --- a/src/iter/ast_node.rs +++ b/src/iter/ast_node.rs @@ -1 +1,110 @@ +use crate::types::AngleLink; +use crate::types::BabelCall; +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::Drawer; +use crate::types::DynamicBlock; +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::OrgMacro; +use crate::types::Paragraph; +use crate::types::PlainLink; +use crate::types::PlainList; +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::SrcBlock; +use crate::types::StatisticsCookie; +use crate::types::StrikeThrough; +use crate::types::Subscript; +use crate::types::Superscript; +use crate::types::Table; +use crate::types::Target; +use crate::types::Timestamp; +use crate::types::Underline; +use crate::types::Verbatim; +use crate::types::VerseBlock; +pub enum AstNode<'r, 's> { + // Document Nodes + Document(&'r Document<'s>), + Heading(&'r Heading<'s>), + Section(&'r Section<'s>), + // Elements + Paragraph(&'r Paragraph<'s>), + PlainList(&'r PlainList<'s>), + GreaterBlock(&'r GreaterBlock<'s>), + DynamicBlock(&'r DynamicBlock<'s>), + FootnoteDefinition(&'r FootnoteDefinition<'s>), + Comment(&'r Comment<'s>), + Drawer(&'r Drawer<'s>), + PropertyDrawer(&'r PropertyDrawer<'s>), + Table(&'r Table<'s>), + VerseBlock(&'r VerseBlock<'s>), + CommentBlock(&'r CommentBlock<'s>), + ExampleBlock(&'r ExampleBlock<'s>), + ExportBlock(&'r ExportBlock<'s>), + SrcBlock(&'r SrcBlock<'s>), + Clock(&'r Clock<'s>), + DiarySexp(&'r DiarySexp<'s>), + Planning(&'r Planning<'s>), + FixedWidthArea(&'r FixedWidthArea<'s>), + HorizontalRule(&'r HorizontalRule<'s>), + Keyword(&'r Keyword<'s>), + BabelCall(&'r BabelCall<'s>), + LatexEnvironment(&'r LatexEnvironment<'s>), + // Objects + Bold(&'r Bold<'s>), + Italic(&'r Italic<'s>), + Underline(&'r Underline<'s>), + StrikeThrough(&'r StrikeThrough<'s>), + Code(&'r Code<'s>), + Verbatim(&'r Verbatim<'s>), + PlainText(&'r PlainText<'s>), + RegularLink(&'r RegularLink<'s>), + RadioLink(&'r RadioLink<'s>), + RadioTarget(&'r RadioTarget<'s>), + PlainLink(&'r PlainLink<'s>), + AngleLink(&'r AngleLink<'s>), + OrgMacro(&'r OrgMacro<'s>), + Entity(&'r Entity<'s>), + LatexFragment(&'r LatexFragment<'s>), + ExportSnippet(&'r ExportSnippet<'s>), + FootnoteReference(&'r FootnoteReference<'s>), + Citation(&'r Citation<'s>), + CitationReference(&'r CitationReference<'s>), + InlineBabelCall(&'r InlineBabelCall<'s>), + InlineSourceBlock(&'r InlineSourceBlock<'s>), + LineBreak(&'r LineBreak<'s>), + Target(&'r Target<'s>), + StatisticsCookie(&'r StatisticsCookie<'s>), + Subscript(&'r Subscript<'s>), + Superscript(&'r Superscript<'s>), + Timestamp(&'r Timestamp<'s>), +} diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index 136814a..dcd79bc 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -1,5 +1,63 @@ use crate::types::Object; +pub enum AstNodeIter<'s> { + // Document Nodes + // Document(DocumentIter<'s>), + // Heading(HeadingIter<'s>), + // Section(SectionIter<'s>), + // Elements + // Paragraph(ParagraphIter<'s>), + // PlainList(PlainListIter<'s>), + // GreaterBlock(GreaterBlockIter<'s>), + // DynamicBlock(DynamicBlockIter<'s>), + // FootnoteDefinition(FootnoteDefinitionIter<'s>), + // Comment(CommentIter<'s>), + // Drawer(DrawerIter<'s>), + // PropertyDrawer(PropertyDrawerIter<'s>), + // Table(TableIter<'s>), + // VerseBlock(VerseBlockIter<'s>), + // CommentBlock(CommentBlockIter<'s>), + // ExampleBlock(ExampleBlockIter<'s>), + // ExportBlock(ExportBlockIter<'s>), + // SrcBlock(SrcBlockIter<'s>), + // Clock(ClockIter<'s>), + // DiarySexp(DiarySexpIter<'s>), + // Planning(PlanningIter<'s>), + // FixedWidthArea(FixedWidthAreaIter<'s>), + // HorizontalRule(HorizontalRuleIter<'s>), + // Keyword(KeywordIter<'s>), + // BabelCall(BabelCallIter<'s>), + // LatexEnvironment(LatexEnvironmentIter<'s>), + // Objects + Bold(BoldIter<'s>), + // Italic(ItalicIter<'s>), + // Underline(UnderlineIter<'s>), + // StrikeThrough(StrikeThroughIter<'s>), + // Code(CodeIter<'s>), + // Verbatim(VerbatimIter<'s>), + // PlainText(PlainTextIter<'s>), + // RegularLink(RegularLinkIter<'s>), + // RadioLink(RadioLinkIter<'s>), + // RadioTarget(RadioTargetIter<'s>), + // PlainLink(PlainLinkIter<'s>), + // AngleLink(AngleLinkIter<'s>), + // OrgMacro(OrgMacroIter<'s>), + // Entity(EntityIter<'s>), + // LatexFragment(LatexFragmentIter<'s>), + // ExportSnippet(ExportSnippetIter<'s>), + // FootnoteReference(FootnoteReferenceIter<'s>), + // Citation(CitationIter<'s>), + // CitationReference(CitationReferenceIter<'s>), + // InlineBabelCall(InlineBabelCallIter<'s>), + // InlineSourceBlock(InlineSourceBlockIter<'s>), + // LineBreak(LineBreakIter<'s>), + // Target(TargetIter<'s>), + // StatisticsCookie(StatisticsCookieIter<'s>), + // Subscript(SubscriptIter<'s>), + // Superscript(SuperscriptIter<'s>), + // Timestamp(TimestampIter<'s>), +} + pub struct BoldIter<'s> { next: std::slice::Iter<'s, Object<'s>>, } From df5d699a39c5649592d8518e1ff2d460eb33b078 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 15:07:26 -0400 Subject: [PATCH 03/18] Implement Into for AstNode. --- src/iter/ast_node.rs | 326 ++++++++++++++++++++++++++++++++++++++ src/iter/ast_node_iter.rs | 120 +++++++------- 2 files changed, 391 insertions(+), 55 deletions(-) diff --git a/src/iter/ast_node.rs b/src/iter/ast_node.rs index da38bc2..0704ab3 100644 --- a/src/iter/ast_node.rs +++ b/src/iter/ast_node.rs @@ -11,6 +11,7 @@ use crate::types::DiarySexp; use crate::types::Document; use crate::types::Drawer; use crate::types::DynamicBlock; +use crate::types::Element; use crate::types::Entity; use crate::types::ExampleBlock; use crate::types::ExportBlock; @@ -28,6 +29,7 @@ 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; @@ -108,3 +110,327 @@ pub enum AstNode<'r, 's> { Superscript(&'r Superscript<'s>), Timestamp(&'r Timestamp<'s>), } + +impl<'r, 's> From<&'r Element<'s>> for AstNode<'r, 's> { + fn from(value: &'r Element<'s>) -> Self { + match value { + Element::Paragraph(inner) => inner.into(), + Element::PlainList(inner) => inner.into(), + Element::GreaterBlock(inner) => inner.into(), + Element::DynamicBlock(inner) => inner.into(), + Element::FootnoteDefinition(inner) => inner.into(), + Element::Comment(inner) => inner.into(), + Element::Drawer(inner) => inner.into(), + Element::PropertyDrawer(inner) => inner.into(), + Element::Table(inner) => inner.into(), + Element::VerseBlock(inner) => inner.into(), + Element::CommentBlock(inner) => inner.into(), + Element::ExampleBlock(inner) => inner.into(), + Element::ExportBlock(inner) => inner.into(), + Element::SrcBlock(inner) => inner.into(), + Element::Clock(inner) => inner.into(), + Element::DiarySexp(inner) => inner.into(), + Element::Planning(inner) => inner.into(), + Element::FixedWidthArea(inner) => inner.into(), + Element::HorizontalRule(inner) => inner.into(), + Element::Keyword(inner) => inner.into(), + Element::BabelCall(inner) => inner.into(), + Element::LatexEnvironment(inner) => inner.into(), + } + } +} + +impl<'r, 's> From<&'r Object<'s>> for AstNode<'r, 's> { + fn from(value: &'r Object<'s>) -> Self { + match value { + Object::Bold(inner) => inner.into(), + Object::Italic(inner) => inner.into(), + Object::Underline(inner) => inner.into(), + Object::StrikeThrough(inner) => inner.into(), + Object::Code(inner) => inner.into(), + Object::Verbatim(inner) => inner.into(), + Object::PlainText(inner) => inner.into(), + Object::RegularLink(inner) => inner.into(), + Object::RadioLink(inner) => inner.into(), + Object::RadioTarget(inner) => inner.into(), + Object::PlainLink(inner) => inner.into(), + Object::AngleLink(inner) => inner.into(), + Object::OrgMacro(inner) => inner.into(), + Object::Entity(inner) => inner.into(), + Object::LatexFragment(inner) => inner.into(), + Object::ExportSnippet(inner) => inner.into(), + Object::FootnoteReference(inner) => inner.into(), + Object::Citation(inner) => inner.into(), + Object::CitationReference(inner) => inner.into(), + Object::InlineBabelCall(inner) => inner.into(), + Object::InlineSourceBlock(inner) => inner.into(), + Object::LineBreak(inner) => inner.into(), + Object::Target(inner) => inner.into(), + Object::StatisticsCookie(inner) => inner.into(), + Object::Subscript(inner) => inner.into(), + Object::Superscript(inner) => inner.into(), + Object::Timestamp(inner) => inner.into(), + } + } +} + +impl<'r, 's> From<&'r Document<'s>> for AstNode<'r, 's> { + fn from(value: &'r Document<'s>) -> Self { + AstNode::Document(value) + } +} +impl<'r, 's> From<&'r Heading<'s>> for AstNode<'r, 's> { + fn from(value: &'r Heading<'s>) -> Self { + AstNode::Heading(value) + } +} +impl<'r, 's> From<&'r Section<'s>> for AstNode<'r, 's> { + fn from(value: &'r Section<'s>) -> Self { + AstNode::Section(value) + } +} +impl<'r, 's> From<&'r Paragraph<'s>> for AstNode<'r, 's> { + fn from(value: &'r Paragraph<'s>) -> Self { + AstNode::Paragraph(value) + } +} +impl<'r, 's> From<&'r PlainList<'s>> for AstNode<'r, 's> { + fn from(value: &'r PlainList<'s>) -> Self { + AstNode::PlainList(value) + } +} +impl<'r, 's> From<&'r GreaterBlock<'s>> for AstNode<'r, 's> { + fn from(value: &'r GreaterBlock<'s>) -> Self { + AstNode::GreaterBlock(value) + } +} +impl<'r, 's> From<&'r DynamicBlock<'s>> for AstNode<'r, 's> { + fn from(value: &'r DynamicBlock<'s>) -> Self { + AstNode::DynamicBlock(value) + } +} +impl<'r, 's> From<&'r FootnoteDefinition<'s>> for AstNode<'r, 's> { + fn from(value: &'r FootnoteDefinition<'s>) -> Self { + AstNode::FootnoteDefinition(value) + } +} +impl<'r, 's> From<&'r Comment<'s>> for AstNode<'r, 's> { + fn from(value: &'r Comment<'s>) -> Self { + AstNode::Comment(value) + } +} +impl<'r, 's> From<&'r Drawer<'s>> for AstNode<'r, 's> { + fn from(value: &'r Drawer<'s>) -> Self { + AstNode::Drawer(value) + } +} +impl<'r, 's> From<&'r PropertyDrawer<'s>> for AstNode<'r, 's> { + fn from(value: &'r PropertyDrawer<'s>) -> Self { + AstNode::PropertyDrawer(value) + } +} +impl<'r, 's> From<&'r Table<'s>> for AstNode<'r, 's> { + fn from(value: &'r Table<'s>) -> Self { + AstNode::Table(value) + } +} +impl<'r, 's> From<&'r VerseBlock<'s>> for AstNode<'r, 's> { + fn from(value: &'r VerseBlock<'s>) -> Self { + AstNode::VerseBlock(value) + } +} +impl<'r, 's> From<&'r CommentBlock<'s>> for AstNode<'r, 's> { + fn from(value: &'r CommentBlock<'s>) -> Self { + AstNode::CommentBlock(value) + } +} +impl<'r, 's> From<&'r ExampleBlock<'s>> for AstNode<'r, 's> { + fn from(value: &'r ExampleBlock<'s>) -> Self { + AstNode::ExampleBlock(value) + } +} +impl<'r, 's> From<&'r ExportBlock<'s>> for AstNode<'r, 's> { + fn from(value: &'r ExportBlock<'s>) -> Self { + AstNode::ExportBlock(value) + } +} +impl<'r, 's> From<&'r SrcBlock<'s>> for AstNode<'r, 's> { + fn from(value: &'r SrcBlock<'s>) -> Self { + AstNode::SrcBlock(value) + } +} +impl<'r, 's> From<&'r Clock<'s>> for AstNode<'r, 's> { + fn from(value: &'r Clock<'s>) -> Self { + AstNode::Clock(value) + } +} +impl<'r, 's> From<&'r DiarySexp<'s>> for AstNode<'r, 's> { + fn from(value: &'r DiarySexp<'s>) -> Self { + AstNode::DiarySexp(value) + } +} +impl<'r, 's> From<&'r Planning<'s>> for AstNode<'r, 's> { + fn from(value: &'r Planning<'s>) -> Self { + AstNode::Planning(value) + } +} +impl<'r, 's> From<&'r FixedWidthArea<'s>> for AstNode<'r, 's> { + fn from(value: &'r FixedWidthArea<'s>) -> Self { + AstNode::FixedWidthArea(value) + } +} +impl<'r, 's> From<&'r HorizontalRule<'s>> for AstNode<'r, 's> { + fn from(value: &'r HorizontalRule<'s>) -> Self { + AstNode::HorizontalRule(value) + } +} +impl<'r, 's> From<&'r Keyword<'s>> for AstNode<'r, 's> { + fn from(value: &'r Keyword<'s>) -> Self { + AstNode::Keyword(value) + } +} +impl<'r, 's> From<&'r BabelCall<'s>> for AstNode<'r, 's> { + fn from(value: &'r BabelCall<'s>) -> Self { + AstNode::BabelCall(value) + } +} +impl<'r, 's> From<&'r LatexEnvironment<'s>> for AstNode<'r, 's> { + fn from(value: &'r LatexEnvironment<'s>) -> Self { + AstNode::LatexEnvironment(value) + } +} +impl<'r, 's> From<&'r Bold<'s>> for AstNode<'r, 's> { + fn from(value: &'r Bold<'s>) -> Self { + AstNode::Bold(value) + } +} +impl<'r, 's> From<&'r Italic<'s>> for AstNode<'r, 's> { + fn from(value: &'r Italic<'s>) -> Self { + AstNode::Italic(value) + } +} +impl<'r, 's> From<&'r Underline<'s>> for AstNode<'r, 's> { + fn from(value: &'r Underline<'s>) -> Self { + AstNode::Underline(value) + } +} +impl<'r, 's> From<&'r StrikeThrough<'s>> for AstNode<'r, 's> { + fn from(value: &'r StrikeThrough<'s>) -> Self { + AstNode::StrikeThrough(value) + } +} +impl<'r, 's> From<&'r Code<'s>> for AstNode<'r, 's> { + fn from(value: &'r Code<'s>) -> Self { + AstNode::Code(value) + } +} +impl<'r, 's> From<&'r Verbatim<'s>> for AstNode<'r, 's> { + fn from(value: &'r Verbatim<'s>) -> Self { + AstNode::Verbatim(value) + } +} +impl<'r, 's> From<&'r PlainText<'s>> for AstNode<'r, 's> { + fn from(value: &'r PlainText<'s>) -> Self { + AstNode::PlainText(value) + } +} +impl<'r, 's> From<&'r RegularLink<'s>> for AstNode<'r, 's> { + fn from(value: &'r RegularLink<'s>) -> Self { + AstNode::RegularLink(value) + } +} +impl<'r, 's> From<&'r RadioLink<'s>> for AstNode<'r, 's> { + fn from(value: &'r RadioLink<'s>) -> Self { + AstNode::RadioLink(value) + } +} +impl<'r, 's> From<&'r RadioTarget<'s>> for AstNode<'r, 's> { + fn from(value: &'r RadioTarget<'s>) -> Self { + AstNode::RadioTarget(value) + } +} +impl<'r, 's> From<&'r PlainLink<'s>> for AstNode<'r, 's> { + fn from(value: &'r PlainLink<'s>) -> Self { + AstNode::PlainLink(value) + } +} +impl<'r, 's> From<&'r AngleLink<'s>> for AstNode<'r, 's> { + fn from(value: &'r AngleLink<'s>) -> Self { + AstNode::AngleLink(value) + } +} +impl<'r, 's> From<&'r OrgMacro<'s>> for AstNode<'r, 's> { + fn from(value: &'r OrgMacro<'s>) -> Self { + AstNode::OrgMacro(value) + } +} +impl<'r, 's> From<&'r Entity<'s>> for AstNode<'r, 's> { + fn from(value: &'r Entity<'s>) -> Self { + AstNode::Entity(value) + } +} +impl<'r, 's> From<&'r LatexFragment<'s>> for AstNode<'r, 's> { + fn from(value: &'r LatexFragment<'s>) -> Self { + AstNode::LatexFragment(value) + } +} +impl<'r, 's> From<&'r ExportSnippet<'s>> for AstNode<'r, 's> { + fn from(value: &'r ExportSnippet<'s>) -> Self { + AstNode::ExportSnippet(value) + } +} +impl<'r, 's> From<&'r FootnoteReference<'s>> for AstNode<'r, 's> { + fn from(value: &'r FootnoteReference<'s>) -> Self { + AstNode::FootnoteReference(value) + } +} +impl<'r, 's> From<&'r Citation<'s>> for AstNode<'r, 's> { + fn from(value: &'r Citation<'s>) -> Self { + AstNode::Citation(value) + } +} +impl<'r, 's> From<&'r CitationReference<'s>> for AstNode<'r, 's> { + fn from(value: &'r CitationReference<'s>) -> Self { + AstNode::CitationReference(value) + } +} +impl<'r, 's> From<&'r InlineBabelCall<'s>> for AstNode<'r, 's> { + fn from(value: &'r InlineBabelCall<'s>) -> Self { + AstNode::InlineBabelCall(value) + } +} +impl<'r, 's> From<&'r InlineSourceBlock<'s>> for AstNode<'r, 's> { + fn from(value: &'r InlineSourceBlock<'s>) -> Self { + AstNode::InlineSourceBlock(value) + } +} +impl<'r, 's> From<&'r LineBreak<'s>> for AstNode<'r, 's> { + fn from(value: &'r LineBreak<'s>) -> Self { + AstNode::LineBreak(value) + } +} +impl<'r, 's> From<&'r Target<'s>> for AstNode<'r, 's> { + fn from(value: &'r Target<'s>) -> Self { + AstNode::Target(value) + } +} +impl<'r, 's> From<&'r StatisticsCookie<'s>> for AstNode<'r, 's> { + fn from(value: &'r StatisticsCookie<'s>) -> Self { + AstNode::StatisticsCookie(value) + } +} +impl<'r, 's> From<&'r Subscript<'s>> for AstNode<'r, 's> { + fn from(value: &'r Subscript<'s>) -> Self { + AstNode::Subscript(value) + } +} +impl<'r, 's> From<&'r Superscript<'s>> for AstNode<'r, 's> { + fn from(value: &'r Superscript<'s>) -> Self { + AstNode::Superscript(value) + } +} +impl<'r, 's> From<&'r Timestamp<'s>> for AstNode<'r, 's> { + fn from(value: &'r Timestamp<'s>) -> Self { + AstNode::Timestamp(value) + } +} diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index dcd79bc..0ad3093 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -1,63 +1,73 @@ +use super::ast_node::AstNode; use crate::types::Object; -pub enum AstNodeIter<'s> { +pub enum AstNodeIter<'r, 's> { // Document Nodes - // Document(DocumentIter<'s>), - // Heading(HeadingIter<'s>), - // Section(SectionIter<'s>), + // Document(DocumentIter<'r, 's>), + // Heading(HeadingIter<'r, 's>), + // Section(SectionIter<'r, 's>), // Elements - // Paragraph(ParagraphIter<'s>), - // PlainList(PlainListIter<'s>), - // GreaterBlock(GreaterBlockIter<'s>), - // DynamicBlock(DynamicBlockIter<'s>), - // FootnoteDefinition(FootnoteDefinitionIter<'s>), - // Comment(CommentIter<'s>), - // Drawer(DrawerIter<'s>), - // PropertyDrawer(PropertyDrawerIter<'s>), - // Table(TableIter<'s>), - // VerseBlock(VerseBlockIter<'s>), - // CommentBlock(CommentBlockIter<'s>), - // ExampleBlock(ExampleBlockIter<'s>), - // ExportBlock(ExportBlockIter<'s>), - // SrcBlock(SrcBlockIter<'s>), - // Clock(ClockIter<'s>), - // DiarySexp(DiarySexpIter<'s>), - // Planning(PlanningIter<'s>), - // FixedWidthArea(FixedWidthAreaIter<'s>), - // HorizontalRule(HorizontalRuleIter<'s>), - // Keyword(KeywordIter<'s>), - // BabelCall(BabelCallIter<'s>), - // LatexEnvironment(LatexEnvironmentIter<'s>), + // Paragraph(ParagraphIter<'r, 's>), + // PlainList(PlainListIter<'r, 's>), + // GreaterBlock(GreaterBlockIter<'r, 's>), + // DynamicBlock(DynamicBlockIter<'r, 's>), + // FootnoteDefinition(FootnoteDefinitionIter<'r, 's>), + // Comment(CommentIter<'r, 's>), + // Drawer(DrawerIter<'r, 's>), + // PropertyDrawer(PropertyDrawerIter<'r, 's>), + // Table(TableIter<'r, 's>), + // VerseBlock(VerseBlockIter<'r, 's>), + // CommentBlock(CommentBlockIter<'r, 's>), + // ExampleBlock(ExampleBlockIter<'r, 's>), + // ExportBlock(ExportBlockIter<'r, 's>), + // SrcBlock(SrcBlockIter<'r, 's>), + // Clock(ClockIter<'r, 's>), + // DiarySexp(DiarySexpIter<'r, 's>), + // Planning(PlanningIter<'r, 's>), + // FixedWidthArea(FixedWidthAreaIter<'r, 's>), + // HorizontalRule(HorizontalRuleIter<'r, 's>), + // Keyword(KeywordIter<'r, 's>), + // BabelCall(BabelCallIter<'r, 's>), + // LatexEnvironment(LatexEnvironmentIter<'r, 's>), // Objects - Bold(BoldIter<'s>), - // Italic(ItalicIter<'s>), - // Underline(UnderlineIter<'s>), - // StrikeThrough(StrikeThroughIter<'s>), - // Code(CodeIter<'s>), - // Verbatim(VerbatimIter<'s>), - // PlainText(PlainTextIter<'s>), - // RegularLink(RegularLinkIter<'s>), - // RadioLink(RadioLinkIter<'s>), - // RadioTarget(RadioTargetIter<'s>), - // PlainLink(PlainLinkIter<'s>), - // AngleLink(AngleLinkIter<'s>), - // OrgMacro(OrgMacroIter<'s>), - // Entity(EntityIter<'s>), - // LatexFragment(LatexFragmentIter<'s>), - // ExportSnippet(ExportSnippetIter<'s>), - // FootnoteReference(FootnoteReferenceIter<'s>), - // Citation(CitationIter<'s>), - // CitationReference(CitationReferenceIter<'s>), - // InlineBabelCall(InlineBabelCallIter<'s>), - // InlineSourceBlock(InlineSourceBlockIter<'s>), - // LineBreak(LineBreakIter<'s>), - // Target(TargetIter<'s>), - // StatisticsCookie(StatisticsCookieIter<'s>), - // Subscript(SubscriptIter<'s>), - // Superscript(SuperscriptIter<'s>), - // Timestamp(TimestampIter<'s>), + Bold(BoldIter<'r, 's>), + // Italic(ItalicIter<'r, 's>), + // Underline(UnderlineIter<'r, 's>), + // StrikeThrough(StrikeThroughIter<'r, 's>), + // Code(CodeIter<'r, 's>), + // Verbatim(VerbatimIter<'r, 's>), + // PlainText(PlainTextIter<'r, 's>), + // RegularLink(RegularLinkIter<'r, 's>), + // RadioLink(RadioLinkIter<'r, 's>), + // RadioTarget(RadioTargetIter<'r, 's>), + // PlainLink(PlainLinkIter<'r, 's>), + // AngleLink(AngleLinkIter<'r, 's>), + // OrgMacro(OrgMacroIter<'r, 's>), + // Entity(EntityIter<'r, 's>), + // LatexFragment(LatexFragmentIter<'r, 's>), + // ExportSnippet(ExportSnippetIter<'r, 's>), + // FootnoteReference(FootnoteReferenceIter<'r, 's>), + // Citation(CitationIter<'r, 's>), + // CitationReference(CitationReferenceIter<'r, 's>), + // InlineBabelCall(InlineBabelCallIter<'r, 's>), + // InlineSourceBlock(InlineSourceBlockIter<'r, 's>), + // LineBreak(LineBreakIter<'r, 's>), + // Target(TargetIter<'r, 's>), + // StatisticsCookie(StatisticsCookieIter<'r, 's>), + // Subscript(SubscriptIter<'r, 's>), + // Superscript(SuperscriptIter<'r, 's>), + // Timestamp(TimestampIter<'r, 's>), } -pub struct BoldIter<'s> { - next: std::slice::Iter<'s, Object<'s>>, +pub struct BoldIter<'r, 's> { + next: std::slice::Iter<'r, Object<'s>>, +} + +impl<'r, 's> Iterator for BoldIter<'r, 's> { + type Item = AstNode<'r, 's>; + + fn next(&mut self) -> Option { + let foo = self.next.next(); + todo!() + } } From 9a1d91ae45576f0f15a142bd63d0358f4c057546 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 15:17:56 -0400 Subject: [PATCH 04/18] Manual implementation of BoldIter. --- src/iter/ast_node_iter.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index 0ad3093..0abe9d9 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -1,4 +1,5 @@ use super::ast_node::AstNode; +use crate::types::Bold; use crate::types::Object; pub enum AstNodeIter<'r, 's> { @@ -67,7 +68,18 @@ impl<'r, 's> Iterator for BoldIter<'r, 's> { type Item = AstNode<'r, 's>; fn next(&mut self) -> Option { - let foo = self.next.next(); - todo!() + self.next.next().map(Into::::into) + } +} + +impl<'r, 's> IntoIterator for &'r Bold<'s> { + type Item = AstNode<'r, 's>; + + type IntoIter = BoldIter<'r, 's>; + + fn into_iter(self) -> Self::IntoIter { + BoldIter { + next: self.children.iter(), + } } } From e4cfc296e567d27d3920659768ad6ea4684b47d0 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 15:28:43 -0400 Subject: [PATCH 05/18] Introduce macro to simplify this. --- src/iter/ast_node_iter.rs | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index 0abe9d9..0c55a80 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -1,5 +1,6 @@ use super::ast_node::AstNode; use crate::types::Bold; +use crate::types::Italic; use crate::types::Object; pub enum AstNodeIter<'r, 's> { @@ -32,7 +33,7 @@ pub enum AstNodeIter<'r, 's> { // LatexEnvironment(LatexEnvironmentIter<'r, 's>), // Objects Bold(BoldIter<'r, 's>), - // Italic(ItalicIter<'r, 's>), + Italic(ItalicIter<'r, 's>), // Underline(UnderlineIter<'r, 's>), // StrikeThrough(StrikeThroughIter<'r, 's>), // Code(CodeIter<'r, 's>), @@ -83,3 +84,33 @@ impl<'r, 's> IntoIterator for &'r Bold<'s> { } } } + +macro_rules! simple_iter { + ($astnodetype:ty, $itertype:ident, $innertype:ty) => { + pub struct $itertype<'r, 's> { + next: $innertype, + } + + impl<'r, 's> Iterator for $itertype<'r, 's> { + type Item = AstNode<'r, 's>; + + fn next(&mut self) -> Option { + self.next.next().map(Into::::into) + } + } + + impl<'r, 's> IntoIterator for &'r $astnodetype { + type Item = AstNode<'r, 's>; + + type IntoIter = $itertype<'r, 's>; + + fn into_iter(self) -> Self::IntoIter { + $itertype { + next: self.children.iter(), + } + } + } + }; +} + +simple_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); From 7419b75d76fbae9c218eaf255bb9c391adaf7bc3 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 15:38:33 -0400 Subject: [PATCH 06/18] Implement empty iterator for types with no ast node children. --- src/iter/ast_node_iter.rs | 70 +++++++++++++++++++++++---------------- src/iter/macros.rs | 30 +++++++++++++++++ src/iter/mod.rs | 1 + 3 files changed, 72 insertions(+), 29 deletions(-) create mode 100644 src/iter/macros.rs diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index 0c55a80..19b85c1 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -1,7 +1,13 @@ +use std::marker::PhantomData; + use super::ast_node::AstNode; +use super::macros::simple_iter; use crate::types::Bold; +use crate::types::Code; use crate::types::Italic; use crate::types::Object; +use crate::types::StrikeThrough; +use crate::types::Underline; pub enum AstNodeIter<'r, 's> { // Document Nodes @@ -34,9 +40,9 @@ pub enum AstNodeIter<'r, 's> { // Objects Bold(BoldIter<'r, 's>), Italic(ItalicIter<'r, 's>), - // Underline(UnderlineIter<'r, 's>), - // StrikeThrough(StrikeThroughIter<'r, 's>), - // Code(CodeIter<'r, 's>), + Underline(UnderlineIter<'r, 's>), + StrikeThrough(StrikeThroughIter<'r, 's>), + Code(CodeIter<'r, 's>), // Verbatim(VerbatimIter<'r, 's>), // PlainText(PlainTextIter<'r, 's>), // RegularLink(RegularLinkIter<'r, 's>), @@ -85,32 +91,38 @@ impl<'r, 's> IntoIterator for &'r Bold<'s> { } } -macro_rules! simple_iter { - ($astnodetype:ty, $itertype:ident, $innertype:ty) => { - pub struct $itertype<'r, 's> { - next: $innertype, - } +simple_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); +simple_iter!( + Underline<'s>, + UnderlineIter, + std::slice::Iter<'r, Object<'s>> +); +simple_iter!( + StrikeThrough<'s>, + StrikeThroughIter, + std::slice::Iter<'r, Object<'s>> +); - impl<'r, 's> Iterator for $itertype<'r, 's> { - type Item = AstNode<'r, 's>; - - fn next(&mut self) -> Option { - self.next.next().map(Into::::into) - } - } - - impl<'r, 's> IntoIterator for &'r $astnodetype { - type Item = AstNode<'r, 's>; - - type IntoIter = $itertype<'r, 's>; - - fn into_iter(self) -> Self::IntoIter { - $itertype { - next: self.children.iter(), - } - } - } - }; +pub struct CodeIter<'r, 's> { + phantom: PhantomData<&'r Code<'s>>, } -simple_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); +impl<'r, 's> Iterator for CodeIter<'r, 's> { + type Item = AstNode<'r, 's>; + + fn next(&mut self) -> Option { + None + } +} + +impl<'r, 's> IntoIterator for &'r Code<'s> { + type Item = AstNode<'r, 's>; + + type IntoIter = CodeIter<'r, 's>; + + fn into_iter(self) -> Self::IntoIter { + CodeIter { + phantom: PhantomData, + } + } +} diff --git a/src/iter/macros.rs b/src/iter/macros.rs new file mode 100644 index 0000000..acb0f40 --- /dev/null +++ b/src/iter/macros.rs @@ -0,0 +1,30 @@ +/// Create iterators for ast nodes where it only has to iterate over children +macro_rules! simple_iter { + ($astnodetype:ty, $itertype:ident, $innertype:ty) => { + pub struct $itertype<'r, 's> { + next: $innertype, + } + + impl<'r, 's> Iterator for $itertype<'r, 's> { + type Item = AstNode<'r, 's>; + + fn next(&mut self) -> Option { + self.next.next().map(Into::::into) + } + } + + impl<'r, 's> IntoIterator for &'r $astnodetype { + type Item = AstNode<'r, 's>; + + type IntoIter = $itertype<'r, 's>; + + fn into_iter(self) -> Self::IntoIter { + $itertype { + next: self.children.iter(), + } + } + } + }; +} + +pub(crate) use simple_iter; diff --git a/src/iter/mod.rs b/src/iter/mod.rs index b59a57f..b622d37 100644 --- a/src/iter/mod.rs +++ b/src/iter/mod.rs @@ -1,2 +1,3 @@ mod ast_node; mod ast_node_iter; +mod macros; From 4359fc92667109e83573730a9c09950a11b3ded0 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 15:47:01 -0400 Subject: [PATCH 07/18] Introduce a macro for empty iterators. --- src/iter/ast_node_iter.rs | 19 ++++++++++++++----- src/iter/macros.rs | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index 19b85c1..39d5b58 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -1,14 +1,21 @@ use std::marker::PhantomData; use super::ast_node::AstNode; -use super::macros::simple_iter; +use super::macros::children_iter; +use super::macros::empty_iter; 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; +/// Iterator over the AST nodes contained within the starting node. +/// +/// This only iterates over the children, not the starting node itself. So an AstNodeIter::PlainList would only return PlainListItems, not the PlainList. +/// +/// This only iterates over AST nodes, so an AstNodeIter::Heading would iterate over both the title and section contents, but it would not iterate over simple strings like the TODO keyword or priority. pub enum AstNodeIter<'r, 's> { // Document Nodes // Document(DocumentIter<'r, 's>), @@ -43,7 +50,7 @@ pub enum AstNodeIter<'r, 's> { Underline(UnderlineIter<'r, 's>), StrikeThrough(StrikeThroughIter<'r, 's>), Code(CodeIter<'r, 's>), - // Verbatim(VerbatimIter<'r, 's>), + Verbatim(VerbatimIter<'r, 's>), // PlainText(PlainTextIter<'r, 's>), // RegularLink(RegularLinkIter<'r, 's>), // RadioLink(RadioLinkIter<'r, 's>), @@ -91,13 +98,13 @@ impl<'r, 's> IntoIterator for &'r Bold<'s> { } } -simple_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); -simple_iter!( +children_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); +children_iter!( Underline<'s>, UnderlineIter, std::slice::Iter<'r, Object<'s>> ); -simple_iter!( +children_iter!( StrikeThrough<'s>, StrikeThroughIter, std::slice::Iter<'r, Object<'s>> @@ -126,3 +133,5 @@ impl<'r, 's> IntoIterator for &'r Code<'s> { } } } + +empty_iter!(Verbatim<'s>, VerbatimIter); diff --git a/src/iter/macros.rs b/src/iter/macros.rs index acb0f40..07b36fe 100644 --- a/src/iter/macros.rs +++ b/src/iter/macros.rs @@ -1,5 +1,5 @@ /// Create iterators for ast nodes where it only has to iterate over children -macro_rules! simple_iter { +macro_rules! children_iter { ($astnodetype:ty, $itertype:ident, $innertype:ty) => { pub struct $itertype<'r, 's> { next: $innertype, @@ -27,4 +27,35 @@ macro_rules! simple_iter { }; } -pub(crate) use simple_iter; +pub(crate) use children_iter; + +/// Create iterators for ast nodes that do not contain any ast node children. +macro_rules! empty_iter { + ($astnodetype:ty, $itertype:ident) => { + pub struct $itertype<'r, 's> { + phantom: PhantomData<&'r $astnodetype>, + } + + impl<'r, 's> Iterator for $itertype<'r, 's> { + type Item = AstNode<'r, 's>; + + fn next(&mut self) -> Option { + None + } + } + + impl<'r, 's> IntoIterator for &'r $astnodetype { + type Item = AstNode<'r, 's>; + + type IntoIter = $itertype<'r, 's>; + + fn into_iter(self) -> Self::IntoIter { + $itertype { + phantom: PhantomData, + } + } + } + }; +} + +pub(crate) use empty_iter; From ab46a9e5c6cf44abc72bbac521070e428ad324d2 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 15:56:45 -0400 Subject: [PATCH 08/18] Ran into issue with heading, naming this type is going to be a nightmare. --- src/iter/ast_node.rs | 10 +++++++ src/iter/ast_node_iter.rs | 62 +++++++++++++++++---------------------- 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/iter/ast_node.rs b/src/iter/ast_node.rs index 0704ab3..4ff87a6 100644 --- a/src/iter/ast_node.rs +++ b/src/iter/ast_node.rs @@ -9,6 +9,7 @@ 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; @@ -111,6 +112,15 @@ pub enum AstNode<'r, 's> { Timestamp(&'r Timestamp<'s>), } +impl<'r, 's> From<&'r DocumentElement<'s>> for AstNode<'r, 's> { + fn from(value: &'r DocumentElement<'s>) -> Self { + match value { + DocumentElement::Heading(inner) => inner.into(), + DocumentElement::Section(inner) => inner.into(), + } + } +} + impl<'r, 's> From<&'r Element<'s>> for AstNode<'r, 's> { fn from(value: &'r Element<'s>) -> Self { match value { diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index 39d5b58..dc181da 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -5,8 +5,12 @@ use super::macros::children_iter; use super::macros::empty_iter; use crate::types::Bold; use crate::types::Code; +use crate::types::Heading; use crate::types::Italic; use crate::types::Object; +use crate::types::PlainText; +use crate::types::RadioLink; +use crate::types::RegularLink; use crate::types::StrikeThrough; use crate::types::Underline; use crate::types::Verbatim; @@ -19,7 +23,7 @@ use crate::types::Verbatim; pub enum AstNodeIter<'r, 's> { // Document Nodes // Document(DocumentIter<'r, 's>), - // Heading(HeadingIter<'r, 's>), + Heading(HeadingIter<'r, 's>), // Section(SectionIter<'r, 's>), // Elements // Paragraph(ParagraphIter<'r, 's>), @@ -51,9 +55,9 @@ pub enum AstNodeIter<'r, 's> { StrikeThrough(StrikeThroughIter<'r, 's>), Code(CodeIter<'r, 's>), Verbatim(VerbatimIter<'r, 's>), - // PlainText(PlainTextIter<'r, 's>), - // RegularLink(RegularLinkIter<'r, 's>), - // RadioLink(RadioLinkIter<'r, 's>), + PlainText(PlainTextIter<'r, 's>), + RegularLink(RegularLinkIter<'r, 's>), + RadioLink(RadioLinkIter<'r, 's>), // RadioTarget(RadioTargetIter<'r, 's>), // PlainLink(PlainLinkIter<'r, 's>), // AngleLink(AngleLinkIter<'r, 's>), @@ -74,11 +78,11 @@ pub enum AstNodeIter<'r, 's> { // Timestamp(TimestampIter<'r, 's>), } -pub struct BoldIter<'r, 's> { +pub struct HeadingIter<'r, 's> { next: std::slice::Iter<'r, Object<'s>>, } -impl<'r, 's> Iterator for BoldIter<'r, 's> { +impl<'r, 's> Iterator for HeadingIter<'r, 's> { type Item = AstNode<'r, 's>; fn next(&mut self) -> Option { @@ -86,18 +90,23 @@ impl<'r, 's> Iterator for BoldIter<'r, 's> { } } -impl<'r, 's> IntoIterator for &'r Bold<'s> { +impl<'r, 's> IntoIterator for &'r Heading<'s> { type Item = AstNode<'r, 's>; - type IntoIter = BoldIter<'r, 's>; + type IntoIter = HeadingIter<'r, 's>; fn into_iter(self) -> Self::IntoIter { - BoldIter { - next: self.children.iter(), + HeadingIter { + next: self + .title + .iter() + .map(Into::::into) + .chain(self.children.iter().map(Into::::into)), } } } +children_iter!(Bold<'s>, BoldIter, std::slice::Iter<'r, Object<'s>>); children_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); children_iter!( Underline<'s>, @@ -109,29 +118,12 @@ children_iter!( StrikeThroughIter, std::slice::Iter<'r, Object<'s>> ); - -pub struct CodeIter<'r, 's> { - phantom: PhantomData<&'r Code<'s>>, -} - -impl<'r, 's> Iterator for CodeIter<'r, 's> { - type Item = AstNode<'r, 's>; - - fn next(&mut self) -> Option { - None - } -} - -impl<'r, 's> IntoIterator for &'r Code<'s> { - type Item = AstNode<'r, 's>; - - type IntoIter = CodeIter<'r, 's>; - - fn into_iter(self) -> Self::IntoIter { - CodeIter { - phantom: PhantomData, - } - } -} - +empty_iter!(Code<'s>, CodeIter); empty_iter!(Verbatim<'s>, VerbatimIter); +empty_iter!(PlainText<'s>, PlainTextIter); +empty_iter!(RegularLink<'s>, RegularLinkIter); +children_iter!( + RadioLink<'s>, + RadioLinkIter, + std::slice::Iter<'r, Object<'s>> +); From 282417ee944948445e1fced8334f25478ca91c55 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 18:00:30 -0400 Subject: [PATCH 09/18] Implementing HeadingIter but I do not think it can be generic enough for a macro. Hopefully most types won't need so much care. --- src/iter/ast_node_iter.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index dc181da..ee92efa 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -5,6 +5,8 @@ use super::macros::children_iter; use super::macros::empty_iter; use crate::types::Bold; use crate::types::Code; +use crate::types::DocumentElement; +use crate::types::Element; use crate::types::Heading; use crate::types::Italic; use crate::types::Object; @@ -79,14 +81,18 @@ pub enum AstNodeIter<'r, 's> { } pub struct HeadingIter<'r, 's> { - next: std::slice::Iter<'r, Object<'s>>, + title_next: std::slice::Iter<'r, Object<'s>>, + children_next: std::slice::Iter<'r, DocumentElement<'s>>, } impl<'r, 's> Iterator for HeadingIter<'r, 's> { type Item = AstNode<'r, 's>; fn next(&mut self) -> Option { - self.next.next().map(Into::::into) + self.title_next + .next() + .map(Into::::into) + .or_else(|| self.children_next.next().map(Into::::into)) } } @@ -97,11 +103,8 @@ impl<'r, 's> IntoIterator for &'r Heading<'s> { fn into_iter(self) -> Self::IntoIter { HeadingIter { - next: self - .title - .iter() - .map(Into::::into) - .chain(self.children.iter().map(Into::::into)), + title_next: self.title.iter(), + children_next: self.children.iter(), } } } From c5be75ee8d3421326bed6a1d0dd4a35008dd5660 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 18:05:53 -0400 Subject: [PATCH 10/18] Implement DocumentIter and SectionIter. --- src/iter/ast_node_iter.rs | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index ee92efa..d0e18ea 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -5,6 +5,7 @@ use super::macros::children_iter; use super::macros::empty_iter; use crate::types::Bold; use crate::types::Code; +use crate::types::Document; use crate::types::DocumentElement; use crate::types::Element; use crate::types::Heading; @@ -13,6 +14,7 @@ use crate::types::Object; use crate::types::PlainText; use crate::types::RadioLink; use crate::types::RegularLink; +use crate::types::Section; use crate::types::StrikeThrough; use crate::types::Underline; use crate::types::Verbatim; @@ -24,9 +26,9 @@ use crate::types::Verbatim; /// This only iterates over AST nodes, so an AstNodeIter::Heading would iterate over both the title and section contents, but it would not iterate over simple strings like the TODO keyword or priority. pub enum AstNodeIter<'r, 's> { // Document Nodes - // Document(DocumentIter<'r, 's>), + Document(DocumentIter<'r, 's>), Heading(HeadingIter<'r, 's>), - // Section(SectionIter<'r, 's>), + Section(SectionIter<'r, 's>), // Elements // Paragraph(ParagraphIter<'r, 's>), // PlainList(PlainListIter<'r, 's>), @@ -80,6 +82,35 @@ pub enum AstNodeIter<'r, 's> { // Timestamp(TimestampIter<'r, 's>), } +pub struct DocumentIter<'r, 's> { + zeroth_section_next: std::option::Iter<'r, Section<'s>>, + children_next: std::slice::Iter<'r, Heading<'s>>, +} + +impl<'r, 's> Iterator for DocumentIter<'r, 's> { + type Item = AstNode<'r, 's>; + + fn next(&mut self) -> Option { + self.zeroth_section_next + .next() + .map(Into::::into) + .or_else(|| self.children_next.next().map(Into::::into)) + } +} + +impl<'r, 's> IntoIterator for &'r Document<'s> { + type Item = AstNode<'r, 's>; + + type IntoIter = DocumentIter<'r, 's>; + + fn into_iter(self) -> Self::IntoIter { + DocumentIter { + zeroth_section_next: self.zeroth_section.iter(), + children_next: self.children.iter(), + } + } +} + pub struct HeadingIter<'r, 's> { title_next: std::slice::Iter<'r, Object<'s>>, children_next: std::slice::Iter<'r, DocumentElement<'s>>, @@ -109,6 +140,7 @@ impl<'r, 's> IntoIterator for &'r Heading<'s> { } } +children_iter!(Section<'s>, SectionIter, std::slice::Iter<'r, Element<'s>>); children_iter!(Bold<'s>, BoldIter, std::slice::Iter<'r, Object<'s>>); children_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); children_iter!( From d8c52568db5a4e38dc779cee2930983c08c6805b Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 18:21:42 -0400 Subject: [PATCH 11/18] Add PlainListItem to ast nodes. --- src/iter/ast_node.rs | 316 +++++++------------------------------- src/iter/ast_node_iter.rs | 17 +- src/iter/macros.rs | 13 ++ 3 files changed, 84 insertions(+), 262 deletions(-) diff --git a/src/iter/ast_node.rs b/src/iter/ast_node.rs index 4ff87a6..579a26b 100644 --- a/src/iter/ast_node.rs +++ b/src/iter/ast_node.rs @@ -1,3 +1,4 @@ +use super::macros::to_ast_node; use crate::types::AngleLink; use crate::types::BabelCall; use crate::types::Bold; @@ -35,6 +36,7 @@ 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; @@ -62,6 +64,7 @@ pub enum AstNode<'r, 's> { // Elements Paragraph(&'r Paragraph<'s>), PlainList(&'r PlainList<'s>), + PlainListItem(&'r PlainListItem<'s>), GreaterBlock(&'r GreaterBlock<'s>), DynamicBlock(&'r DynamicBlock<'s>), FootnoteDefinition(&'r FootnoteDefinition<'s>), @@ -184,263 +187,56 @@ impl<'r, 's> From<&'r Object<'s>> for AstNode<'r, 's> { } } -impl<'r, 's> From<&'r Document<'s>> for AstNode<'r, 's> { - fn from(value: &'r Document<'s>) -> Self { - AstNode::Document(value) - } -} -impl<'r, 's> From<&'r Heading<'s>> for AstNode<'r, 's> { - fn from(value: &'r Heading<'s>) -> Self { - AstNode::Heading(value) - } -} -impl<'r, 's> From<&'r Section<'s>> for AstNode<'r, 's> { - fn from(value: &'r Section<'s>) -> Self { - AstNode::Section(value) - } -} -impl<'r, 's> From<&'r Paragraph<'s>> for AstNode<'r, 's> { - fn from(value: &'r Paragraph<'s>) -> Self { - AstNode::Paragraph(value) - } -} -impl<'r, 's> From<&'r PlainList<'s>> for AstNode<'r, 's> { - fn from(value: &'r PlainList<'s>) -> Self { - AstNode::PlainList(value) - } -} -impl<'r, 's> From<&'r GreaterBlock<'s>> for AstNode<'r, 's> { - fn from(value: &'r GreaterBlock<'s>) -> Self { - AstNode::GreaterBlock(value) - } -} -impl<'r, 's> From<&'r DynamicBlock<'s>> for AstNode<'r, 's> { - fn from(value: &'r DynamicBlock<'s>) -> Self { - AstNode::DynamicBlock(value) - } -} -impl<'r, 's> From<&'r FootnoteDefinition<'s>> for AstNode<'r, 's> { - fn from(value: &'r FootnoteDefinition<'s>) -> Self { - AstNode::FootnoteDefinition(value) - } -} -impl<'r, 's> From<&'r Comment<'s>> for AstNode<'r, 's> { - fn from(value: &'r Comment<'s>) -> Self { - AstNode::Comment(value) - } -} -impl<'r, 's> From<&'r Drawer<'s>> for AstNode<'r, 's> { - fn from(value: &'r Drawer<'s>) -> Self { - AstNode::Drawer(value) - } -} -impl<'r, 's> From<&'r PropertyDrawer<'s>> for AstNode<'r, 's> { - fn from(value: &'r PropertyDrawer<'s>) -> Self { - AstNode::PropertyDrawer(value) - } -} -impl<'r, 's> From<&'r Table<'s>> for AstNode<'r, 's> { - fn from(value: &'r Table<'s>) -> Self { - AstNode::Table(value) - } -} -impl<'r, 's> From<&'r VerseBlock<'s>> for AstNode<'r, 's> { - fn from(value: &'r VerseBlock<'s>) -> Self { - AstNode::VerseBlock(value) - } -} -impl<'r, 's> From<&'r CommentBlock<'s>> for AstNode<'r, 's> { - fn from(value: &'r CommentBlock<'s>) -> Self { - AstNode::CommentBlock(value) - } -} -impl<'r, 's> From<&'r ExampleBlock<'s>> for AstNode<'r, 's> { - fn from(value: &'r ExampleBlock<'s>) -> Self { - AstNode::ExampleBlock(value) - } -} -impl<'r, 's> From<&'r ExportBlock<'s>> for AstNode<'r, 's> { - fn from(value: &'r ExportBlock<'s>) -> Self { - AstNode::ExportBlock(value) - } -} -impl<'r, 's> From<&'r SrcBlock<'s>> for AstNode<'r, 's> { - fn from(value: &'r SrcBlock<'s>) -> Self { - AstNode::SrcBlock(value) - } -} -impl<'r, 's> From<&'r Clock<'s>> for AstNode<'r, 's> { - fn from(value: &'r Clock<'s>) -> Self { - AstNode::Clock(value) - } -} -impl<'r, 's> From<&'r DiarySexp<'s>> for AstNode<'r, 's> { - fn from(value: &'r DiarySexp<'s>) -> Self { - AstNode::DiarySexp(value) - } -} -impl<'r, 's> From<&'r Planning<'s>> for AstNode<'r, 's> { - fn from(value: &'r Planning<'s>) -> Self { - AstNode::Planning(value) - } -} -impl<'r, 's> From<&'r FixedWidthArea<'s>> for AstNode<'r, 's> { - fn from(value: &'r FixedWidthArea<'s>) -> Self { - AstNode::FixedWidthArea(value) - } -} -impl<'r, 's> From<&'r HorizontalRule<'s>> for AstNode<'r, 's> { - fn from(value: &'r HorizontalRule<'s>) -> Self { - AstNode::HorizontalRule(value) - } -} -impl<'r, 's> From<&'r Keyword<'s>> for AstNode<'r, 's> { - fn from(value: &'r Keyword<'s>) -> Self { - AstNode::Keyword(value) - } -} -impl<'r, 's> From<&'r BabelCall<'s>> for AstNode<'r, 's> { - fn from(value: &'r BabelCall<'s>) -> Self { - AstNode::BabelCall(value) - } -} -impl<'r, 's> From<&'r LatexEnvironment<'s>> for AstNode<'r, 's> { - fn from(value: &'r LatexEnvironment<'s>) -> Self { - AstNode::LatexEnvironment(value) - } -} -impl<'r, 's> From<&'r Bold<'s>> for AstNode<'r, 's> { - fn from(value: &'r Bold<'s>) -> Self { - AstNode::Bold(value) - } -} -impl<'r, 's> From<&'r Italic<'s>> for AstNode<'r, 's> { - fn from(value: &'r Italic<'s>) -> Self { - AstNode::Italic(value) - } -} -impl<'r, 's> From<&'r Underline<'s>> for AstNode<'r, 's> { - fn from(value: &'r Underline<'s>) -> Self { - AstNode::Underline(value) - } -} -impl<'r, 's> From<&'r StrikeThrough<'s>> for AstNode<'r, 's> { - fn from(value: &'r StrikeThrough<'s>) -> Self { - AstNode::StrikeThrough(value) - } -} -impl<'r, 's> From<&'r Code<'s>> for AstNode<'r, 's> { - fn from(value: &'r Code<'s>) -> Self { - AstNode::Code(value) - } -} -impl<'r, 's> From<&'r Verbatim<'s>> for AstNode<'r, 's> { - fn from(value: &'r Verbatim<'s>) -> Self { - AstNode::Verbatim(value) - } -} -impl<'r, 's> From<&'r PlainText<'s>> for AstNode<'r, 's> { - fn from(value: &'r PlainText<'s>) -> Self { - AstNode::PlainText(value) - } -} -impl<'r, 's> From<&'r RegularLink<'s>> for AstNode<'r, 's> { - fn from(value: &'r RegularLink<'s>) -> Self { - AstNode::RegularLink(value) - } -} -impl<'r, 's> From<&'r RadioLink<'s>> for AstNode<'r, 's> { - fn from(value: &'r RadioLink<'s>) -> Self { - AstNode::RadioLink(value) - } -} -impl<'r, 's> From<&'r RadioTarget<'s>> for AstNode<'r, 's> { - fn from(value: &'r RadioTarget<'s>) -> Self { - AstNode::RadioTarget(value) - } -} -impl<'r, 's> From<&'r PlainLink<'s>> for AstNode<'r, 's> { - fn from(value: &'r PlainLink<'s>) -> Self { - AstNode::PlainLink(value) - } -} -impl<'r, 's> From<&'r AngleLink<'s>> for AstNode<'r, 's> { - fn from(value: &'r AngleLink<'s>) -> Self { - AstNode::AngleLink(value) - } -} -impl<'r, 's> From<&'r OrgMacro<'s>> for AstNode<'r, 's> { - fn from(value: &'r OrgMacro<'s>) -> Self { - AstNode::OrgMacro(value) - } -} -impl<'r, 's> From<&'r Entity<'s>> for AstNode<'r, 's> { - fn from(value: &'r Entity<'s>) -> Self { - AstNode::Entity(value) - } -} -impl<'r, 's> From<&'r LatexFragment<'s>> for AstNode<'r, 's> { - fn from(value: &'r LatexFragment<'s>) -> Self { - AstNode::LatexFragment(value) - } -} -impl<'r, 's> From<&'r ExportSnippet<'s>> for AstNode<'r, 's> { - fn from(value: &'r ExportSnippet<'s>) -> Self { - AstNode::ExportSnippet(value) - } -} -impl<'r, 's> From<&'r FootnoteReference<'s>> for AstNode<'r, 's> { - fn from(value: &'r FootnoteReference<'s>) -> Self { - AstNode::FootnoteReference(value) - } -} -impl<'r, 's> From<&'r Citation<'s>> for AstNode<'r, 's> { - fn from(value: &'r Citation<'s>) -> Self { - AstNode::Citation(value) - } -} -impl<'r, 's> From<&'r CitationReference<'s>> for AstNode<'r, 's> { - fn from(value: &'r CitationReference<'s>) -> Self { - AstNode::CitationReference(value) - } -} -impl<'r, 's> From<&'r InlineBabelCall<'s>> for AstNode<'r, 's> { - fn from(value: &'r InlineBabelCall<'s>) -> Self { - AstNode::InlineBabelCall(value) - } -} -impl<'r, 's> From<&'r InlineSourceBlock<'s>> for AstNode<'r, 's> { - fn from(value: &'r InlineSourceBlock<'s>) -> Self { - AstNode::InlineSourceBlock(value) - } -} -impl<'r, 's> From<&'r LineBreak<'s>> for AstNode<'r, 's> { - fn from(value: &'r LineBreak<'s>) -> Self { - AstNode::LineBreak(value) - } -} -impl<'r, 's> From<&'r Target<'s>> for AstNode<'r, 's> { - fn from(value: &'r Target<'s>) -> Self { - AstNode::Target(value) - } -} -impl<'r, 's> From<&'r StatisticsCookie<'s>> for AstNode<'r, 's> { - fn from(value: &'r StatisticsCookie<'s>) -> Self { - AstNode::StatisticsCookie(value) - } -} -impl<'r, 's> From<&'r Subscript<'s>> for AstNode<'r, 's> { - fn from(value: &'r Subscript<'s>) -> Self { - AstNode::Subscript(value) - } -} -impl<'r, 's> From<&'r Superscript<'s>> for AstNode<'r, 's> { - fn from(value: &'r Superscript<'s>) -> Self { - AstNode::Superscript(value) - } -} -impl<'r, 's> From<&'r Timestamp<'s>> for AstNode<'r, 's> { - fn from(value: &'r Timestamp<'s>) -> Self { - AstNode::Timestamp(value) - } -} +to_ast_node!(&'r Document<'s>, AstNode::Document); +to_ast_node!(&'r Heading<'s>, AstNode::Heading); +to_ast_node!(&'r Section<'s>, AstNode::Section); +to_ast_node!(&'r Paragraph<'s>, AstNode::Paragraph); +to_ast_node!(&'r PlainList<'s>, AstNode::PlainList); +to_ast_node!(&'r PlainListItem<'s>, AstNode::PlainListItem); +to_ast_node!(&'r GreaterBlock<'s>, AstNode::GreaterBlock); +to_ast_node!(&'r DynamicBlock<'s>, AstNode::DynamicBlock); +to_ast_node!(&'r FootnoteDefinition<'s>, AstNode::FootnoteDefinition); +to_ast_node!(&'r Comment<'s>, AstNode::Comment); +to_ast_node!(&'r Drawer<'s>, AstNode::Drawer); +to_ast_node!(&'r PropertyDrawer<'s>, AstNode::PropertyDrawer); +to_ast_node!(&'r Table<'s>, AstNode::Table); +to_ast_node!(&'r VerseBlock<'s>, AstNode::VerseBlock); +to_ast_node!(&'r CommentBlock<'s>, AstNode::CommentBlock); +to_ast_node!(&'r ExampleBlock<'s>, AstNode::ExampleBlock); +to_ast_node!(&'r ExportBlock<'s>, AstNode::ExportBlock); +to_ast_node!(&'r SrcBlock<'s>, AstNode::SrcBlock); +to_ast_node!(&'r Clock<'s>, AstNode::Clock); +to_ast_node!(&'r DiarySexp<'s>, AstNode::DiarySexp); +to_ast_node!(&'r Planning<'s>, AstNode::Planning); +to_ast_node!(&'r FixedWidthArea<'s>, AstNode::FixedWidthArea); +to_ast_node!(&'r HorizontalRule<'s>, AstNode::HorizontalRule); +to_ast_node!(&'r Keyword<'s>, AstNode::Keyword); +to_ast_node!(&'r BabelCall<'s>, AstNode::BabelCall); +to_ast_node!(&'r LatexEnvironment<'s>, AstNode::LatexEnvironment); +to_ast_node!(&'r Bold<'s>, AstNode::Bold); +to_ast_node!(&'r Italic<'s>, AstNode::Italic); +to_ast_node!(&'r Underline<'s>, AstNode::Underline); +to_ast_node!(&'r StrikeThrough<'s>, AstNode::StrikeThrough); +to_ast_node!(&'r Code<'s>, AstNode::Code); +to_ast_node!(&'r Verbatim<'s>, AstNode::Verbatim); +to_ast_node!(&'r PlainText<'s>, AstNode::PlainText); +to_ast_node!(&'r RegularLink<'s>, AstNode::RegularLink); +to_ast_node!(&'r RadioLink<'s>, AstNode::RadioLink); +to_ast_node!(&'r RadioTarget<'s>, AstNode::RadioTarget); +to_ast_node!(&'r PlainLink<'s>, AstNode::PlainLink); +to_ast_node!(&'r AngleLink<'s>, AstNode::AngleLink); +to_ast_node!(&'r OrgMacro<'s>, AstNode::OrgMacro); +to_ast_node!(&'r Entity<'s>, AstNode::Entity); +to_ast_node!(&'r LatexFragment<'s>, AstNode::LatexFragment); +to_ast_node!(&'r ExportSnippet<'s>, AstNode::ExportSnippet); +to_ast_node!(&'r FootnoteReference<'s>, AstNode::FootnoteReference); +to_ast_node!(&'r Citation<'s>, AstNode::Citation); +to_ast_node!(&'r CitationReference<'s>, AstNode::CitationReference); +to_ast_node!(&'r InlineBabelCall<'s>, AstNode::InlineBabelCall); +to_ast_node!(&'r InlineSourceBlock<'s>, AstNode::InlineSourceBlock); +to_ast_node!(&'r LineBreak<'s>, AstNode::LineBreak); +to_ast_node!(&'r Target<'s>, AstNode::Target); +to_ast_node!(&'r StatisticsCookie<'s>, AstNode::StatisticsCookie); +to_ast_node!(&'r Subscript<'s>, AstNode::Subscript); +to_ast_node!(&'r Superscript<'s>, AstNode::Superscript); +to_ast_node!(&'r Timestamp<'s>, AstNode::Timestamp); diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index d0e18ea..aa7adcd 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -11,6 +11,9 @@ use crate::types::Element; use crate::types::Heading; use crate::types::Italic; use crate::types::Object; +use crate::types::Paragraph; +use crate::types::PlainList; +use crate::types::PlainListItem; use crate::types::PlainText; use crate::types::RadioLink; use crate::types::RegularLink; @@ -30,8 +33,8 @@ pub enum AstNodeIter<'r, 's> { Heading(HeadingIter<'r, 's>), Section(SectionIter<'r, 's>), // Elements - // Paragraph(ParagraphIter<'r, 's>), - // PlainList(PlainListIter<'r, 's>), + Paragraph(ParagraphIter<'r, 's>), + PlainList(PlainListIter<'r, 's>), // GreaterBlock(GreaterBlockIter<'r, 's>), // DynamicBlock(DynamicBlockIter<'r, 's>), // FootnoteDefinition(FootnoteDefinitionIter<'r, 's>), @@ -141,6 +144,16 @@ impl<'r, 's> IntoIterator for &'r Heading<'s> { } children_iter!(Section<'s>, SectionIter, std::slice::Iter<'r, Element<'s>>); +children_iter!( + Paragraph<'s>, + ParagraphIter, + std::slice::Iter<'r, Object<'s>> +); +children_iter!( + PlainList<'s>, + PlainListIter, + std::slice::Iter<'r, PlainListItem<'s>> +); children_iter!(Bold<'s>, BoldIter, std::slice::Iter<'r, Object<'s>>); children_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); children_iter!( diff --git a/src/iter/macros.rs b/src/iter/macros.rs index 07b36fe..c6f1901 100644 --- a/src/iter/macros.rs +++ b/src/iter/macros.rs @@ -1,3 +1,16 @@ +/// Write the implementation of From<> to convert a borrow of the type to an AstNode +macro_rules! to_ast_node { + ($inp:ty, $enum:expr) => { + impl<'r, 's> From<$inp> for AstNode<'r, 's> { + fn from(value: $inp) -> Self { + $enum(value) + } + } + }; +} + +pub(crate) use to_ast_node; + /// Create iterators for ast nodes where it only has to iterate over children macro_rules! children_iter { ($astnodetype:ty, $itertype:ident, $innertype:ty) => { From 32a7ce3f361c7ae00d950b42921790eb36de69d5 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 18:27:52 -0400 Subject: [PATCH 12/18] Implement a macro for iterators with multiple fields. --- src/iter/ast_node_iter.rs | 11 +++++++++++ src/iter/macros.rs | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index aa7adcd..1c08490 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -3,6 +3,7 @@ use std::marker::PhantomData; use super::ast_node::AstNode; use super::macros::children_iter; use super::macros::empty_iter; +use super::macros::multi_field_iter; use crate::types::Bold; use crate::types::Code; use crate::types::Document; @@ -35,6 +36,7 @@ pub enum AstNodeIter<'r, 's> { // Elements Paragraph(ParagraphIter<'r, 's>), PlainList(PlainListIter<'r, 's>), + PlainListItem(PlainListItemIter<'r, 's>), // GreaterBlock(GreaterBlockIter<'r, 's>), // DynamicBlock(DynamicBlockIter<'r, 's>), // FootnoteDefinition(FootnoteDefinitionIter<'r, 's>), @@ -154,6 +156,15 @@ children_iter!( PlainListIter, std::slice::Iter<'r, PlainListItem<'s>> ); + +multi_field_iter!( + PlainListItem<'s>, + PlainListItemIter, + tag, + std::slice::Iter<'r, Object<'s>>, + children, + std::slice::Iter<'r, Element<'s>> +); children_iter!(Bold<'s>, BoldIter, std::slice::Iter<'r, Object<'s>>); children_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); children_iter!( diff --git a/src/iter/macros.rs b/src/iter/macros.rs index c6f1901..3834d1b 100644 --- a/src/iter/macros.rs +++ b/src/iter/macros.rs @@ -72,3 +72,43 @@ macro_rules! empty_iter { } pub(crate) use empty_iter; + +/// Create iterators for ast nodes where it has to iterate over multiple child lists. +macro_rules! multi_field_iter { + ($astnodetype:ty, $itertype:ident, $firstfieldname: ident, $firstinnertype:ty, $($fieldname: ident, $innertype:ty),*) => { + pub struct $itertype<'r, 's> { + $firstfieldname: $firstinnertype, + $( +$fieldname: $innertype, +),* + } + + impl<'r, 's> Iterator for $itertype<'r, 's> { + type Item = AstNode<'r, 's>; + + fn next(&mut self) -> Option { + self.$firstfieldname.next().map(Into::::into) + $( +.or_else(|| self.$fieldname.next().map(Into::::into)) +),* + } + } + + impl<'r, 's> IntoIterator for &'r $astnodetype { + type Item = AstNode<'r, 's>; + + type IntoIter = $itertype<'r, 's>; + + fn into_iter(self) -> Self::IntoIter { + $itertype { + $firstfieldname: self.$firstfieldname.iter(), + $( +$fieldname: self.$fieldname.iter(), +),* + } + } + } + }; +} + +pub(crate) use multi_field_iter; From 95fa8344201acba126d5d5129318f6ea88b38f32 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 18:38:51 -0400 Subject: [PATCH 13/18] Switch to using the multi field macro for document and heading. --- src/iter/ast_node_iter.rs | 75 +++++++++------------------------------ 1 file changed, 16 insertions(+), 59 deletions(-) diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index 1c08490..1a633dd 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -87,64 +87,22 @@ pub enum AstNodeIter<'r, 's> { // Timestamp(TimestampIter<'r, 's>), } -pub struct DocumentIter<'r, 's> { - zeroth_section_next: std::option::Iter<'r, Section<'s>>, - children_next: std::slice::Iter<'r, Heading<'s>>, -} - -impl<'r, 's> Iterator for DocumentIter<'r, 's> { - type Item = AstNode<'r, 's>; - - fn next(&mut self) -> Option { - self.zeroth_section_next - .next() - .map(Into::::into) - .or_else(|| self.children_next.next().map(Into::::into)) - } -} - -impl<'r, 's> IntoIterator for &'r Document<'s> { - type Item = AstNode<'r, 's>; - - type IntoIter = DocumentIter<'r, 's>; - - fn into_iter(self) -> Self::IntoIter { - DocumentIter { - zeroth_section_next: self.zeroth_section.iter(), - children_next: self.children.iter(), - } - } -} - -pub struct HeadingIter<'r, 's> { - title_next: std::slice::Iter<'r, Object<'s>>, - children_next: std::slice::Iter<'r, DocumentElement<'s>>, -} - -impl<'r, 's> Iterator for HeadingIter<'r, 's> { - type Item = AstNode<'r, 's>; - - fn next(&mut self) -> Option { - self.title_next - .next() - .map(Into::::into) - .or_else(|| self.children_next.next().map(Into::::into)) - } -} - -impl<'r, 's> IntoIterator for &'r Heading<'s> { - type Item = AstNode<'r, 's>; - - type IntoIter = HeadingIter<'r, 's>; - - fn into_iter(self) -> Self::IntoIter { - HeadingIter { - title_next: self.title.iter(), - children_next: self.children.iter(), - } - } -} - +multi_field_iter!( + Document<'s>, + DocumentIter, + zeroth_section, + std::option::Iter<'r, Section<'s>>, + children, + std::slice::Iter<'r, Heading<'s>> +); +multi_field_iter!( + Heading<'s>, + HeadingIter, + title, + std::slice::Iter<'r, Object<'s>>, + children, + std::slice::Iter<'r, DocumentElement<'s>> +); children_iter!(Section<'s>, SectionIter, std::slice::Iter<'r, Element<'s>>); children_iter!( Paragraph<'s>, @@ -156,7 +114,6 @@ children_iter!( PlainListIter, std::slice::Iter<'r, PlainListItem<'s>> ); - multi_field_iter!( PlainListItem<'s>, PlainListItemIter, From c4ea3fbf8872f26853c365976874e0776896757c Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 18:55:50 -0400 Subject: [PATCH 14/18] Implement the rest of the elements. --- src/iter/ast_node.rs | 9 +++ src/iter/ast_node_iter.rs | 117 +++++++++++++++++++++++++++++++------- 2 files changed, 106 insertions(+), 20 deletions(-) diff --git a/src/iter/ast_node.rs b/src/iter/ast_node.rs index 579a26b..0efae5f 100644 --- a/src/iter/ast_node.rs +++ b/src/iter/ast_node.rs @@ -31,6 +31,7 @@ use crate::types::Keyword; use crate::types::LatexEnvironment; use crate::types::LatexFragment; use crate::types::LineBreak; +use crate::types::NodeProperty; use crate::types::Object; use crate::types::OrgMacro; use crate::types::Paragraph; @@ -50,6 +51,8 @@ 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; @@ -71,7 +74,9 @@ pub enum AstNode<'r, 's> { Comment(&'r Comment<'s>), Drawer(&'r Drawer<'s>), PropertyDrawer(&'r PropertyDrawer<'s>), + NodeProperty(&'r NodeProperty<'s>), Table(&'r Table<'s>), + TableRow(&'r TableRow<'s>), VerseBlock(&'r VerseBlock<'s>), CommentBlock(&'r CommentBlock<'s>), ExampleBlock(&'r ExampleBlock<'s>), @@ -112,6 +117,7 @@ pub enum AstNode<'r, 's> { StatisticsCookie(&'r StatisticsCookie<'s>), Subscript(&'r Subscript<'s>), Superscript(&'r Superscript<'s>), + TableCell(&'r TableCell<'s>), Timestamp(&'r Timestamp<'s>), } @@ -199,7 +205,9 @@ to_ast_node!(&'r FootnoteDefinition<'s>, AstNode::FootnoteDefinition); to_ast_node!(&'r Comment<'s>, AstNode::Comment); to_ast_node!(&'r Drawer<'s>, AstNode::Drawer); to_ast_node!(&'r PropertyDrawer<'s>, AstNode::PropertyDrawer); +to_ast_node!(&'r NodeProperty<'s>, AstNode::NodeProperty); to_ast_node!(&'r Table<'s>, AstNode::Table); +to_ast_node!(&'r TableRow<'s>, AstNode::TableRow); to_ast_node!(&'r VerseBlock<'s>, AstNode::VerseBlock); to_ast_node!(&'r CommentBlock<'s>, AstNode::CommentBlock); to_ast_node!(&'r ExampleBlock<'s>, AstNode::ExampleBlock); @@ -239,4 +247,5 @@ to_ast_node!(&'r Target<'s>, AstNode::Target); to_ast_node!(&'r StatisticsCookie<'s>, AstNode::StatisticsCookie); to_ast_node!(&'r Subscript<'s>, AstNode::Subscript); to_ast_node!(&'r Superscript<'s>, AstNode::Superscript); +to_ast_node!(&'r TableCell<'s>, AstNode::TableCell); to_ast_node!(&'r Timestamp<'s>, AstNode::Timestamp); diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index 1a633dd..fabe91d 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -4,24 +4,47 @@ use super::ast_node::AstNode; use super::macros::children_iter; use super::macros::empty_iter; use super::macros::multi_field_iter; +use crate::types::BabelCall; use crate::types::Bold; +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::ExampleBlock; +use crate::types::ExportBlock; +use crate::types::FixedWidthArea; +use crate::types::FootnoteDefinition; +use crate::types::GreaterBlock; use crate::types::Heading; +use crate::types::HorizontalRule; use crate::types::Italic; +use crate::types::Keyword; +use crate::types::LatexEnvironment; +use crate::types::NodeProperty; use crate::types::Object; use crate::types::Paragraph; 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::RegularLink; use crate::types::Section; +use crate::types::SrcBlock; use crate::types::StrikeThrough; +use crate::types::Table; +use crate::types::TableCell; +use crate::types::TableRow; use crate::types::Underline; use crate::types::Verbatim; +use crate::types::VerseBlock; /// Iterator over the AST nodes contained within the starting node. /// @@ -37,26 +60,28 @@ pub enum AstNodeIter<'r, 's> { Paragraph(ParagraphIter<'r, 's>), PlainList(PlainListIter<'r, 's>), PlainListItem(PlainListItemIter<'r, 's>), - // GreaterBlock(GreaterBlockIter<'r, 's>), - // DynamicBlock(DynamicBlockIter<'r, 's>), - // FootnoteDefinition(FootnoteDefinitionIter<'r, 's>), - // Comment(CommentIter<'r, 's>), - // Drawer(DrawerIter<'r, 's>), - // PropertyDrawer(PropertyDrawerIter<'r, 's>), - // Table(TableIter<'r, 's>), - // VerseBlock(VerseBlockIter<'r, 's>), - // CommentBlock(CommentBlockIter<'r, 's>), - // ExampleBlock(ExampleBlockIter<'r, 's>), - // ExportBlock(ExportBlockIter<'r, 's>), - // SrcBlock(SrcBlockIter<'r, 's>), - // Clock(ClockIter<'r, 's>), - // DiarySexp(DiarySexpIter<'r, 's>), - // Planning(PlanningIter<'r, 's>), - // FixedWidthArea(FixedWidthAreaIter<'r, 's>), - // HorizontalRule(HorizontalRuleIter<'r, 's>), - // Keyword(KeywordIter<'r, 's>), - // BabelCall(BabelCallIter<'r, 's>), - // LatexEnvironment(LatexEnvironmentIter<'r, 's>), + GreaterBlock(GreaterBlockIter<'r, 's>), + DynamicBlock(DynamicBlockIter<'r, 's>), + FootnoteDefinition(FootnoteDefinitionIter<'r, 's>), + Comment(CommentIter<'r, 's>), + Drawer(DrawerIter<'r, 's>), + PropertyDrawer(PropertyDrawerIter<'r, 's>), + NodeProperty(NodePropertyIter<'r, 's>), + Table(TableIter<'r, 's>), + TableRow(TableRowIter<'r, 's>), + VerseBlock(VerseBlockIter<'r, 's>), + CommentBlock(CommentBlockIter<'r, 's>), + ExampleBlock(ExampleBlockIter<'r, 's>), + ExportBlock(ExportBlockIter<'r, 's>), + SrcBlock(SrcBlockIter<'r, 's>), + Clock(ClockIter<'r, 's>), + DiarySexp(DiarySexpIter<'r, 's>), + Planning(PlanningIter<'r, 's>), + FixedWidthArea(FixedWidthAreaIter<'r, 's>), + HorizontalRule(HorizontalRuleIter<'r, 's>), + Keyword(KeywordIter<'r, 's>), + BabelCall(BabelCallIter<'r, 's>), + LatexEnvironment(LatexEnvironmentIter<'r, 's>), // Objects Bold(BoldIter<'r, 's>), Italic(ItalicIter<'r, 's>), @@ -84,6 +109,7 @@ pub enum AstNodeIter<'r, 's> { // StatisticsCookie(StatisticsCookieIter<'r, 's>), // Subscript(SubscriptIter<'r, 's>), // Superscript(SuperscriptIter<'r, 's>), + TableCell(TableCellIter<'r, 's>), // Timestamp(TimestampIter<'r, 's>), } @@ -122,6 +148,52 @@ multi_field_iter!( children, std::slice::Iter<'r, Element<'s>> ); +children_iter!( + GreaterBlock<'s>, + GreaterBlockIter, + std::slice::Iter<'r, Element<'s>> +); +children_iter!( + DynamicBlock<'s>, + DynamicBlockIter, + std::slice::Iter<'r, Element<'s>> +); +children_iter!( + FootnoteDefinition<'s>, + FootnoteDefinitionIter, + std::slice::Iter<'r, Element<'s>> +); +empty_iter!(Comment<'s>, CommentIter); +children_iter!(Drawer<'s>, DrawerIter, std::slice::Iter<'r, Element<'s>>); +children_iter!( + PropertyDrawer<'s>, + PropertyDrawerIter, + std::slice::Iter<'r, NodeProperty<'s>> +); +empty_iter!(NodeProperty<'s>, NodePropertyIter); +children_iter!(Table<'s>, TableIter, std::slice::Iter<'r, TableRow<'s>>); +children_iter!( + TableRow<'s>, + TableRowIter, + std::slice::Iter<'r, TableCell<'s>> +); +children_iter!( + VerseBlock<'s>, + VerseBlockIter, + std::slice::Iter<'r, Object<'s>> +); +empty_iter!(CommentBlock<'s>, CommentBlockIter); +empty_iter!(ExampleBlock<'s>, ExampleBlockIter); +empty_iter!(ExportBlock<'s>, ExportBlockIter); +empty_iter!(SrcBlock<'s>, SrcBlockIter); +empty_iter!(Clock<'s>, ClockIter); +empty_iter!(DiarySexp<'s>, DiarySexpIter); +empty_iter!(Planning<'s>, PlanningIter); +empty_iter!(FixedWidthArea<'s>, FixedWidthAreaIter); +empty_iter!(HorizontalRule<'s>, HorizontalRuleIter); +empty_iter!(Keyword<'s>, KeywordIter); +empty_iter!(BabelCall<'s>, BabelCallIter); +empty_iter!(LatexEnvironment<'s>, LatexEnvironmentIter); children_iter!(Bold<'s>, BoldIter, std::slice::Iter<'r, Object<'s>>); children_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); children_iter!( @@ -143,3 +215,8 @@ children_iter!( RadioLinkIter, std::slice::Iter<'r, Object<'s>> ); +children_iter!( + TableCell<'s>, + TableCellIter, + std::slice::Iter<'r, Object<'s>> +); From 875a50ae46c9e72e6b93c592072fe08751ee9971 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 19:02:33 -0400 Subject: [PATCH 15/18] Finish implementing AstNodeIter for all types. --- src/iter/ast_node_iter.rs | 81 ++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 18 deletions(-) diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index fabe91d..4866681 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -4,8 +4,11 @@ use super::ast_node::AstNode; use super::macros::children_iter; use super::macros::empty_iter; use super::macros::multi_field_iter; +use crate::types::AngleLink; use crate::types::BabelCall; use crate::types::Bold; +use crate::types::Citation; +use crate::types::CitationReference; use crate::types::Clock; use crate::types::Code; use crate::types::Comment; @@ -16,32 +19,47 @@ 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::NodeProperty; 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::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; @@ -92,25 +110,25 @@ pub enum AstNodeIter<'r, 's> { PlainText(PlainTextIter<'r, 's>), RegularLink(RegularLinkIter<'r, 's>), RadioLink(RadioLinkIter<'r, 's>), - // RadioTarget(RadioTargetIter<'r, 's>), - // PlainLink(PlainLinkIter<'r, 's>), - // AngleLink(AngleLinkIter<'r, 's>), - // OrgMacro(OrgMacroIter<'r, 's>), - // Entity(EntityIter<'r, 's>), - // LatexFragment(LatexFragmentIter<'r, 's>), - // ExportSnippet(ExportSnippetIter<'r, 's>), - // FootnoteReference(FootnoteReferenceIter<'r, 's>), - // Citation(CitationIter<'r, 's>), - // CitationReference(CitationReferenceIter<'r, 's>), - // InlineBabelCall(InlineBabelCallIter<'r, 's>), - // InlineSourceBlock(InlineSourceBlockIter<'r, 's>), - // LineBreak(LineBreakIter<'r, 's>), - // Target(TargetIter<'r, 's>), - // StatisticsCookie(StatisticsCookieIter<'r, 's>), - // Subscript(SubscriptIter<'r, 's>), - // Superscript(SuperscriptIter<'r, 's>), + RadioTarget(RadioTargetIter<'r, 's>), + PlainLink(PlainLinkIter<'r, 's>), + AngleLink(AngleLinkIter<'r, 's>), + OrgMacro(OrgMacroIter<'r, 's>), + Entity(EntityIter<'r, 's>), + LatexFragment(LatexFragmentIter<'r, 's>), + ExportSnippet(ExportSnippetIter<'r, 's>), + FootnoteReference(FootnoteReferenceIter<'r, 's>), + Citation(CitationIter<'r, 's>), + CitationReference(CitationReferenceIter<'r, 's>), + InlineBabelCall(InlineBabelCallIter<'r, 's>), + InlineSourceBlock(InlineSourceBlockIter<'r, 's>), + LineBreak(LineBreakIter<'r, 's>), + Target(TargetIter<'r, 's>), + StatisticsCookie(StatisticsCookieIter<'r, 's>), + Subscript(SubscriptIter<'r, 's>), + Superscript(SuperscriptIter<'r, 's>), TableCell(TableCellIter<'r, 's>), - // Timestamp(TimestampIter<'r, 's>), + Timestamp(TimestampIter<'r, 's>), } multi_field_iter!( @@ -215,8 +233,35 @@ children_iter!( RadioLinkIter, std::slice::Iter<'r, Object<'s>> ); +children_iter!( + RadioTarget<'s>, + RadioTargetIter, + std::slice::Iter<'r, Object<'s>> +); +empty_iter!(PlainLink<'s>, PlainLinkIter); +empty_iter!(AngleLink<'s>, AngleLinkIter); +empty_iter!(OrgMacro<'s>, OrgMacroIter); +empty_iter!(Entity<'s>, EntityIter); +empty_iter!(LatexFragment<'s>, LatexFragmentIter); +empty_iter!(ExportSnippet<'s>, ExportSnippetIter); +multi_field_iter!( + FootnoteReference<'s>, + FootnoteReferenceIter, + definition, + std::slice::Iter<'r, Object<'s>>, +); +empty_iter!(Citation<'s>, CitationIter); +empty_iter!(CitationReference<'s>, CitationReferenceIter); +empty_iter!(InlineBabelCall<'s>, InlineBabelCallIter); +empty_iter!(InlineSourceBlock<'s>, InlineSourceBlockIter); +empty_iter!(LineBreak<'s>, LineBreakIter); +empty_iter!(Target<'s>, TargetIter); +empty_iter!(StatisticsCookie<'s>, StatisticsCookieIter); +empty_iter!(Subscript<'s>, SubscriptIter); +empty_iter!(Superscript<'s>, SuperscriptIter); children_iter!( TableCell<'s>, TableCellIter, std::slice::Iter<'r, Object<'s>> ); +empty_iter!(Timestamp<'s>, TimestampIter); From 8784da5179e17c1d62052d01f0b180b1dcb72943 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 19:30:21 -0400 Subject: [PATCH 16/18] Implement all ast node iteration. --- src/iter/all_ast_node_iter.rs | 102 ++++++++++++++++++++++++++++++++++ src/iter/ast_node_iter.rs | 65 ++++++++++++++++++++++ src/iter/mod.rs | 1 + 3 files changed, 168 insertions(+) create mode 100644 src/iter/all_ast_node_iter.rs diff --git a/src/iter/all_ast_node_iter.rs b/src/iter/all_ast_node_iter.rs new file mode 100644 index 0000000..1598990 --- /dev/null +++ b/src/iter/all_ast_node_iter.rs @@ -0,0 +1,102 @@ +use std::collections::VecDeque; + +use super::ast_node::AstNode; +use super::ast_node_iter::AstNodeIter; + +pub struct AllAstNodeIter<'r, 's> { + root: Option>, + queue: VecDeque>, +} + +impl<'r, 's> Iterator for AllAstNodeIter<'r, 's> { + type Item = AstNode<'r, 's>; + + fn next(&mut self) -> Option { + if let Some(root) = self.root.take() { + self.queue.push_back(AstNodeIter::from_ast_node(&root)); + return Some(root); + } + while let Some(child) = self.queue.front_mut() { + let next_elem_this_iter = match child { + AstNodeIter::Document(ref mut i) => i.next(), + AstNodeIter::Heading(ref mut i) => i.next(), + AstNodeIter::Section(ref mut i) => i.next(), + AstNodeIter::Paragraph(ref mut i) => i.next(), + AstNodeIter::PlainList(ref mut i) => i.next(), + AstNodeIter::PlainListItem(ref mut i) => i.next(), + AstNodeIter::GreaterBlock(ref mut i) => i.next(), + AstNodeIter::DynamicBlock(ref mut i) => i.next(), + AstNodeIter::FootnoteDefinition(ref mut i) => i.next(), + AstNodeIter::Comment(ref mut i) => i.next(), + AstNodeIter::Drawer(ref mut i) => i.next(), + AstNodeIter::PropertyDrawer(ref mut i) => i.next(), + AstNodeIter::NodeProperty(ref mut i) => i.next(), + AstNodeIter::Table(ref mut i) => i.next(), + AstNodeIter::TableRow(ref mut i) => i.next(), + AstNodeIter::VerseBlock(ref mut i) => i.next(), + AstNodeIter::CommentBlock(ref mut i) => i.next(), + AstNodeIter::ExampleBlock(ref mut i) => i.next(), + AstNodeIter::ExportBlock(ref mut i) => i.next(), + AstNodeIter::SrcBlock(ref mut i) => i.next(), + AstNodeIter::Clock(ref mut i) => i.next(), + AstNodeIter::DiarySexp(ref mut i) => i.next(), + AstNodeIter::Planning(ref mut i) => i.next(), + AstNodeIter::FixedWidthArea(ref mut i) => i.next(), + AstNodeIter::HorizontalRule(ref mut i) => i.next(), + AstNodeIter::Keyword(ref mut i) => i.next(), + AstNodeIter::BabelCall(ref mut i) => i.next(), + AstNodeIter::LatexEnvironment(ref mut i) => i.next(), + AstNodeIter::Bold(ref mut i) => i.next(), + AstNodeIter::Italic(ref mut i) => i.next(), + AstNodeIter::Underline(ref mut i) => i.next(), + AstNodeIter::StrikeThrough(ref mut i) => i.next(), + AstNodeIter::Code(ref mut i) => i.next(), + AstNodeIter::Verbatim(ref mut i) => i.next(), + AstNodeIter::PlainText(ref mut i) => i.next(), + AstNodeIter::RegularLink(ref mut i) => i.next(), + AstNodeIter::RadioLink(ref mut i) => i.next(), + AstNodeIter::RadioTarget(ref mut i) => i.next(), + AstNodeIter::PlainLink(ref mut i) => i.next(), + AstNodeIter::AngleLink(ref mut i) => i.next(), + AstNodeIter::OrgMacro(ref mut i) => i.next(), + AstNodeIter::Entity(ref mut i) => i.next(), + AstNodeIter::LatexFragment(ref mut i) => i.next(), + AstNodeIter::ExportSnippet(ref mut i) => i.next(), + AstNodeIter::FootnoteReference(ref mut i) => i.next(), + AstNodeIter::Citation(ref mut i) => i.next(), + AstNodeIter::CitationReference(ref mut i) => i.next(), + AstNodeIter::InlineBabelCall(ref mut i) => i.next(), + AstNodeIter::InlineSourceBlock(ref mut i) => i.next(), + AstNodeIter::LineBreak(ref mut i) => i.next(), + AstNodeIter::Target(ref mut i) => i.next(), + AstNodeIter::StatisticsCookie(ref mut i) => i.next(), + AstNodeIter::Subscript(ref mut i) => i.next(), + AstNodeIter::Superscript(ref mut i) => i.next(), + AstNodeIter::TableCell(ref mut i) => i.next(), + AstNodeIter::Timestamp(ref mut i) => i.next(), + }; + if let Some(next_elem_this_iter) = next_elem_this_iter { + self.queue + .push_back(AstNodeIter::from_ast_node(&next_elem_this_iter)); + return Some(next_elem_this_iter); + } else { + self.queue.pop_front(); + } + } + + None + } +} + +impl<'r, 's> IntoIterator for AstNode<'r, 's> { + type Item = AstNode<'r, 's>; + + type IntoIter = AllAstNodeIter<'r, 's>; + + fn into_iter(self) -> Self::IntoIter { + AllAstNodeIter { + root: Some(self), + queue: VecDeque::new(), + } + } +} diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index 4866681..39bac09 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -131,6 +131,71 @@ pub enum AstNodeIter<'r, 's> { Timestamp(TimestampIter<'r, 's>), } +impl<'r, 's> AstNodeIter<'r, 's> { + pub fn from_ast_node(node: &AstNode<'r, 's>) -> AstNodeIter<'r, 's> { + match node { + AstNode::Document(inner) => AstNodeIter::Document(inner.into_iter()), + AstNode::Heading(inner) => AstNodeIter::Heading(inner.into_iter()), + AstNode::Section(inner) => AstNodeIter::Section(inner.into_iter()), + AstNode::Paragraph(inner) => AstNodeIter::Paragraph(inner.into_iter()), + AstNode::PlainList(inner) => AstNodeIter::PlainList(inner.into_iter()), + AstNode::PlainListItem(inner) => AstNodeIter::PlainListItem(inner.into_iter()), + AstNode::GreaterBlock(inner) => AstNodeIter::GreaterBlock(inner.into_iter()), + AstNode::DynamicBlock(inner) => AstNodeIter::DynamicBlock(inner.into_iter()), + AstNode::FootnoteDefinition(inner) => { + AstNodeIter::FootnoteDefinition(inner.into_iter()) + } + AstNode::Comment(inner) => AstNodeIter::Comment(inner.into_iter()), + AstNode::Drawer(inner) => AstNodeIter::Drawer(inner.into_iter()), + AstNode::PropertyDrawer(inner) => AstNodeIter::PropertyDrawer(inner.into_iter()), + AstNode::NodeProperty(inner) => AstNodeIter::NodeProperty(inner.into_iter()), + AstNode::Table(inner) => AstNodeIter::Table(inner.into_iter()), + AstNode::TableRow(inner) => AstNodeIter::TableRow(inner.into_iter()), + AstNode::VerseBlock(inner) => AstNodeIter::VerseBlock(inner.into_iter()), + AstNode::CommentBlock(inner) => AstNodeIter::CommentBlock(inner.into_iter()), + AstNode::ExampleBlock(inner) => AstNodeIter::ExampleBlock(inner.into_iter()), + AstNode::ExportBlock(inner) => AstNodeIter::ExportBlock(inner.into_iter()), + AstNode::SrcBlock(inner) => AstNodeIter::SrcBlock(inner.into_iter()), + AstNode::Clock(inner) => AstNodeIter::Clock(inner.into_iter()), + AstNode::DiarySexp(inner) => AstNodeIter::DiarySexp(inner.into_iter()), + AstNode::Planning(inner) => AstNodeIter::Planning(inner.into_iter()), + AstNode::FixedWidthArea(inner) => AstNodeIter::FixedWidthArea(inner.into_iter()), + AstNode::HorizontalRule(inner) => AstNodeIter::HorizontalRule(inner.into_iter()), + AstNode::Keyword(inner) => AstNodeIter::Keyword(inner.into_iter()), + AstNode::BabelCall(inner) => AstNodeIter::BabelCall(inner.into_iter()), + AstNode::LatexEnvironment(inner) => AstNodeIter::LatexEnvironment(inner.into_iter()), + AstNode::Bold(inner) => AstNodeIter::Bold(inner.into_iter()), + AstNode::Italic(inner) => AstNodeIter::Italic(inner.into_iter()), + AstNode::Underline(inner) => AstNodeIter::Underline(inner.into_iter()), + AstNode::StrikeThrough(inner) => AstNodeIter::StrikeThrough(inner.into_iter()), + AstNode::Code(inner) => AstNodeIter::Code(inner.into_iter()), + AstNode::Verbatim(inner) => AstNodeIter::Verbatim(inner.into_iter()), + AstNode::PlainText(inner) => AstNodeIter::PlainText(inner.into_iter()), + AstNode::RegularLink(inner) => AstNodeIter::RegularLink(inner.into_iter()), + AstNode::RadioLink(inner) => AstNodeIter::RadioLink(inner.into_iter()), + AstNode::RadioTarget(inner) => AstNodeIter::RadioTarget(inner.into_iter()), + AstNode::PlainLink(inner) => AstNodeIter::PlainLink(inner.into_iter()), + AstNode::AngleLink(inner) => AstNodeIter::AngleLink(inner.into_iter()), + AstNode::OrgMacro(inner) => AstNodeIter::OrgMacro(inner.into_iter()), + AstNode::Entity(inner) => AstNodeIter::Entity(inner.into_iter()), + AstNode::LatexFragment(inner) => AstNodeIter::LatexFragment(inner.into_iter()), + AstNode::ExportSnippet(inner) => AstNodeIter::ExportSnippet(inner.into_iter()), + AstNode::FootnoteReference(inner) => AstNodeIter::FootnoteReference(inner.into_iter()), + AstNode::Citation(inner) => AstNodeIter::Citation(inner.into_iter()), + AstNode::CitationReference(inner) => AstNodeIter::CitationReference(inner.into_iter()), + AstNode::InlineBabelCall(inner) => AstNodeIter::InlineBabelCall(inner.into_iter()), + AstNode::InlineSourceBlock(inner) => AstNodeIter::InlineSourceBlock(inner.into_iter()), + AstNode::LineBreak(inner) => AstNodeIter::LineBreak(inner.into_iter()), + AstNode::Target(inner) => AstNodeIter::Target(inner.into_iter()), + AstNode::StatisticsCookie(inner) => AstNodeIter::StatisticsCookie(inner.into_iter()), + AstNode::Subscript(inner) => AstNodeIter::Subscript(inner.into_iter()), + AstNode::Superscript(inner) => AstNodeIter::Superscript(inner.into_iter()), + AstNode::TableCell(inner) => AstNodeIter::TableCell(inner.into_iter()), + AstNode::Timestamp(inner) => AstNodeIter::Timestamp(inner.into_iter()), + } + } +} + multi_field_iter!( Document<'s>, DocumentIter, diff --git a/src/iter/mod.rs b/src/iter/mod.rs index b622d37..c380ada 100644 --- a/src/iter/mod.rs +++ b/src/iter/mod.rs @@ -1,3 +1,4 @@ +mod all_ast_node_iter; mod ast_node; mod ast_node_iter; mod macros; From 9ce042d5b68ac6d20e6d9ea8276fb2c3467527bf Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 19:36:23 -0400 Subject: [PATCH 17/18] Replace old iteration with new iteration. --- src/iter/ast_node_iter.rs | 4 ++-- src/iter/mod.rs | 1 + src/parser/document.rs | 18 +++++++++--------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/iter/ast_node_iter.rs b/src/iter/ast_node_iter.rs index 39bac09..6c51c11 100644 --- a/src/iter/ast_node_iter.rs +++ b/src/iter/ast_node_iter.rs @@ -69,7 +69,7 @@ use crate::types::VerseBlock; /// This only iterates over the children, not the starting node itself. So an AstNodeIter::PlainList would only return PlainListItems, not the PlainList. /// /// This only iterates over AST nodes, so an AstNodeIter::Heading would iterate over both the title and section contents, but it would not iterate over simple strings like the TODO keyword or priority. -pub enum AstNodeIter<'r, 's> { +pub(crate) enum AstNodeIter<'r, 's> { // Document Nodes Document(DocumentIter<'r, 's>), Heading(HeadingIter<'r, 's>), @@ -132,7 +132,7 @@ pub enum AstNodeIter<'r, 's> { } impl<'r, 's> AstNodeIter<'r, 's> { - pub fn from_ast_node(node: &AstNode<'r, 's>) -> AstNodeIter<'r, 's> { + pub(crate) fn from_ast_node(node: &AstNode<'r, 's>) -> AstNodeIter<'r, 's> { match node { AstNode::Document(inner) => AstNodeIter::Document(inner.into_iter()), AstNode::Heading(inner) => AstNodeIter::Heading(inner.into_iter()), diff --git a/src/iter/mod.rs b/src/iter/mod.rs index c380ada..d820847 100644 --- a/src/iter/mod.rs +++ b/src/iter/mod.rs @@ -2,3 +2,4 @@ mod all_ast_node_iter; mod ast_node; mod ast_node_iter; mod macros; +pub(crate) use ast_node::AstNode; diff --git a/src/parser/document.rs b/src/parser/document.rs index 9c26a41..11582c5 100644 --- a/src/parser/document.rs +++ b/src/parser/document.rs @@ -19,6 +19,7 @@ use crate::context::RefContext; use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; +use crate::iter::AstNode; use crate::parser::org_source::convert_error; use crate::parser::util::blank_line; use crate::types::Document; @@ -111,15 +112,14 @@ fn document_org_source<'b, 'g, 'r, 's>( _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 - .iter_tokens() - .filter_map(|tkn| match tkn { - Token::Object(obj) => Some(obj), - _ => None, - }) - .filter_map(|obj| match obj { - Object::RadioTarget(rt) => Some(rt), - _ => None, + let all_radio_targets: Vec<&Vec>> = Into::::into(&document) + .into_iter() + .filter_map(|ast_node| { + if let AstNode::RadioTarget(ast_node) = ast_node { + Some(ast_node) + } else { + None + } }) .map(|rt| &rt.children) .collect(); From 48d550e1fcf0cc969f8753b54eb658e9e0405aaa Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Wed, 27 Sep 2023 19:45:40 -0400 Subject: [PATCH 18/18] Remove old implementation of iteration. --- src/parser/document.rs | 8 --- src/parser/mod.rs | 1 - src/parser/token.rs | 135 ----------------------------------------- 3 files changed, 144 deletions(-) delete mode 100644 src/parser/token.rs diff --git a/src/parser/document.rs b/src/parser/document.rs index 11582c5..4d6a64b 100644 --- a/src/parser/document.rs +++ b/src/parser/document.rs @@ -7,8 +7,6 @@ use super::in_buffer_settings::apply_in_buffer_settings; use super::in_buffer_settings::scan_for_in_buffer_settings; use super::org_source::OrgSource; use super::section::zeroth_section; -use super::token::AllTokensIterator; -use super::token::Token; use super::util::get_consumed; use crate::context::parser_with_context; use crate::context::Context; @@ -155,9 +153,3 @@ fn _document<'b, 'g, 'r, 's>( }, )) } - -impl<'s> Document<'s> { - fn iter_tokens<'r>(&'r self) -> impl Iterator> { - AllTokensIterator::new(Token::Document(self)) - } -} diff --git a/src/parser/mod.rs b/src/parser/mod.rs index b19f9ca..8729294 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -43,7 +43,6 @@ mod table; mod target; mod text_markup; mod timestamp; -mod token; mod util; pub use document::parse; pub use document::parse_with_settings; diff --git a/src/parser/token.rs b/src/parser/token.rs deleted file mode 100644 index 8479273..0000000 --- a/src/parser/token.rs +++ /dev/null @@ -1,135 +0,0 @@ -use std::collections::VecDeque; - -use crate::types::Document; -use crate::types::DocumentElement; -use crate::types::Element; -use crate::types::Heading; -use crate::types::NodeProperty; -use crate::types::Object; -use crate::types::PlainListItem; -use crate::types::Section; -use crate::types::TableCell; -use crate::types::TableRow; - -pub(crate) enum Token<'r, 's> { - Document(&'r Document<'s>), - Heading(&'r Heading<'s>), - Section(&'r Section<'s>), - Object(&'r Object<'s>), - Element(&'r Element<'s>), - PlainListItem(&'r PlainListItem<'s>), - TableRow(&'r TableRow<'s>), - TableCell(&'r TableCell<'s>), - NodeProperty(&'r NodeProperty<'s>), -} - -impl<'r, 's> Token<'r, 's> { - fn iter_tokens(&self) -> Box> + '_> { - match self { - Token::Document(document) => Box::new( - document - .zeroth_section - .iter() - .map(Token::Section) - .chain(document.children.iter().map(Token::Heading)), - ), - Token::Heading(heading) => Box::new(heading.title.iter().map(Token::Object).chain( - heading.children.iter().map(|de| match de { - DocumentElement::Heading(ref obj) => Token::Heading(obj), - DocumentElement::Section(ref obj) => Token::Section(obj), - }), - )), - Token::Section(section) => Box::new(section.children.iter().map(Token::Element)), - Token::Object(obj) => match obj { - Object::Bold(inner) => Box::new(inner.children.iter().map(Token::Object)), - Object::Italic(inner) => Box::new(inner.children.iter().map(Token::Object)), - Object::Underline(inner) => Box::new(inner.children.iter().map(Token::Object)), - Object::StrikeThrough(inner) => Box::new(inner.children.iter().map(Token::Object)), - Object::Code(_) => Box::new(std::iter::empty()), - Object::Verbatim(_) => Box::new(std::iter::empty()), - Object::PlainText(_) => Box::new(std::iter::empty()), - Object::RegularLink(_) => Box::new(std::iter::empty()), - Object::RadioLink(inner) => Box::new(inner.children.iter().map(Token::Object)), - Object::RadioTarget(inner) => Box::new(inner.children.iter().map(Token::Object)), - Object::PlainLink(_) => Box::new(std::iter::empty()), - Object::AngleLink(_) => Box::new(std::iter::empty()), - Object::OrgMacro(_) => Box::new(std::iter::empty()), - Object::Entity(_) => Box::new(std::iter::empty()), - Object::LatexFragment(_) => Box::new(std::iter::empty()), - Object::ExportSnippet(_) => Box::new(std::iter::empty()), - Object::FootnoteReference(inner) => { - Box::new(inner.definition.iter().map(Token::Object)) - } - Object::Citation(_) => Box::new(std::iter::empty()), // TODO: Iterate over children - Object::CitationReference(_) => Box::new(std::iter::empty()), // TODO: Iterate over children - Object::InlineBabelCall(_) => Box::new(std::iter::empty()), - Object::InlineSourceBlock(_) => Box::new(std::iter::empty()), - Object::LineBreak(_) => Box::new(std::iter::empty()), - Object::Target(_) => Box::new(std::iter::empty()), - Object::StatisticsCookie(_) => Box::new(std::iter::empty()), - Object::Subscript(_) => Box::new(std::iter::empty()), // TODO: Iterate over children - Object::Superscript(_) => Box::new(std::iter::empty()), // TODO: Iterate over children - Object::Timestamp(_) => Box::new(std::iter::empty()), - }, - Token::Element(elem) => match elem { - Element::Paragraph(inner) => Box::new(inner.children.iter().map(Token::Object)), - Element::PlainList(inner) => { - Box::new(inner.children.iter().map(Token::PlainListItem)) - } - Element::GreaterBlock(inner) => Box::new(inner.children.iter().map(Token::Element)), - Element::DynamicBlock(inner) => Box::new(inner.children.iter().map(Token::Element)), - Element::FootnoteDefinition(inner) => { - Box::new(inner.children.iter().map(Token::Element)) - } - Element::Comment(_) => Box::new(std::iter::empty()), - Element::Drawer(inner) => Box::new(inner.children.iter().map(Token::Element)), - Element::PropertyDrawer(inner) => { - Box::new(inner.children.iter().map(Token::NodeProperty)) - } - Element::Table(inner) => Box::new(inner.children.iter().map(Token::TableRow)), - Element::VerseBlock(inner) => Box::new(inner.children.iter().map(Token::Object)), - Element::CommentBlock(_) => Box::new(std::iter::empty()), - Element::ExampleBlock(_) => Box::new(std::iter::empty()), - Element::ExportBlock(_) => Box::new(std::iter::empty()), - Element::SrcBlock(_) => Box::new(std::iter::empty()), - Element::Clock(_) => Box::new(std::iter::empty()), - Element::DiarySexp(_) => Box::new(std::iter::empty()), - Element::Planning(_) => Box::new(std::iter::empty()), - Element::FixedWidthArea(_) => Box::new(std::iter::empty()), - Element::HorizontalRule(_) => Box::new(std::iter::empty()), - Element::Keyword(_) => Box::new(std::iter::empty()), - Element::BabelCall(_) => Box::new(std::iter::empty()), - Element::LatexEnvironment(_) => Box::new(std::iter::empty()), - }, - Token::PlainListItem(elem) => Box::new(elem.children.iter().map(Token::Element)), - Token::TableRow(elem) => Box::new(elem.children.iter().map(Token::TableCell)), - Token::TableCell(elem) => Box::new(elem.children.iter().map(Token::Object)), - Token::NodeProperty(_) => Box::new(std::iter::empty()), - } - } -} - -pub(crate) struct AllTokensIterator<'r, 's> { - queued_tokens: VecDeque>, -} - -impl<'r, 's> AllTokensIterator<'r, 's> { - pub(crate) fn new(tkn: Token<'r, 's>) -> Self { - let mut queued_tokens = VecDeque::new(); - queued_tokens.push_back(tkn); - AllTokensIterator { queued_tokens } - } -} - -impl<'r, 's> Iterator for AllTokensIterator<'r, 's> { - type Item = Token<'r, 's>; - - fn next(&mut self) -> Option { - let next_token = match self.queued_tokens.pop_front() { - Some(tkn) => tkn, - None => return None, - }; - self.queued_tokens.extend(next_token.iter_tokens()); - Some(next_token) - } -}