From 54f5e9fd883e207931baa9c87b6181ca724d6bab Mon Sep 17 00:00:00 2001 From: Ben Bridle Date: Thu, 25 Aug 2022 21:09:25 +1200 Subject: Initial commit --- src/parse_heirarchical.rs | 137 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 src/parse_heirarchical.rs (limited to 'src/parse_heirarchical.rs') diff --git a/src/parse_heirarchical.rs b/src/parse_heirarchical.rs new file mode 100644 index 0000000..75c2bec --- /dev/null +++ b/src/parse_heirarchical.rs @@ -0,0 +1,137 @@ +use crate::*; + +macro_rules! get_subsection { + ($t:ident) => { + pub fn get_subsection(&self, name: &str) -> Option<&$t> { + for section in &self.sections { + if line_to_string(§ion.title) == name { + return Some(section); + } + } + return None; + } + }; +} + +#[derive(Default)] +pub struct Document { + pub preamble: Vec, + pub sections: Vec, +} +impl Document { + get_subsection! {TopLevelSection} +} + +#[derive(Default)] +pub struct TopLevelSection { + pub title: Line, + pub content: Vec, + pub sections: Vec, +} +impl TopLevelSection { + get_subsection! {MidLevelSection} +} + +#[derive(Default)] +pub struct MidLevelSection { + pub title: Line, + pub content: Vec, + pub sections: Vec, +} +impl MidLevelSection { + get_subsection! {LowLevelSection} +} + +#[derive(Default)] +pub struct LowLevelSection { + pub title: Line, + pub content: Vec, +} + +pub fn parse_heirarchical(markdown: &str) -> Result { + macro_rules! push_section { + ($from:ident => $to:ident) => { + $to.sections.push(std::mem::take(&mut $from)) + }; + } + let mut document = Document::default(); + let mut h1_buffer = TopLevelSection::default(); + let mut h2_buffer = MidLevelSection::default(); + let mut h3_buffer = LowLevelSection::default(); + let mut level = 0; + + let blocks = parse(markdown); + for block in blocks { + match (level, block) { + (0, Block::Heading1(title)) => { + h1_buffer.title = title; + level = 1; + } + (0, Block::Heading2(_)) => return Err(()), + (0, Block::Heading3(_)) => return Err(()), + (0, block) => document.preamble.push(block), + (1, Block::Heading1(title)) => { + push_section!(h1_buffer => document); + h1_buffer.title = title; + } + (1, Block::Heading2(title)) => { + h2_buffer.title = title; + level = 2; + } + (1, Block::Heading3(_)) => return Err(()), + (1, block) => h1_buffer.content.push(block), + (2, Block::Heading1(title)) => { + push_section!(h2_buffer => h1_buffer); + push_section!(h1_buffer => document); + h1_buffer.title = title; + level = 1; + } + (2, Block::Heading2(title)) => { + push_section!(h2_buffer => h1_buffer); + h2_buffer.title = title; + } + (2, Block::Heading3(title)) => { + h3_buffer.title = title; + level = 3; + } + (2, block) => h2_buffer.content.push(block), + (3, Block::Heading1(title)) => { + push_section!(h3_buffer => h2_buffer); + push_section!(h2_buffer => h1_buffer); + push_section!(h1_buffer => document); + h1_buffer.title = title; + level = 1; + } + (3, Block::Heading2(title)) => { + push_section!(h3_buffer => h2_buffer); + push_section!(h2_buffer => h1_buffer); + h2_buffer.title = title; + level = 2; + } + (3, Block::Heading3(title)) => { + push_section!(h3_buffer => h2_buffer); + h3_buffer.title = title; + } + (3, block) => h3_buffer.content.push(block), + _ => unreachable!(), + } + } + + // Push all in-progress sections + match level { + 3 => { + push_section!(h3_buffer => h2_buffer); + push_section!(h2_buffer => h1_buffer); + push_section!(h1_buffer => document); + } + 2 => { + push_section!(h2_buffer => h1_buffer); + push_section!(h1_buffer => document); + } + 1 => { + push_section!(h1_buffer => document); + } + _ => (), + } + Ok(document) +} -- cgit v1.2.3-70-g09d2