1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use super::{Document, Section};
use log::debug;
use regex::Regex;
use std::convert::TryInto;
use std::fs::File;
use std::io::{prelude::*, BufReader, Result};
pub struct Parser {
re: Regex,
document: Document,
current: Option<usize>,
}
impl Parser {
pub fn new() -> Parser {
Parser {
re: Regex::new(r"^(#{1,6}) (.*)$").unwrap(),
document: Document::new(),
current: None,
}
}
pub fn parse_file(&mut self, file: File) -> Result<Document> {
let reader = BufReader::new(file);
for line in reader.lines() {
let line = line.unwrap();
self.parse_line(line);
}
Ok(self.document.clone())
}
fn parse_line(&mut self, line: String) {
let caps = match self.re.captures(&line) {
Some(caps) => caps,
None => {
if let Some(current) = self.current {
self.document[current].append_to_body(line);
}
return;
}
};
let mut new_section = Section::new();
new_section.level = caps[1].len().try_into().unwrap();
new_section.title = (&caps[2]).to_string();
let index = self.document.len();
self.find_home(&mut new_section, index);
self.document.push(new_section);
}
fn find_home(&mut self, section: &mut Section, index: usize) {
let current_index = match self.current {
Some(current) => current,
None => {
debug!("Found initial section");
self.current = Some(index);
return;
}
};
let current = &mut self.document[current_index];
if current.level < section.level {
debug!("Found child section");
section.parent = Some(current_index);
current.add_child(index);
self.current = Some(index);
} else if current.level == section.level {
debug!("Found adjacent section");
self.current = Some(index);
section.parent = current.parent;
if let Some(parent) = section.parent {
self.document[parent].add_child(index);
}
} else {
debug!("Found ancestor section. Climbing...");
self.current = current.parent;
self.find_home(section, index);
}
}
}