Start work on parser
This commit is contained in:
parent
bff5ee3fcd
commit
76cf5e496c
115
src/lib.rs
115
src/lib.rs
|
@ -81,20 +81,117 @@ pub struct List {}
|
||||||
|
|
||||||
pub fn parse(source: &str) -> Document {
|
pub fn parse(source: &str) -> Document {
|
||||||
let lines = source.lines().collect::<Vec<_>>();
|
let lines = source.lines().collect::<Vec<_>>();
|
||||||
let mut document = vec![];
|
let mut document = Vec::new();
|
||||||
let mut paragraph = vec![];
|
|
||||||
|
|
||||||
for line in lines {
|
let mut to_parse = &lines[..];
|
||||||
if line.starts_with('#') {
|
while let Some((node, remaining)) = parse_node(to_parse) {
|
||||||
todo!()
|
document.push(node);
|
||||||
} else if line.is_empty() {
|
to_parse = &to_parse[remaining..];
|
||||||
document.push(paragraph.join(" "));
|
}
|
||||||
|
|
||||||
|
Document(document)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a single node from the list of lines, if one exists. Return
|
||||||
|
/// the node parsed, and the number of lines of input consumed.
|
||||||
|
fn parse_node(mut lines: &[&str]) -> Option<(Node, usize)> {
|
||||||
|
if lines.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
while lines[0].is_empty() {
|
||||||
|
lines = &lines[1..];
|
||||||
|
if lines.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None.or_else(|| parse_normal_header(lines))
|
||||||
|
.or_else(|| parse_underline_header(lines))
|
||||||
|
.or_else(|| parse_hrule(lines))
|
||||||
|
.or_else(|| parse_paragraph(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a header as a number of "#"-signs followed by the header
|
||||||
|
/// text.
|
||||||
|
fn parse_normal_header(lines: &[&str]) -> Option<(Node, usize)> {
|
||||||
|
if lines[0].starts_with('#') {
|
||||||
|
let depth = lines[0].chars().take_while(|&c| c == '#').count();
|
||||||
|
let text = lines[0][depth..].trim().to_string();
|
||||||
|
Some((
|
||||||
|
Node::Header(Header {
|
||||||
|
label: text,
|
||||||
|
level: depth as u8,
|
||||||
|
}),
|
||||||
|
1,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
paragraph.push(line);
|
None
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a header as a single line of text followed by an underline,
|
||||||
|
/// i.e. a line of "-" or "=" characters.
|
||||||
|
fn parse_underline_header(lines: &[&str]) -> Option<(Node, usize)> {
|
||||||
|
if lines.len() < 2 {
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
todo!()
|
let text = lines[0];
|
||||||
|
let underline = lines[1];
|
||||||
|
if !text.is_empty() && !underline.is_empty() {
|
||||||
|
if underline.chars().all(|c| c == '-') {
|
||||||
|
Some((
|
||||||
|
Node::Header(Header {
|
||||||
|
label: text.to_string(),
|
||||||
|
level: 2,
|
||||||
|
}),
|
||||||
|
2,
|
||||||
|
))
|
||||||
|
} else if underline.chars().all(|c| c == '=') {
|
||||||
|
Some((
|
||||||
|
Node::Header(Header {
|
||||||
|
label: text.to_string(),
|
||||||
|
level: 1,
|
||||||
|
}),
|
||||||
|
2,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a horizontal rule.
|
||||||
|
fn parse_hrule(lines: &[&str]) -> Option<(Node, usize)> {
|
||||||
|
let line = lines[0];
|
||||||
|
if !line.is_empty() && (line.chars().all(|c| c == '-') || line.chars().all(|c| c == '=')) {
|
||||||
|
Some((Node::HRule, 1))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a paragraph of text.
|
||||||
|
fn parse_paragraph(lines: &[&str]) -> Option<(Node, usize)> {
|
||||||
|
let len = lines.iter().take_while(|line| !line.is_empty()).count();
|
||||||
|
let text = lines[0..len].join(" ");
|
||||||
|
|
||||||
|
// TODO: Parse style components from `text` here, and turn it into
|
||||||
|
// a Vec<StyledText>.
|
||||||
|
|
||||||
|
Some((
|
||||||
|
Node::Paragraph(vec![StyledText {
|
||||||
|
italic: false,
|
||||||
|
bold: false,
|
||||||
|
underline: false,
|
||||||
|
color: None,
|
||||||
|
text,
|
||||||
|
}]),
|
||||||
|
len,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Reference in a new issue