1use crate::ast::*;
2use failure::Error;
3use nom::types::CompleteStr;
4use std::str;
5use wasmly::DataType;
6
7fn to_string(s: CompleteStr) -> String {
8 s.to_string()
9}
10
11fn is_start_identifier_char(c: char) -> bool {
12 c == '_' || c == '$' || c.is_alphabetic()
13}
14
15fn is_identifier_char(c: char) -> bool {
16 c == '_' || c == '!' || c == '-' || c == '$' || c.is_alphanumeric()
17}
18
19fn is_text_char(c: char) -> bool {
20 c != '"'
21}
22
23fn is_digit(c: char) -> bool {
24 c.is_digit(10)
25}
26
27fn is_comment_char(c: char) -> bool {
28 c != '\r' && c != '\n'
29}
30
31fn to_data_type(c: &str) -> DataType {
32 match c {
33 "i32" => DataType::I32,
34 "i64" => DataType::I64,
35 "f32" => DataType::F32,
36 "f64" => DataType::F64,
37 _ => panic!("invalid type"),
38 }
39}
40
41named!(
42 token_comment<CompleteStr,String>,
43 do_parse!(
44 pair: pair!(tag!("//"),take_while!(is_comment_char))>>
45 (pair.0.to_string())
46 )
47);
48
49named!(
50 token_identifier<CompleteStr,String>,
51 do_parse!(
52 start: map!(take_while1!(is_start_identifier_char), to_string) >>
53 end: map!(take_while!(is_identifier_char), to_string) >>
54 (format!("{}{}",start,end).to_string())
55 )
56);
57
58named!(
59 operator_identifiers<CompleteStr,String>,
60 do_parse!(
61 id: alt!(map!(tag!(">>"),to_string)|map!(tag!("<<"),to_string)|map!(tag!(">="),to_string)|map!(tag!("<="),to_string)|map!(tag!(">"),to_string)|map!(tag!("<"),to_string)|map!(tag!("or"),to_string)|map!(tag!("and"),to_string)|map!(tag!("!="),to_string)|map!(tag!("=="),to_string)|map!(tag!("+"),to_string)|map!(tag!("-"),to_string)|map!(tag!("*"),to_string)|map!(tag!("/"),to_string)|map!(tag!("%"),to_string)|map!(tag!("|"),to_string)|map!(tag!("&"),to_string))>>
62 (id)
63 )
64);
65
66named!(
67 unary_operator_identifiers<CompleteStr,String>,
68 do_parse!(
69 id: alt!(map!(tag!("^"),to_string)|map!(tag!("~"),to_string)|map!(tag!("!"),to_string))>>
70 (id)
71 )
72);
73
74named!(
75 function_identifiers<CompleteStr,String>,
76 do_parse!(
77 id: alt!(map!(tag!("assert"),to_string)|map!(tag!("call"),to_string)|token_identifier)>>
78 (id)
79 )
80);
81
82named!(
83 token_data_type<CompleteStr,DataType>,
84 do_parse!(
85 t: map!(alt!(tag!("()")|tag!("i32")|tag!("i64")|tag!("f32")|tag!("f64")), to_string) >>
86 (to_data_type(&t))
87 )
88);
89
90named!(
91 token_text<CompleteStr,String>,
92 do_parse!(
93 tag!("\"")
94 >> text: map!(take_while!(is_text_char), to_string)
95 >> tag!("\"")
96 >> (text)
97 )
98);
99
100named!(
101 token_symbol<CompleteStr,String>,
102 do_parse!(
103 tag!(":")
104 >> text: map!(take_while!(is_identifier_char), to_string)
105 >> (text)
106 )
107);
108
109named!(
110 base_float<CompleteStr,String>,
111 do_parse!(
112 num: map!(take_while1!(is_digit), to_string) >>
113 tag!(".") >>
114 den: map!(take_while1!(is_digit), to_string) >>
115 (format!("{}.{}",num,den).to_owned())
116 )
117);
118
119named!(
120 base_int<CompleteStr,String>,
121 do_parse!(
122 num: map!(take_while1!(is_digit), to_string) >>
123 (num.to_owned())
124 )
125);
126
127named!(
128 negative_number<CompleteStr,f64>,
129 do_parse!(
130 tag!("-")
131 >> num: alt!(base_float|base_int)
132 >> (-num.parse::<f64>().unwrap())
133 )
134);
135
136named!(
137 positive_number<CompleteStr,f64>,
138 do_parse!(
139 num: alt!(base_float|base_int)
140 >> (num.parse::<f64>().unwrap())
141 )
142);
143
144named!(
145 token_number<CompleteStr,f64>,
146 alt!(positive_number|negative_number)
147);
148
149named!(external_function<CompleteStr, TopLevelOperation>,
150 do_parse!(
151 ws!(tag!("extern")) >>
152 function_name: ws!(token_identifier) >>
153 ws!(tag!("(")) >>
154 params: ws!(separated_list!(tag!(","),ws!(token_identifier))) >>
155 ws!(tag!(")")) >>
156 (TopLevelOperation::ExternalFunction(ExternalFunction{name:function_name,params:params}))
157 )
158);
159
160named!(expression_literal_string<CompleteStr, Expression>,
161 do_parse!(
162 text: ws!(token_text) >>
163 (Expression::TextLiteral(text))
164 )
165);
166
167named!(expression_literal_token<CompleteStr, Expression>,
168 do_parse!(
169 text: ws!(token_symbol) >>
170 (Expression::SymbolLiteral(text))
171 )
172);
173
174named!(expression_identifier<CompleteStr, Expression>,
175 do_parse!(
176 text: ws!(token_identifier) >>
177 (Expression::Identifier(text))
178 )
179);
180
181named!(expression_number<CompleteStr, Expression>,
182 do_parse!(
183 num: ws!(token_number) >>
184 (Expression::Number(num))
185 )
186);
187
188named!(boolean_true<CompleteStr, Expression>,
189 do_parse!(
190 tag!("true") >>
191 (Expression::Number(1.0))
192 )
193);
194
195named!(boolean_false<CompleteStr, Expression>,
196 do_parse!(
197 tag!("false") >>
198 (Expression::Number(0.0))
199 )
200);
201
202named!(expression_let_pair<CompleteStr, (String, Expression)>,
203 do_parse!(
204 id: ws!(token_identifier) >>
205 exp: ws!(expression) >>
206 ((id,exp))
207 )
208);
209
210named!(expression_loop<CompleteStr, Expression>,
211 do_parse!(
212 ws!(tag!("loop")) >>
213 many0!(ws!(token_comment)) >>
214 ws!(tag!("{")) >>
215 expressions: expression_list >>
216 tag!("}") >>
217 (Expression::Loop(OperationLoop{expressions:expressions}))
218 )
219);
220
221named!(expression_recur<CompleteStr, Expression>,
222 do_parse!(
223 tag!("recur") >>
224 (Expression::Recur(OperationRecur{}))
225 )
226);
227
228named!(expression_fnsig<CompleteStr, Expression>,
229 do_parse!(
230 ws!(tag!("fn")) >>
231 many0!(ws!(token_comment)) >>
232 ws!(tag!("(")) >>
233 many0!(ws!(token_comment)) >>
234 inputs: ws!(separated_list!(tag!(","),ws!(token_data_type))) >>
235 many0!(ws!(token_comment)) >>
236 ws!(tag!(")")) >>
237 ws!(tag!("->")) >>
238 many0!(ws!(token_comment)) >>
239 output: opt!(ws!(token_data_type)) >>
240 (Expression::FnSig(OperationFnSig{inputs:inputs, output:output}))
241 )
242);
243
244named!(expression<CompleteStr, Expression>,
245 alt!(expression_if_statement|expression_fnsig|expression_operator_call|expression_unary_operator_call|expression_assignment|expression_function_call|expression_loop|expression_recur|expression_number|boolean_true|boolean_false|expression_literal_token|expression_literal_string|expression_identifier)
246);
247
248named!(expression_list_item<CompleteStr, Expression>,
249 do_parse!(
250 many0!(ws!(token_comment)) >>
251 expr: ws!(expression) >>
252 (expr)
253 )
254);
255
256named!(expression_list<CompleteStr, Vec<Expression>>,
257 do_parse!(
258 exprs: ws!(ws!(many1!(ws!(expression_list_item)))) >>
259 (exprs)
260 )
261);
262
263named!(function_params<CompleteStr, Vec<Expression>>,
264 do_parse!(
265 op: ws!(separated_list!(tag!(","),ws!(expression))) >>
266 (op)
267 )
268);
269
270named!(expression_operator_call<CompleteStr, Expression>,
271 do_parse!(
272 tag!("(") >>
273 expr_a: ws!(expression) >>
274 function_name: ws!(operator_identifiers) >>
275 expr_b: ws!(expression) >>
276 tag!(")") >>
277 (Expression::FunctionCall(OperationFunctionCall{function_name:function_name,params:vec![expr_a,expr_b]}))
278 )
279);
280
281named!(expression_assignment<CompleteStr, Expression>,
282 do_parse!(
283 id: ws!(token_identifier) >>
284 ws!(tag!("=")) >>
285 expr: ws!(expression) >>
286 (Expression::Assignment(OperationAssignment{id:id,value:Box::new(expr)}))
287 )
288);
289
290named!(expression_else_statement<CompleteStr, Vec<Expression>>,
291 do_parse!(
292 ws!(tag!("else")) >>
293 ws!(tag!("{")) >>
294 expr_c: expression_list >>
295 tag!("}") >>
296 (expr_c)
297 )
298);
299
300named!(expression_if_statement<CompleteStr, Expression>,
301 do_parse!(
302 ws!(tag!("if")) >>
303 expr_a: ws!(expression) >>
304 ws!(tag!("{")) >>
305 expr_b: expression_list >>
306 tag!("}") >>
307 expr_c: ws!(opt!(expression_else_statement)) >>
308 (Expression::IfStatement(OperationIfStatement{condition:Box::new(expr_a),if_true:expr_b,if_false:expr_c}))
309 )
310);
311
312named!(expression_unary_operator_call<CompleteStr, Expression>,
313 do_parse!(
314 function_name: ws!(unary_operator_identifiers) >>
315 expr_a: ws!(expression) >>
316 (Expression::FunctionCall(OperationFunctionCall{function_name:function_name,params:vec![expr_a]}))
317 )
318);
319
320named!(expression_function_call<CompleteStr, Expression>,
321 do_parse!(
322 function_name: ws!(function_identifiers) >>
323 tag!("(") >>
324 params: ws!(function_params) >>
325 ws!(tag!(")")) >>
326 (Expression::FunctionCall(OperationFunctionCall{function_name:function_name,params:params}))
327 )
328);
329
330named!(define_function<CompleteStr, TopLevelOperation>,
331 do_parse!(
332 external_name:opt!( ws!(tag!("pub"))) >>
333 many0!(ws!(token_comment)) >>
334 ws!(tag!("fn")) >>
335 many0!(ws!(token_comment)) >>
336 function_name: ws!(token_identifier) >>
337 many0!(ws!(token_comment)) >>
338 ws!(tag!("(")) >>
339 many0!(ws!(token_comment)) >>
340 params: ws!(separated_list!(tag!(","),ws!(token_identifier))) >>
341 many0!(ws!(token_comment)) >>
342 ws!(tag!(")")) >>
343 many0!(ws!(token_comment)) >>
344 ws!(tag!("{")) >>
345 children: expression_list >>
346 tag!("}") >>
347 (TopLevelOperation::DefineFunction(FunctionDefinition{name: function_name,
348 exported: external_name.is_some(),
349 params: params,
350 output: None,
351 children: children}))
352 )
353);
354
355named!(struct_pair<CompleteStr, StructMember>,
356 do_parse!(
357 name: token_symbol >>
358 many0!(ws!(token_comment)) >>
359 (StructMember{name: name})
360 )
361);
362
363named!(define_struct<CompleteStr, TopLevelOperation>,
364 do_parse!(
365 ws!(tag!("struct")) >>
366 many0!(ws!(token_comment)) >>
367 name: ws!(token_identifier) >>
368 many0!(ws!(token_comment)) >>
369 tag!("{") >>
370 many0!(ws!(token_comment)) >>
371 members: many0!(ws!(struct_pair)) >>
372 many0!(ws!(token_comment)) >>
373 tag!("}") >>
374 (TopLevelOperation::DefineGlobal(Global{name:name,value:GlobalValue::Struct(StructDefinition{
375 members: members})}))
376 )
377);
378
379named!(value_number<CompleteStr, GlobalValue>,
380 do_parse!(
381 value: token_number >>
382 (GlobalValue::Number(value))
383 )
384);
385
386named!(value_text<CompleteStr, GlobalValue>,
387 do_parse!(
388 value: token_text >>
389 (GlobalValue::Text(value))
390 )
391);
392
393named!(value_symbol<CompleteStr, GlobalValue>,
394 do_parse!(
395 value: token_symbol >>
396 (GlobalValue::Symbol(value))
397 )
398);
399
400named!(global_bool_true<CompleteStr, GlobalValue>,
401 do_parse!(
402 tag!("true") >>
403 (GlobalValue::Number(1.0))
404 )
405);
406
407named!(global_bool_false<CompleteStr, GlobalValue>,
408 do_parse!(
409 tag!("false") >>
410 (GlobalValue::Number(0.0))
411 )
412);
413
414named!(global_identifier<CompleteStr, GlobalValue>,
415 do_parse!(
416 value: token_identifier >>
417 (GlobalValue::Identifier(value))
418 )
419);
420
421named!(global_data<CompleteStr, GlobalValue>,
422 do_parse!(
423 tag!("(") >>
424 values: ws!(separated_list!(tag!(","),ws!(alt!(global_value|global_identifier)))) >>
425 tag!(")") >>
426 (GlobalValue::Data(values))
427 )
428);
429
430named!(global_value<CompleteStr, GlobalValue>,
431 do_parse!(
432 value: ws!(alt!(global_bool_true|global_bool_false|value_number|value_symbol|value_text|global_data)) >>
433 (value)
434 )
435);
436
437named!(define_global<CompleteStr, TopLevelOperation>,
438 do_parse!(
439 ws!(tag!("static")) >>
440 name: ws!(token_identifier) >>
441 ws!(tag!("=")) >>
442 value: global_value >>
443 (TopLevelOperation::DefineGlobal(Global{name: name,value:value}))
444 )
445);
446
447named!(comment<CompleteStr, TopLevelOperation>,
448 do_parse!(
449 tag!("//") >>
450 comment: map!(take_while!(is_comment_char),to_string) >>
451 (TopLevelOperation::Comment(comment))
452 )
453);
454
455named!(app<CompleteStr, App>,
456 do_parse!(
457 op: many0!(ws!(alt!(comment|external_function|define_function|define_struct|define_global))) >>
458 eof!() >>
459 (App{children:op})
460 )
461);
462
463pub fn parse(content: &str) -> Result<App, Error> {
464 let result = app(CompleteStr(content));
465 match result {
466 Ok((_, value)) => Ok(value),
467 Err(nom::Err::Incomplete(needed)) => Err(format_err!("{:?}", needed)),
468 Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => Err(format_err!("{:?}", e)),
469 }
470}