1extern crate pest;
2#[macro_use]
3extern crate pest_derive;
4
5use pest::Parser;
6use std::num::ParseIntError;
7
8#[derive(Parser)]
9#[grammar = "../grammar/cyclo.pest"]
10struct CycloParser;
11
12#[derive(Debug, Clone, PartialEq)]
13#[allow(non_camel_case_types)]
14pub enum Type {
15 None,
16 i32,
17 i64,
18 String,
19 Bool,
20 List(Box<Type>),
21}
22
23#[derive(Debug, Clone, PartialEq)]
24pub enum Expression {
25 Number(i32),
26 Number64(i64),
27 String(String),
28 Bool(bool),
29 Nil,
30 List(Vec<Expression>),
31 ListIndex(Box<Expression>, Box<Expression>),
32 ListAssign(String, Box<Expression>, Box<Expression>),
33 Variable(String),
34 Binary(Box<Expression>, String, Box<Expression>),
35 Grouping(Box<Expression>),
36 LetStmt(String, Type, Box<Expression>),
37 BlockStmt(Vec<Expression>),
38 FuncArg(String, Type),
39 FuncStmt(String, Vec<Expression>, Type, Box<Expression>),
40 CallStmt(String, Vec<Expression>),
41 IfStmt(Box<Expression>, Box<Expression>, Box<Option<Expression>>),
42 WhileStmt(Box<Expression>, Box<Expression>),
43 ReturnStmt(Box<Expression>),
44 ForStmt(String, i32, i32, i32, Box<Expression>),
45 Print(Box<Expression>),
46 Len(Box<Expression>),
47}
48
49impl Expression {
50 fn new_number(n: i32) -> Self {
51 Self::Number(n)
52 }
53 fn new_number64(n: i64) -> Self {
54 Self::Number64(n)
55 }
56
57 fn new_string(s: String) -> Self {
58 Self::String(s)
59 }
60
61 fn new_binary(left: Expression, op: String, right: Expression) -> Self {
62 Self::Binary(Box::new(left), op, Box::new(right))
63 }
64
65 fn new_bool(b: bool) -> Self {
66 Self::Bool(b)
67 }
68
69 fn new_list(list: Vec<Expression>) -> Self {
70 Self::List(list)
71 }
72
73 fn new_list_index(list: Expression, index: Expression) -> Self {
74 Self::ListIndex(Box::new(list), Box::new(index))
75 }
76
77 fn new_list_assign(var: String, index: Expression, value: Expression) -> Self {
78 Self::ListAssign(var, Box::new(index), Box::new(value))
79 }
80
81 fn new_nil() -> Self {
82 Self::Nil
83 }
84
85 fn new_variable(name: String) -> Self {
86 Self::Variable(name)
87 }
88
89 fn new_let_stmt(name: String, let_type: Type, value: Expression) -> Self {
90 Self::LetStmt(name, let_type, Box::new(value))
91 }
92
93 fn new_block_stmt(exprs: Vec<Expression>) -> Self {
94 Self::BlockStmt(exprs)
95 }
96
97 fn new_if_stmt(
98 condition: Expression,
99 if_block_expr: Expression,
100 else_block_expr: Option<Expression>,
101 ) -> Self {
102 Self::IfStmt(
103 Box::new(condition),
104 Box::new(if_block_expr),
105 Box::new(else_block_expr),
106 )
107 }
108
109 fn new_while_stmt(condition: Expression, while_block_expr: Expression) -> Self {
110 Self::WhileStmt(Box::new(condition), Box::new(while_block_expr))
111 }
112
113 fn new_for_stmt(
114 var_name: String,
115 start: i32,
116 end: i32,
117 step: i32,
118 for_block_expr: Expression,
119 ) -> Self {
120 Self::ForStmt(var_name, start, end, step, Box::new(for_block_expr))
121 }
122
123 fn new_func_stmt(
124 name: String,
125 args: Vec<Expression>,
126 return_type: Type,
127 body: Expression,
128 ) -> Self {
129 Self::FuncStmt(name, args, return_type, Box::new(body))
130 }
131
132 fn new_func_arg(name: String, arg_type: Type) -> Self {
133 Self::FuncArg(name, arg_type)
134 }
135
136 fn new_call_stmt(name: String, args: Vec<Expression>) -> Self {
137 Self::CallStmt(name, args)
138 }
139
140 fn new_print_stmt(value: Expression) -> Self {
141 Self::Print(Box::new(value))
142 }
143
144 fn new_len_stmt(value: Expression) -> Self {
145 Self::Len(Box::new(value))
146 }
147
148 fn new_return_stmt(value: Expression) -> Self {
149 Self::ReturnStmt(Box::new(value))
150 }
151}
152
153fn get_type(next: pest::iterators::Pair<Rule>) -> Type {
154 let mut inner_pairs = next.into_inner();
155 let next = inner_pairs.next().unwrap();
156 match next.as_rule() {
157 Rule::string_type => Type::String,
158 Rule::bool_type => Type::Bool,
159 Rule::i32_type => Type::i32,
160 Rule::i64_type => Type::i64,
161 Rule::list_type => {
162 let list_inner_type = get_type(next);
163 Type::List(Box::new(list_inner_type))
164 }
165 _ => Type::None,
166 }
167}
168
169fn parse_expression(
170 pair: pest::iterators::Pair<Rule>,
171) -> Result<Expression, Box<pest::error::Error<Rule>>> {
172 match pair.as_rule() {
173 Rule::number => {
174 let val_str = pair.as_str();
175 let parse_i32: Result<i32, _> = val_str.parse();
177 match parse_i32 {
178 Err(_) => {
179 let n: i64 = val_str.parse().map_err(|e: ParseIntError| {
181 pest::error::Error::new_from_span(
182 pest::error::ErrorVariant::CustomError {
183 message: e.to_string(),
184 },
185 pair.as_span(),
186 )
187 })?;
188 Ok(Expression::new_number64(n))
189 }
190 Ok(n) => Ok(Expression::new_number(n)),
191 }
192 }
193 Rule::name => {
194 let s = pair.as_str().to_string().replace(' ', "");
195 Ok(Expression::new_variable(s))
196 }
197 Rule::string => {
198 let s = pair.as_str().to_string();
199 Ok(Expression::new_string(s))
200 }
201 Rule::bool => match pair.as_str() {
202 "true" => Ok(Expression::new_bool(true)),
203 "false" => Ok(Expression::new_bool(false)),
204 _ => Err(Box::new(pest::error::Error::new_from_span(
205 pest::error::ErrorVariant::CustomError {
206 message: "Invalid boolean value".to_string(),
207 },
208 pair.as_span(),
209 ))),
210 },
211 Rule::nil => Ok(Expression::new_nil()),
212 Rule::binary => {
213 let mut inner_pairs = pair.into_inner();
214 let next = inner_pairs.next().unwrap();
215 let left = parse_expression(next)?;
216 let op = inner_pairs.next().unwrap().as_str().to_string();
217 let right = parse_expression(inner_pairs.next().unwrap())?;
218 Ok(Expression::new_binary(left, op, right))
219 }
220 Rule::grouping => {
221 let inner_pair = pair.into_inner().next().unwrap();
222 parse_expression(inner_pair).map(|expr| Expression::Grouping(Box::new(expr)))
223 }
224 Rule::let_stmt => {
225 let mut inner_pairs = pair.into_inner();
226 let name = inner_pairs
227 .next()
228 .unwrap()
229 .as_str()
230 .to_string()
231 .replace(' ', "");
232 let mut let_type = Type::None;
233
234 let next = inner_pairs.next().unwrap();
235 if next.as_rule() == Rule::colon {
236 let_type = get_type(inner_pairs.next().unwrap());
237 inner_pairs.next();
238 }
239 let value = parse_expression(inner_pairs.next().unwrap())?;
240 Ok(Expression::new_let_stmt(name, let_type, value))
241 }
242 Rule::expression => {
243 let mut inner_pairs = pair.into_inner();
244 let left = parse_expression(inner_pairs.next().unwrap())?;
245 let op = inner_pairs.next().unwrap().as_str().to_string();
246 let right = parse_expression(inner_pairs.next().unwrap())?;
247 Ok(Expression::new_binary(left, op, right))
248 }
249 Rule::literal => {
250 let inner_pair = pair.into_inner().next().unwrap();
251 parse_expression(inner_pair)
252 }
253 Rule::print_stmt => {
254 let inner_pair = pair.into_inner().next().unwrap();
255 let value = parse_expression(inner_pair)?;
256 Ok(Expression::new_print_stmt(value))
257 }
258 Rule::len_stmt => {
259 let inner_pair = pair.into_inner().next().unwrap();
260 let value = parse_expression(inner_pair)?;
261 Ok(Expression::new_len_stmt(value))
262 }
263 Rule::func_stmt => {
264 let mut inner_pairs = pair.into_inner();
265 let name = inner_pairs.next().unwrap().as_str().to_string();
266
267 let mut func_args = vec![];
269
270 while inner_pairs
271 .peek()
272 .map_or(false, |p| p.as_rule() == Rule::func_arg)
273 {
274 let args: pest::iterators::Pair<'_, Rule> = inner_pairs.next().unwrap();
275 func_args.push(parse_expression(args)?);
276 }
277
278 let mut func_type = Type::None;
279 while inner_pairs.peek().map_or(false, |p| {
281 p.as_rule() == Rule::type_name || p.as_rule() == Rule::arrow
282 }) {
283 let next: pest::iterators::Pair<'_, Rule> = inner_pairs.next().unwrap();
284 if next.as_rule() == Rule::type_name {
285 func_type = get_type(next);
286 }
287 }
288 let inner = inner_pairs.next().unwrap();
289 let body = parse_expression(inner)?;
290 let func = Expression::new_func_stmt(name, func_args, func_type, body);
291 Ok(func)
292 }
293 Rule::func_arg => {
294 let mut inner_pairs = pair.clone().into_inner();
295 while inner_pairs.peek().map_or(false, |p| {
296 p.as_rule() == Rule::comma
297 || p.as_rule() == Rule::name
298 || p.as_rule() == Rule::type_name
299 }) {
300 let next = inner_pairs.next().unwrap();
301 if next.as_rule() == Rule::comma {
302 continue;
303 }
304 if next.as_rule() == Rule::type_name {
305 let arg_type = get_type(next);
306 let arg_name = inner_pairs.next().unwrap().as_str().to_string();
307 if arg_type == Type::None {
308 return Err(Box::new(pest::error::Error::new_from_span(
309 pest::error::ErrorVariant::CustomError {
310 message: format!(
311 "Unable to find argument type for {:?}",
312 pair.as_rule()
313 ),
314 },
315 pair.as_span(),
316 )));
317 }
318 return Ok(Expression::new_func_arg(arg_name, arg_type));
319 }
320 }
321 unreachable!("Unable to parse args {:?}", inner_pairs)
322 }
323 Rule::call_stmt => {
324 let mut inner_pairs = pair.into_inner();
325 let name = inner_pairs.next().unwrap().as_str().to_string();
326 let mut args = vec![];
327 while inner_pairs.peek().map_or(false, |p| {
329 p.as_rule() == Rule::comma
330 || p.as_rule() == Rule::binary
331 || p.as_rule() == Rule::literal
332 || p.as_rule() == Rule::name
333 }) {
334 let next = inner_pairs.next().unwrap();
335 if next.as_rule() != Rule::comma {
336 let arg_expr = parse_expression(next)?;
337 args.push(arg_expr);
338 }
339 }
340 let call = Expression::new_call_stmt(name, args);
341 Ok(call)
342 }
343 Rule::block_stmt => {
344 let inner_pairs = pair.into_inner();
345 let mut expressions = Vec::new();
346
347 for inner_pair in inner_pairs {
348 let rule = inner_pair.as_rule();
349 if rule == Rule::semicolon {
350 continue;
351 }
352 expressions.push(parse_expression(inner_pair)?);
353 }
354
355 Ok(Expression::new_block_stmt(expressions))
356 }
357 Rule::if_stmt => {
358 let mut inner_pairs = pair.into_inner();
359 let cond = parse_expression(inner_pairs.next().unwrap())?;
360 let if_stmt = parse_expression(inner_pairs.next().unwrap())?;
361 let else_stmt = if let Some(else_pair) = inner_pairs.next() {
362 Some(parse_expression(else_pair)?)
363 } else {
364 None
365 };
366 Ok(Expression::new_if_stmt(cond, if_stmt, else_stmt))
367 }
368 Rule::for_stmt => {
369 let mut inner_pairs = pair.into_inner();
371 let mut var = inner_pairs.next().unwrap().into_inner();
372 let var_name = var.next().unwrap().as_str().to_string().replace(' ', "");
373 let start = var.next().unwrap().as_str().parse::<i32>().unwrap();
374
375 let mut cond_stmt = inner_pairs.next().unwrap().into_inner();
377 let _cond_var_name = cond_stmt
378 .next()
379 .unwrap()
380 .as_str()
381 .to_string()
382 .replace(' ', "");
383 let end = cond_stmt.next().unwrap().as_str().parse::<i32>().unwrap();
384
385 let mut step = 1;
386 let step_stmt = inner_pairs.next();
387
388 if step_stmt.unwrap().as_str().to_string().contains("--") {
389 step = -1;
390 }
391 let block_stmt = parse_expression(inner_pairs.next().unwrap())?;
392 Ok(Expression::new_for_stmt(
393 var_name, start, end, step, block_stmt,
394 ))
395 }
396 Rule::return_stmt => {
397 let inner_pairs = pair.into_inner().next().unwrap();
398 let expr = parse_expression(inner_pairs)?;
399 Ok(Expression::new_return_stmt(expr))
400 }
401 Rule::while_stmt => {
402 let mut inner_pairs = pair.into_inner();
403 let cond = parse_expression(inner_pairs.next().unwrap())?;
404 let while_block_expr = parse_expression(inner_pairs.next().unwrap())?;
405 Ok(Expression::new_while_stmt(cond, while_block_expr))
406 }
407 Rule::list => {
408 let mut inner_pairs = pair.into_inner();
409 let mut list = vec![];
410 while inner_pairs
411 .peek()
412 .map_or(false, |p| p.as_rule() != Rule::rbracket)
413 {
414 let next = inner_pairs.next().unwrap();
415 let next_rule = next.as_rule();
416 if next_rule != Rule::comma && next_rule != Rule::lbracket {
417 let expr = parse_expression(next)?;
418 list.push(expr);
419 }
420 }
421 Ok(Expression::new_list(list))
422 }
423 Rule::list_index => {
424 let mut inner_pairs = pair.into_inner();
425 let array_expr = parse_expression(inner_pairs.next().unwrap())?;
426 inner_pairs.next(); let index_expr = parse_expression(inner_pairs.next().unwrap())?;
428 Ok(Expression::new_list_index(array_expr, index_expr))
429 }
430 Rule::index_stmt => {
431 let mut inner_pairs = pair.into_inner();
432 let mut array_expr_inner = inner_pairs.next().unwrap().into_inner();
433 let array_var = array_expr_inner.next().unwrap().as_str();
435 array_expr_inner.next(); let array_index = parse_expression(array_expr_inner.next().unwrap())?;
437 inner_pairs.next(); let array_assign = parse_expression(inner_pairs.next().unwrap())?;
439 Ok(Expression::new_list_assign(
440 array_var.to_string(),
441 array_index,
442 array_assign,
443 ))
444 }
445 _ => Err(Box::new(pest::error::Error::new_from_span(
446 pest::error::ErrorVariant::CustomError {
447 message: format!(
448 "Invalid expression for rule {:?} or rule not specified for grammar",
449 pair.as_rule()
450 ),
451 },
452 pair.as_span(),
453 ))),
454 }
455}
456
457fn parse_program(
458 pair: pest::iterators::Pair<Rule>,
459) -> Result<Vec<Expression>, Box<pest::error::Error<Rule>>> {
460 let mut expr_vec = vec![];
461 for stmt_pair in pair.into_inner() {
462 match stmt_pair.as_rule() {
463 Rule::semicolon | Rule::EOI | Rule::comma => {
464 continue;
465 }
466 _ => {
467 let expr = parse_expression(stmt_pair)?;
468 expr_vec.push(expr);
469 }
470 }
471 }
472 Ok(expr_vec)
473}
474
475pub fn parse_cyclo_program(input: &str) -> Result<Vec<Expression>, Box<pest::error::Error<Rule>>> {
476 match CycloParser::parse(Rule::expression_list, input) {
477 Ok(mut pairs) => {
478 if let Some(pair) = pairs.next() {
481 return parse_program(pair);
482 }
483 }
484 Err(e) => return Err(Box::new(e)),
485 };
486 unreachable!("parse function program")
487}
488
489#[cfg(test)]
490mod test {
491 use super::*;
492 use crate::Expression::{FuncArg, Number, Variable};
493
494 #[test]
495 fn test_parse_string_expression() {
496 let input = r#""hello";"#;
497 assert!(parse_cyclo_program(input).is_ok());
498 }
499
500 #[test]
501 fn test_parse_string_expression_err() {
502 let input = r#"hello";"#;
503 assert!(parse_cyclo_program(input).is_err());
504 }
505
506 #[test]
507 fn test_parse_digit() {
508 let input = r#"5;"#;
509 assert!(parse_cyclo_program(input).is_ok());
510 }
511
512 #[test]
513 fn test_parse_digit_err() {
514 let input = r#"5"#;
515 assert!(parse_cyclo_program(input).is_err());
516 }
517
518 #[test]
519 fn test_parse_number_expression() {
520 let input = r#"555;"#;
521 assert!(parse_cyclo_program(input).is_ok());
522 }
523
524 #[test]
525 fn test_parse_number_expression_add() {
526 let input = r#"555 + 555 + 555;"#;
527 assert!(parse_cyclo_program(input).is_ok());
528 }
529
530 #[test]
531 fn test_parse_number_expression_add_grouping() {
532 let input = r#"(555 + 555) + (555 + 555);"#;
533 assert!(parse_cyclo_program(input).is_ok());
534 }
535
536 #[test]
537 fn test_parse_minus_negative_number_expression() {
538 let input = r#"-555 - 555;"#;
539 assert!(parse_cyclo_program(input).is_ok());
540 }
541
542 #[test]
543 fn test_parse_minus_negative_two_number_expression() {
544 let input = r#"-555 - -555;"#;
545 assert!(parse_cyclo_program(input).is_ok());
546 }
547
548 #[test]
549 fn test_parse_negative_digit_expression() {
550 let input = r#"-5 - 5;"#;
551 if let Err(e) = parse_cyclo_program(input) {
552 eprintln!("{}", e);
553 }
554 assert!(parse_cyclo_program(input).is_ok());
555 }
556
557 #[test]
558 fn test_parse_number_expression_err() {
559 let input = r#"555""#;
560 assert!(parse_cyclo_program(input).is_err());
561 }
562
563 #[test]
564 fn test_parse_nil() {
565 let input = r#"nil;"#;
566 assert!(parse_cyclo_program(input).is_ok());
567 }
568
569 #[test]
570 fn test_parse_true_bool() {
571 let input = r#"true;"#;
572 assert!(parse_cyclo_program(input).is_ok());
573 }
574
575 #[test]
576 fn test_parse_false_bool() {
577 let input = r#"false;"#;
578 assert!(parse_cyclo_program(input).is_ok());
579 }
580
581 #[test]
582 fn test_parse_string_equals() {
583 let input = r#""hello" == "hello";"#;
584 assert!(parse_cyclo_program(input).is_ok());
585 }
586
587 #[test]
588 fn test_parse_bool_equals() {
589 let input = r#"true == true;"#;
590 assert!(parse_cyclo_program(input).is_ok());
591 }
592
593 #[test]
594 fn test_parse_nil_equals() {
595 let input = r#"nil == nil;"#;
596 assert!(parse_cyclo_program(input).is_ok());
597 }
598
599 #[test]
600 fn test_parse_char_equals() {
601 let input = r#""h" == "h";"#;
602 assert!(parse_cyclo_program(input).is_ok());
603 }
604
605 #[test]
606 fn test_parse_str_equals() {
607 let input = r#""hello" == "hello";"#;
608 assert!(parse_cyclo_program(input).is_ok());
609 }
610
611 #[test]
612 fn test_parse_number_equals_digit() {
613 let input = r#"5 == 5;"#;
614 if let Err(e) = parse_cyclo_program(input) {
615 eprintln!("{}", e);
616 }
617 assert!(parse_cyclo_program(input).is_ok());
618 }
619
620 #[test]
621 fn test_parse_number_equals_digit_rhs() {
622 let input = r#"55 == 5;"#;
623 assert!(parse_cyclo_program(input).is_ok());
624 }
625
626 #[test]
627 fn test_parse_number_not_equals_digit() {
628 let input = r#"5 != 5;"#;
629 assert!(parse_cyclo_program(input).is_ok());
630 }
631
632 #[test]
633 fn test_parse_number_lt_digit() {
634 let input = r#"5 < 5;"#;
635 assert!(parse_cyclo_program(input).is_ok());
636 }
637
638 #[test]
639 fn test_parse_number_lte_digit() {
640 let input = r#"5 <= 5;"#;
641 assert!(parse_cyclo_program(input).is_ok());
642 }
643
644 #[test]
645 fn test_parse_number_gt_digit() {
646 let input = r#"5 > 5;"#;
647 assert!(parse_cyclo_program(input).is_ok());
648 }
649
650 #[test]
651 fn test_parse_number_gte_digit() {
652 let input = r#"5 >= 5;"#;
653 assert!(parse_cyclo_program(input).is_ok());
654 }
655
656 #[test]
657 fn test_parse_number_equals() {
658 let input = r#"55 == 45;"#;
659 assert!(parse_cyclo_program(input).is_ok());
660 }
661
662 #[test]
663 fn test_parse_number_less_than() {
664 let input = r#"55 < 45;"#;
665 assert!(parse_cyclo_program(input).is_ok());
666 }
667
668 #[test]
669 fn test_parse_number_less_than_equal() {
670 let input = r#"55 <= 45;"#;
671 assert!(parse_cyclo_program(input).is_ok());
672 }
673
674 #[test]
675 fn test_parse_number_more_than() {
676 let input = r#"55 > 45;"#;
677 assert!(parse_cyclo_program(input).is_ok());
678 }
679
680 #[test]
681 fn test_parse_number_more_than_equal() {
682 let input = r#"55 >= 45;"#;
683 assert!(parse_cyclo_program(input).is_ok());
684 }
685
686 #[test]
687 fn test_parse_number_not_equal() {
688 let input = r#"55 != 45;"#;
689 assert!(parse_cyclo_program(input).is_ok());
690 }
691
692 #[test]
693 fn test_parse_bool_equals_string() {
694 let input = r#"true == "hello";"#;
695 assert!(parse_cyclo_program(input).is_ok());
696 }
697
698 #[test]
699 fn test_parse_let_stmt_string() {
700 let input = r#"let value = "hello";"#;
701 assert!(parse_cyclo_program(input).is_ok());
702 }
703
704 #[test]
705 fn test_parse_let_stmt_bool() {
706 let input = r#"let value = true;"#;
707 assert!(parse_cyclo_program(input).is_ok());
708 }
709
710 #[test]
711 fn test_parse_let_stmt_bool_without_comma() {
712 let input = r#"let value: bool = true"#;
713 assert!(parse_cyclo_program(input).is_err());
714 }
715
716 #[test]
717 fn test_parse_let_stmt_digit() {
718 let input = r#"let value: i32 = 5;"#;
719 assert!(parse_cyclo_program(input).is_ok());
720 }
721
722 #[test]
723 fn test_parse_let_stmt_number() {
724 let input = r#"let value = 555;"#;
725 assert!(parse_cyclo_program(input).is_ok());
726 }
727
728 #[test]
729 fn test_parse_let_stmt_nil() {
730 let input = r#"let value = nil;"#;
731 assert!(parse_cyclo_program(input).is_ok());
732 }
733
734 #[test]
735 fn test_parse_let_stmt_list() {
736 let input = r#"let value: List<i32> = [1, 2, 3, 4];"#;
737 assert!(parse_cyclo_program(input).is_ok());
738 }
739
740 #[test]
741 fn test_parse_let_stmt_list_string() {
742 let input = r#"let value: List<string> = ["1", "2", "3", "4"];"#;
743 let output: Result<Vec<Expression>, Box<pest::error::Error<Rule>>> =
744 parse_cyclo_program(input);
745 let list_expr = Expression::List(vec![
746 Expression::String("\"1\"".to_string()),
747 Expression::String("\"2\"".to_string()),
748 Expression::String("\"3\"".to_string()),
749 Expression::String("\"4\"".to_string()),
750 ]);
751 let list_type = Type::List(Box::new(Type::String));
752 let let_stmt_expr =
753 Expression::LetStmt("value".to_string(), list_type, Box::new(list_expr));
754 assert!(output.is_ok());
755 assert!(output.unwrap().contains(&let_stmt_expr))
756 }
757
758 #[test]
759 fn test_parse_let_stmt_list_of_lists_bool() {
760 let input = r#"let value: List<List<bool>> = [[true,false],[true,false]];"#;
761 let output: Result<Vec<Expression>, Box<pest::error::Error<Rule>>> =
762 parse_cyclo_program(input);
763 let list_expr = Expression::List(vec![Expression::Bool(true), Expression::Bool(false)]);
764 let list_of_list_expr = Expression::List(vec![list_expr.clone(), list_expr]);
765 let list_type = Type::List(Box::new(Type::Bool));
766 let list_of_list_type = Type::List(Box::new(list_type));
767 let let_stmt_expr = Expression::LetStmt(
768 "value".to_string(),
769 list_of_list_type,
770 Box::new(list_of_list_expr),
771 );
772 assert!(output.is_ok());
773 assert!(output.unwrap().contains(&let_stmt_expr))
774 }
775
776 #[test]
777 fn test_parse_let_stmt_list_of_lists_int() {
778 let input = r#"let value: List<List<i32>> = [[1,2],[1,2]];"#;
779 let output: Result<Vec<Expression>, Box<pest::error::Error<Rule>>> =
780 parse_cyclo_program(input);
781 let list_expr = Expression::List(vec![Number(1), Number(2)]);
782 let list_of_list_expr = Expression::List(vec![list_expr.clone(), list_expr]);
783 let list_type = Type::List(Box::new(Type::i32));
784 let list_of_list_type = Type::List(Box::new(list_type));
785 let let_stmt_expr = Expression::LetStmt(
786 "value".to_string(),
787 list_of_list_type,
788 Box::new(list_of_list_expr),
789 );
790 assert!(output.is_ok());
791 assert!(output.unwrap().contains(&let_stmt_expr))
792 }
793
794 #[test]
795 fn test_parse_let_stmt_grouping() {
796 let input = r#"let value = (true == true);"#;
797 assert!(parse_cyclo_program(input).is_ok());
798 }
799
800 #[test]
801 fn test_parse_let_stmt_assign() {
802 let input = r#"let value = other_value;"#;
803 assert!(parse_cyclo_program(input).is_ok());
804 }
805
806 #[test]
807 fn test_parse_let_stmt_bool_assign() {
808 let input = r#"let value = (other_value == first_value);"#;
809 assert!(parse_cyclo_program(input).is_ok());
810 }
811
812 #[test]
813 fn test_parse_print_stmt_bool_assign() {
814 let input = r#"print(other_value == first_value);"#;
815 assert!(parse_cyclo_program(input).is_ok());
816 }
817
818 #[test]
826 fn test_comments() {
827 let input = r#"let value = 1 - 1; // hello comments"#;
828 assert!(parse_cyclo_program(input).is_ok());
829 }
830
831 #[test]
832 fn test_parse_multi_line_stmt() {
833 let input = "
834 let one = true;
835 let two = false;
836 let three = (two == one);
837 ";
838 assert!(parse_cyclo_program(input).is_ok());
839 }
840
841 #[test]
842 fn test_empty_block_stmt() {
843 let input = "
844 {
845
846 }
847 ";
848 assert!(parse_cyclo_program(input).is_ok());
849 }
850
851 #[test]
852 fn test_block_stmt() {
853 let input = "
854 {
855 let b = 5;
856 {
857 {
858 fn example(i32 arg1, i32 arg2) {
859 print(arg1 + arg2);
860 }
861 example(5,5);
862 }
863 a = 5;
864 }
865 }
866 ";
867 assert!(parse_cyclo_program(input).is_ok());
868 }
869
870 #[test]
871 fn test_func_no_return() {
872 let input = r#"
873 fn example() {
874 print(1);
875 }
876 fn hello() {
877 print("hello");
878 }
879 "#;
880 assert!(parse_cyclo_program(input).is_ok());
881 }
882
883 #[test]
884 fn test_fn_return_and_print() {
885 let input = r#"
886 fn get_ten(List<List<i32>> example) -> List<List<i32>> {
887 return example;
888 }
889 print(get_ten([[1,2],[1,3]]));
890 "#;
891 let output: Result<Vec<Expression>, Box<pest::error::Error<Rule>>> =
892 parse_cyclo_program(input);
893 assert!(output.is_ok());
894 }
895
896 #[test]
897 fn test_fn_return_int_num() {
898 let input = r#"
899 fn get_ten() -> i32 {
900 return 10;
901 }
902 let var = get_ten();
903 "#;
904 let output: Result<Vec<Expression>, Box<pest::error::Error<Rule>>> =
905 parse_cyclo_program(input);
906 let func_expr = build_basic_func_ast(
907 "get_ten".into(),
908 [].to_vec(),
909 Type::i32,
910 vec![Expression::ReturnStmt(Box::new(Expression::Number(10)))],
911 );
912 assert!(output.is_ok());
913 assert!(output.unwrap().contains(&func_expr))
914 }
915
916 #[test]
917 fn test_fn_return_int_value() {
918 let input = r#"
919 fn get_value(i32 value) -> i32 {
920 return value;
921 }
922 "#;
923 let output: Result<Vec<Expression>, Box<pest::error::Error<Rule>>> =
924 parse_cyclo_program(input);
925 let func_expr = build_basic_func_ast(
926 "get_value".into(),
927 [FuncArg("value".into(), Type::i32)].to_vec(),
928 Type::i32,
929 vec![Expression::ReturnStmt(Box::new(Expression::Variable(
930 "value".into(),
931 )))],
932 );
933 assert!(output.is_ok());
934 assert!(output.unwrap().contains(&func_expr))
935 }
936
937 #[test]
938 fn test_fn_return_string_value() {
939 let input = r#"
940 fn get_value(string value) -> string {
941 return value;
942 }
943 "#;
944 let output: Result<Vec<Expression>, Box<pest::error::Error<Rule>>> =
945 parse_cyclo_program(input);
946 let func_expr = build_basic_func_ast(
947 "get_value".into(),
948 [FuncArg("value".into(), Type::String)].to_vec(),
949 Type::String,
950 vec![Expression::ReturnStmt(Box::new(Expression::Variable(
951 "value".into(),
952 )))],
953 );
954 assert!(output.is_ok());
955 assert!(output.unwrap().contains(&func_expr))
959 }
960
961 #[test]
962 fn test_fn_return_int_add() {
963 let input = r#"
964 fn add(i32 x, i32 y) -> i32 {
965 return x + y;
966 }
967 "#;
968 let output: Result<Vec<Expression>, Box<pest::error::Error<Rule>>> =
969 parse_cyclo_program(input);
970 let func_expr = build_basic_func_ast(
971 "add".into(),
972 [
973 FuncArg("x".into(), Type::i32),
974 FuncArg("y".into(), Type::i32),
975 ]
976 .to_vec(),
977 Type::i32,
978 vec![Expression::ReturnStmt(Box::new(Expression::Binary(
979 Box::new(Variable("x".into())),
980 "+".into(),
981 Box::new(Variable("y".into())),
982 )))],
983 );
984 assert!(output.is_ok());
985 assert!(output.unwrap().contains(&func_expr))
986 }
987
988 fn build_basic_func_ast(
990 name: String,
991 args: Vec<Expression>,
992 return_type: Type,
993 block_stmt: Vec<Expression>,
994 ) -> Expression {
995 let body = Expression::BlockStmt(block_stmt);
996 Expression::new_func_stmt(name, args, return_type, body)
997 }
998
999 #[test]
1000 fn test_fn_return_string() {
1001 let input = r#"
1002 fn hello_world() -> string {
1003 return "hello world";
1004 }
1005 let val = hello_world();
1006 "#;
1007 let output: Result<Vec<Expression>, Box<pest::error::Error<Rule>>> =
1008 parse_cyclo_program(input);
1009 let func_expr = build_basic_func_ast(
1010 "hello_world".into(),
1011 [].to_vec(),
1012 Type::String,
1013 vec![Expression::ReturnStmt(Box::new(Expression::String(
1014 "\"hello world\"".into(),
1015 )))],
1016 );
1017 assert!(output.is_ok());
1018 assert!(output.unwrap().contains(&func_expr))
1019 }
1020
1021 #[test]
1022 fn test_fn_return_bool() {
1023 let input = r#"
1024 fn hello_bool() -> bool {
1025 return true;
1026 }
1027 let val = hello_world();
1028 "#;
1029 let output: Result<Vec<Expression>, Box<pest::error::Error<Rule>>> =
1030 parse_cyclo_program(input);
1031 let func_expr = build_basic_func_ast(
1032 "hello_bool".into(),
1033 [].to_vec(),
1034 Type::Bool,
1035 vec![Expression::ReturnStmt(Box::new(Expression::Bool(true)))],
1036 );
1037 assert!(output.is_ok());
1038 assert!(output.unwrap().contains(&func_expr))
1039 }
1040
1041 #[test]
1042 fn test_fn_return_call_fn_binary_add() {
1043 let input = r#"
1044 fn sum_square(i32 x, i32 y) -> i32 {
1045 return square(x) + square(y);
1046 }
1047 let val = sum_square(x,y);
1048 "#;
1049 let output: Result<Vec<Expression>, Box<pest::error::Error<Rule>>> =
1050 parse_cyclo_program(input);
1051 let func_expr = build_basic_func_ast(
1052 "sum_square".into(),
1053 [
1054 FuncArg("x".into(), Type::i32),
1055 FuncArg("y".into(), Type::i32),
1056 ]
1057 .to_vec(),
1058 Type::i32,
1059 vec![Expression::ReturnStmt(Box::new(Expression::Binary(
1060 Box::new(Expression::CallStmt(
1061 "square".into(),
1062 vec![Variable("x".into())],
1063 )),
1064 "+".into(),
1065 Box::new(Expression::CallStmt(
1066 "square".into(),
1067 vec![Variable("y".into())],
1068 )),
1069 )))],
1070 );
1071 assert!(output.is_ok());
1072 assert!(output.unwrap().contains(&func_expr));
1073 }
1074
1075 #[test]
1076 fn test_fibonacci_fn() {
1077 let input = r#"
1078 fn fib(i32 n) -> i32 {
1079 if (n < 2) {
1080 return 0;
1081 }
1082 return fib(n-1) + fib(n-2);
1083 }
1084 fib(20);
1085 "#;
1086 let output: Result<Vec<Expression>, Box<pest::error::Error<Rule>>> =
1087 parse_cyclo_program(input);
1088 assert!(output.is_ok());
1089 }
1091
1092 #[test]
1093 fn test_call_func() {
1094 let input = r#"
1095 fn hello() {
1096 print("hello");
1097 }
1098 hello();
1099 "#;
1100 assert!(parse_cyclo_program(input).is_ok());
1101 }
1102
1103 #[test]
1104 fn test_if_stmt() {
1105 let input = r#"
1106 if (value)
1107 {
1108 print("hello");
1109 }
1110 "#;
1111 assert!(parse_cyclo_program(input).is_ok());
1112 }
1113
1114 #[test]
1115 fn test_if_stmt_expression_value_comp() {
1116 let input = r#"
1117 if (value == other_value)
1118 {
1119 print("hello");
1120 }
1121 "#;
1122 assert!(parse_cyclo_program(input).is_ok());
1123 }
1124
1125 #[test]
1126 fn test_if_stmt_expression() {
1127 let input = r#"
1128 if (1 == 1)
1129 {
1130 print("hello");
1131 }
1132 "#;
1133 assert!(parse_cyclo_program(input).is_ok());
1134 }
1135
1136 #[test]
1137 fn test_if_else_stmt() {
1138 let input = r#"
1139 if (value)
1140 {
1141 print("hello");
1142 }
1143 else {
1144 print("else");
1145 }
1146 "#;
1147 assert!(parse_cyclo_program(input).is_ok());
1148 }
1149 #[test]
1150 fn test_while_stmt() {
1151 let input = r#"
1152 while (value)
1153 {
1154 print("hello");
1155 let i = 1;
1156 }
1157 "#;
1158 assert!(parse_cyclo_program(input).is_ok());
1159 }
1160 #[test]
1161 fn test_for_loop_stmt() {
1162 let input = r#"
1163 for (let i = 0; i < 20; i++)
1164 {
1165 print(i);
1166 }
1167 "#;
1168 assert!(parse_cyclo_program(input).is_ok());
1169 }
1170
1171 #[test]
1172 fn test_for_loop_stmt_reverse() {
1173 let input = r#"
1174 for (let i = 40; i < 10; i--)
1175 {
1176 print(i);
1177 }
1178 "#;
1179 assert!(parse_cyclo_program(input).is_ok());
1180 }
1181
1182 #[test]
1183 fn test_access_and_set_value_in_list() {
1184 let input = r#"
1185 let val: i32 = array[i+1];
1186 array[i+1] = 1;
1187 "#;
1188 assert!(parse_cyclo_program(input).is_ok());
1189 }
1190}