use std::collections::VecDeque; use super::Document; use super::Element; use super::Heading; use super::Object; use super::PlainListItem; use super::Section; use super::TableCell; use super::TableRow; use crate::parser::DocumentElement; pub 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>), } impl<'r, 's> Token<'r, 's> { pub 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)) } }, 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(_) => Box::new(std::iter::empty()), 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::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)), } } } pub struct AllTokensIterator<'r, 's> { queued_tokens: VecDeque>, } impl<'r, 's> AllTokensIterator<'r, 's> { pub 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) } }