1use crate::ast::*;
2use pest::{iterators::Pair, Parser};
3use std::collections::HashMap;
4
5pub fn parse(content: &str) -> Result<Ast, String> {
6 let program = match AstParser::parse(Rule::program, content) {
7 Ok(mut pairs) => pairs.next().unwrap(),
8 Err(error) => return Err(format!("{:#?}", error)),
9 };
10 let mut ast = Ast::default();
11 for pair in program.into_inner() {
12 match pair.as_rule() {
13 Rule::import_elm => ast.imports.push(parse_import(pair)),
14 Rule::inject_elm => ast.injects.push(parse_inject(pair)),
15 Rule::replace_elm => ast.replacements.push(parse_replace(pair)),
16 Rule::extern_elm => ast.externs.push(parse_extern(pair)),
17 Rule::struct_elm => ast.structs.push(parse_struct(pair)),
18 Rule::enum_elm => ast.enums.push(parse_enum(pair)),
19 Rule::impl_elm => ast.implementations.push(parse_implementation(pair)),
20 Rule::EOI => {}
21 _ => panic!("{:?}", pair.as_rule()),
22 }
23 }
24 Ok(ast)
25}
26
27fn parse_import(pair: Pair<Rule>) -> String {
28 parse_string(pair.into_inner().next().unwrap())
29}
30
31fn parse_inject(pair: Pair<Rule>) -> AstCode {
32 parse_code(pair.into_inner().next().unwrap())
33}
34
35fn parse_replace(pair: Pair<Rule>) -> AstReplace {
36 let mut pairs = pair.into_inner();
37 let pattern = parse_string(pairs.next().unwrap()).replace("\\\\", "\\");
38 let template = parse_code(pairs.next().unwrap());
39 AstReplace { pattern, template }
40}
41
42fn parse_extern(pair: Pair<Rule>) -> AstExtern {
43 let mut pairs = pair.into_inner();
44 let types = parse_extern_types(pairs.next().unwrap());
45 let implementations = parse_extern_implementations(pairs.next().unwrap());
46 AstExtern {
47 types,
48 implementations,
49 }
50}
51
52fn parse_extern_types(pair: Pair<Rule>) -> Vec<String> {
53 pair.into_inner().map(parse_string).collect::<Vec<_>>()
54}
55
56fn parse_extern_implementations(pair: Pair<Rule>) -> Vec<(String, AstCode)> {
57 pair.into_inner()
58 .map(parse_extern_implementation)
59 .collect::<Vec<_>>()
60}
61
62fn parse_extern_implementation(pair: Pair<Rule>) -> (String, AstCode) {
63 let mut pairs = pair.into_inner();
64 let identifier = parse_identifier(pairs.next().unwrap());
65 let code = parse_code(pairs.next().unwrap());
66 (identifier, code)
67}
68
69fn parse_struct(pair: Pair<Rule>) -> AstStruct {
70 let mut result = AstStruct::default();
71 for pair in pair.into_inner() {
72 match pair.as_rule() {
73 Rule::tags => result.tags = parse_tags(pair),
74 Rule::identifier => result.name = parse_identifier(pair),
75 Rule::fields => result.fields = parse_struct_fields(pair),
76 _ => panic!("{:?}", pair.as_rule()),
77 }
78 }
79 result
80}
81
82fn parse_struct_fields(pair: Pair<Rule>) -> Vec<(String, AstType)> {
83 pair.into_inner()
84 .map(parse_struct_field)
85 .collect::<Vec<_>>()
86}
87
88fn parse_struct_field(pair: Pair<Rule>) -> (String, AstType) {
89 let mut pairs = pair.into_inner();
90 let identifier = parse_identifier(pairs.next().unwrap());
91 let type_ = parse_type(pairs.next().unwrap());
92 (identifier, type_)
93}
94
95fn parse_enum(pair: Pair<Rule>) -> AstEnum {
96 let mut result = AstEnum::default();
97 for pair in pair.into_inner() {
98 match pair.as_rule() {
99 Rule::tags => result.tags = parse_tags(pair),
100 Rule::identifier => result.name = parse_identifier(pair),
101 Rule::enum_fields => result.fields = parse_enum_fields(pair),
102 _ => panic!("{:?}", pair.as_rule()),
103 }
104 }
105 result
106}
107
108fn parse_enum_fields(pair: Pair<Rule>) -> Vec<String> {
109 pair.into_inner().map(parse_identifier).collect::<Vec<_>>()
110}
111
112fn parse_implementation(pair: Pair<Rule>) -> AstImplementation {
113 let mut result = AstImplementation::default();
114 for pair in pair.into_inner() {
115 match pair.as_rule() {
116 Rule::impl_target => result.target = parse_implementation_target(pair),
117 Rule::identifier => result.name = parse_identifier(pair),
118 Rule::where_rules => result.where_rules = parse_where_rules(pair),
119 Rule::code => result.code = parse_code(pair),
120 _ => panic!("{:?}", pair.as_rule()),
121 }
122 }
123 result
124}
125
126fn parse_implementation_target(pair: Pair<Rule>) -> AstImplementationTarget {
127 let pair = pair.into_inner().next().unwrap();
128 match pair.as_rule() {
129 Rule::impl_target_struct => AstImplementationTarget::Struct,
130 Rule::impl_target_enum => AstImplementationTarget::Enum,
131 _ => panic!("{:?}", pair.as_rule()),
132 }
133}
134
135fn parse_type(pair: Pair<Rule>) -> AstType {
136 let pair = pair.into_inner().next().unwrap();
137 match pair.as_rule() {
138 Rule::string => AstType::Extern(parse_string(pair)),
139 Rule::identifier => AstType::Local(parse_identifier(pair)),
140 _ => panic!("{:?}", pair.as_rule()),
141 }
142}
143
144fn parse_tags(pair: Pair<Rule>) -> Vec<(String, HashMap<String, String>)> {
145 pair.into_inner().map(parse_tag).collect::<Vec<_>>()
146}
147
148fn parse_tag(pair: Pair<Rule>) -> (String, HashMap<String, String>) {
149 let mut pairs = pair.into_inner();
150 let identifier = parse_identifier(pairs.next().unwrap());
151 let parameters = if let Some(pair) = pairs.next() {
152 pair.into_inner()
153 .map(parse_tag_parameter)
154 .collect::<HashMap<_, _>>()
155 } else {
156 Default::default()
157 };
158 (identifier, parameters)
159}
160
161fn parse_tag_parameter(pair: Pair<Rule>) -> (String, String) {
162 let mut pairs = pair.into_inner();
163 let identifier = parse_identifier(pairs.next().unwrap());
164 let value = if let Some(pair) = pairs.next() {
165 parse_string(pair)
166 } else {
167 Default::default()
168 };
169 (identifier, value)
170}
171
172fn parse_code(pair: Pair<Rule>) -> AstCode {
173 let pair = pair.into_inner().next().unwrap();
174 let mut code = AstCode::default();
175 for pair in pair.into_inner() {
176 match pair.as_rule() {
177 Rule::code_chars => {
178 code.0.push(AstCodeChunk::Content(pair.as_str().to_owned()));
179 }
180 Rule::code_op => {
181 let pair = pair.into_inner().next().unwrap();
182 match pair.as_rule() {
183 Rule::variable => {
184 code.0.push(AstCodeChunk::Variable(parse_variable(pair)));
185 }
186 Rule::code_op_for => {
187 code.0.push(AstCodeChunk::For(parse_code_for(pair)));
188 }
189 _ => panic!("{:?}", pair.as_rule()),
190 }
191 }
192 _ => panic!("{:?}", pair.as_rule()),
193 }
194 }
195 code
196}
197
198fn parse_code_for(pair: Pair<Rule>) -> AstCodeFor {
199 let mut result = AstCodeFor::default();
200 for pair in pair.into_inner() {
201 match pair.as_rule() {
202 Rule::vars => result.variables = parse_variables(pair),
203 Rule::code_op_in => result.container = parse_in(pair),
204 Rule::where_rules => result.where_rules = parse_where_rules(pair),
205 Rule::code => result.code = parse_code(pair),
206 _ => panic!("{:?}", pair.as_rule()),
207 }
208 }
209 result
210}
211
212fn parse_in(pair: Pair<Rule>) -> AstIn {
213 let pair = pair.into_inner().next().unwrap();
214 match pair.as_rule() {
215 Rule::variable => AstIn::Variable(parse_variable(pair)),
216 Rule::code_op_in_fields => AstIn::Fields,
217 _ => panic!("{:?}", pair.as_rule()),
218 }
219}
220
221fn parse_where_rules(pair: Pair<Rule>) -> Vec<AstWhereRule> {
222 pair.into_inner().map(parse_where_rule).collect::<Vec<_>>()
223}
224
225fn parse_where_rule(pair: Pair<Rule>) -> AstWhereRule {
226 let pair = pair.into_inner().next().unwrap();
227 match pair.as_rule() {
228 Rule::where_rule_exists => {
229 AstWhereRule::Exists(parse_variable(pair.into_inner().next().unwrap()))
230 }
231 Rule::where_rule_is => AstWhereRule::Is(parse_where_rule_is(pair)),
232 Rule::where_rule_impl => AstWhereRule::Impl(parse_where_rule_impl(pair)),
233 _ => panic!("{:?}", pair.as_rule()),
234 }
235}
236
237fn parse_where_rule_is(pair: Pair<Rule>) -> AstWhereRuleIs {
238 let mut pairs = pair.into_inner();
239 let variable = parse_variable(pairs.next().unwrap());
240 let value = parse_string(pairs.next().unwrap());
241 AstWhereRuleIs { variable, value }
242}
243
244fn parse_where_rule_impl(pair: Pair<Rule>) -> AstWhereRuleImpl {
245 let mut pairs = pair.into_inner();
246 let container = parse_in(pairs.next().unwrap());
247 let implements = pairs
248 .next()
249 .unwrap()
250 .into_inner()
251 .map(parse_identifier)
252 .collect::<Vec<_>>();
253 AstWhereRuleImpl {
254 container,
255 implements,
256 }
257}
258
259fn parse_variables(pair: Pair<Rule>) -> Vec<String> {
260 pair.into_inner().map(parse_variable).collect::<Vec<_>>()
261}
262
263fn parse_string(pair: Pair<Rule>) -> String {
264 pair.into_inner().next().unwrap().as_str().to_owned()
265}
266
267fn parse_identifier(pair: Pair<Rule>) -> String {
268 pair.as_str().to_owned()
269}
270
271fn parse_variable(pair: Pair<Rule>) -> String {
272 pair.into_inner().next().unwrap().as_str().to_owned()
273}