cyclang_parser/
lib.rs

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            // hack, need to do this through the type system i.e let val: i64 = ..;
176            let parse_i32: Result<i32, _> = val_str.parse();
177            match parse_i32 {
178                Err(_) => {
179                    // ignore i32 error and try to parse i64
180                    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            // Does this handle no args?
268            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            // Get function type or default to none
280            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            // TODO: fix this so it handles the different cases properly instead of this hack
328            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            //TODO: improve this logic
370            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            //TODO: Identify > and < signs
376            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(); // consume lbracket [
427            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            // could array var be an expression?
434            let array_var = array_expr_inner.next().unwrap().as_str();
435            array_expr_inner.next(); // skip [
436            let array_index = parse_expression(array_expr_inner.next().unwrap())?;
437            inner_pairs.next(); // skip = sign
438            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            // TODO: only returns first pair
479            // should this iterate through all pairs?
480            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    // todo: fix
819    // #[test]
820    // fn test_parse_len_stmt_assign() {
821    //     let input = r#"let value = len(value) - 1;"#;
822    //     assert!(parse_cyclo_program(input).is_ok());
823    // }
824
825    #[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        // Return stmt not returning correct ast
956        // Returning Binaray(Expr)
957        // Instead of ReturnStmt(Binary(Expr))
958        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    // func to validate that the return statement AST is correct
989    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        // assert!(output.unwrap().contains(&func_expr)); to test?
1090    }
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}