1use pom::parser::*;
2
3#[derive(Clone, Debug, PartialEq)]
4struct Container {
5 containers: Vec<Container>,
6 contents: Vec<String>,
7}
8
9enum TmpContainerOrContent {
10 Container(Container),
11 Content(String),
12}
13
14fn whitespace<'a>() -> Parser<'a, u8, ()> {
15 one_of(b" \t\r\n").repeat(0..).discard()
16}
17
18fn linebreak<'a>() -> Parser<'a, u8, ()> {
19 sym(b'\r').opt() * sym(b'\n').discard()
20}
21
22fn indented<'a>() -> Parser<'a, u8, Vec<u8>> {
23 sym(b'\t') * none_of(b"\n\r").repeat(1..) - linebreak()
24}
25
26fn empty<'a>() -> Parser<'a, u8, ()> {
27 one_of(b" \t").repeat(0..).discard() - linebreak()
28}
29
30fn content<'a>() -> Parser<'a, u8, String> {
31 none_of(b" \t\r\n").repeat(1..).convert(String::from_utf8) - linebreak()
32}
33
34fn subcontainer<'a>() -> Parser<'a, u8, (Vec<Container>, Vec<String>)> {
35 (
36 call(container).map(|ctr| TmpContainerOrContent::Container(ctr)) |
37 content().map(|ctn| TmpContainerOrContent::Content(ctn))
38 ).repeat(1..).map(
39 |tmp| {
40 tmp.into_iter().fold(
41 (vec![], vec![]),
42 |acc, x| match x {
43 TmpContainerOrContent::Container(ct) => (
44 acc.0.into_iter().chain(vec![ct].into_iter()).collect(),
45 acc.1,
46 ),
47 TmpContainerOrContent::Content(cn) => (
48 acc.0,
49 acc.1.into_iter().chain(vec![cn].into_iter()).collect(),
50 ),
51 }
52 )
53 }
54 )
55}
56
57fn container<'a>() -> Parser<'a, u8, Container> {
58 seq(b"Container\n") *
59 (
60 indented() |
61 empty().map(|()| vec![])
62 ).repeat(1..).map(
63 |lines| lines.into_iter().filter(
64 |line| line.len() > 0
65 ).fold(
66 vec![],
67 |accum, line| accum.into_iter().chain(
68 line.into_iter().chain(vec![b'\n'].into_iter())
69 ).collect()
70 )
71 ).map(|deden| {
72 subcontainer().parse(&deden).expect("subcont")
73 }).map(|(containers, contents)| Container { containers, contents })
74}
75
76fn mylang<'a>() -> Parser<'a, u8, Vec<Container>> {
77 (
78 whitespace() *
79 list(
80 call(container),
81 whitespace()
82 )
83 )
84}
85
86fn main() -> Result<(), ()> {
87 let input = br#"
88Container
89 Container
90 a
91 b
92 c
93
94 1
95 2
96 3
97
98 Container
99 q
100
101Container
102 foo
103 bar
104
105 Container
106 baz
107 quux
108 "#;
109
110 assert_eq!(
111 mylang().parse(input),
112 Ok(
113 vec![
114 Container {
115 containers: vec![
116 Container {
117 containers: vec![],
118 contents: vec![
119 "a".into(),
120 "b".into(),
121 "c".into(),
122 ]
123 },
124 Container {
125 containers: vec![],
126 contents: vec![
127 "q".into(),
128 ]
129 }
130 ],
131 contents: vec![
132 "1".into(),
133 "2".into(),
134 "3".into(),
135 ]
136 },
137 Container {
138 containers: vec![
139 Container {
140 contents: vec![
141 "baz".into(),
142 "quux".into(),
143 ],
144 containers: vec![],
145 },
146 ],
147 contents: vec![
148 "foo".into(),
149 "bar".into(),
150 ]
151 },
152 ]
153 )
154 );
155
156 Ok(())
157}