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
100
101
102
103
104
mod list;
mod util;
mod token;
pub use util::*;
pub use list::*;
use nom::{
branch::alt,
bytes::complete::{tag, take},
combinator::{recognize, opt, map},
multi::{many0, many1, many1_count},
sequence::{terminated, pair},
character::complete::line_ending,
};
use nom::IResult;
use nom::error::ErrorKind;
pub fn format_text(s: &str) -> String {
let r: IResult<&str, String> = map(
many0(
alt((
map(
many1(alt((line_ending, tag("\t")))),
|_| " "
),
take(1u8)
))
),
|v: Vec<&str>| v.join("")
)(s);
r.expect("format_text cannot fail").1
}
#[derive(Debug, Clone)]
pub enum Block {
Heading(usize, String),
Paragraph(String),
List(List),
}
fn end(input: &str) -> IResult<&str, &str> {
recognize(pair(line_ending, line_ending))(input)
}
fn block_text(input: &str) -> IResult<&str, String> {
map(
terminated(
take_until_match(end),
opt(end)
),
|s: &str| s.to_string()
)(input)
}
fn parse_block_heading(input: &str) -> IResult<&str, Block> {
map(
pair(
terminated(
many1_count(tag("#")),
tag(" ")
),
block_text
),
|(level, s)| Block::Heading(level, s)
)(input)
}
fn parse_block_paragraph(input: &str) -> IResult<&str, Block> {
map(
block_text,
|s| Block::Paragraph(format_text(&s))
)(input)
}
fn parse_block_list(input: &str) -> IResult<&str, Block> {
map(
parse_list(0),
|l| Block::List(l)
)(input)
}
fn parse_block(input: &str) -> IResult<&str, Block> {
alt((
parse_block_heading,
parse_block_list,
parse_block_paragraph,
))(input)
}
pub struct Document {
pub blocks: Vec<Block>
}
pub fn parse(input: &str) -> Result<Document, nom::Err<(&str, ErrorKind)>> {
many0(
parse_block
)(input)
.map(|(_, blocks)| Document { blocks })
}