Skip to main content

typr_core/processes/parsing/
elements.rs

1use crate::components::error_message::help_data::HelpData;
2use crate::components::error_message::help_message::ErrorMsg;
3use crate::components::error_message::syntax_error::SyntaxError;
4use crate::components::language::argument_value::ArgumentValue;
5use crate::components::language::operators::op;
6use crate::components::language::operators::Op;
7use crate::components::language::var::Var;
8use crate::components::language::Lang;
9use crate::components::r#type::argument_type::ArgumentType;
10use crate::components::r#type::Type;
11use crate::processes::parsing::base_parse;
12use crate::processes::parsing::lang_token::LangToken;
13use crate::processes::parsing::operation_priority::PriorityTokens;
14use crate::processes::parsing::types::if_type;
15use crate::processes::parsing::types::label;
16use crate::processes::parsing::types::ltype;
17use crate::processes::parsing::types::pascal_case_no_space;
18use crate::processes::parsing::types::primitive_types;
19
20use crate::processes::parsing::vector_priority::VectorPriority;
21use crate::utils::builder;
22use nom::branch::alt;
23use nom::bytes::complete::escaped;
24use nom::bytes::complete::is_not;
25use nom::bytes::complete::tag;
26use nom::bytes::complete::take_while1;
27use nom::character::complete::alpha1;
28use nom::character::complete::alphanumeric1;
29use nom::character::complete::char;
30use nom::character::complete::digit1;
31use nom::character::complete::multispace0;
32use nom::character::complete::multispace1;
33use nom::character::complete::one_of;
34use nom::combinator::not;
35use nom::combinator::opt;
36use nom::combinator::recognize;
37use nom::multi::many0;
38use nom::multi::many1;
39use nom::sequence::delimited;
40use nom::sequence::preceded;
41use nom::sequence::terminated;
42use nom::IResult;
43use nom::Parser;
44use nom_locate::LocatedSpan;
45use std::process::exit;
46
47type Span<'a> = LocatedSpan<&'a str, String>;
48
49pub fn is_pascal_case(name: &str) -> bool {
50    let res = recognize(pascal_case_no_space).parse(name.into());
51    match res {
52        Ok((_, _)) => true,
53        Err(_) => false,
54    }
55}
56
57fn number_helper(s: Span) -> IResult<Span, Lang> {
58    let res = (opt(tag("-")), digit1, tag("."), digit1).parse(s);
59    match res {
60        Ok((s, (sign, d1, _dot, d2))) => {
61            let sign2 = sign.unwrap_or(LocatedSpan::new_extra("", d1.clone().extra));
62            let n = format!("{}{}.{}", sign2, d1, d2).parse::<f32>().unwrap();
63            Ok((
64                s,
65                Lang::Number {
66                    value: n,
67                    help_data: sign2.into(),
68                },
69            ))
70        }
71        Err(r) => Err(r),
72    }
73}
74
75pub fn number(s: Span) -> IResult<Span, Lang> {
76    terminated(number_helper, multispace0).parse(s)
77}
78
79fn integer(s: Span) -> IResult<Span, Lang> {
80    let res = terminated((opt(tag("-")), digit1), multispace0).parse(s);
81    match res {
82        Ok((s, (minus, d))) => {
83            let symbol = match minus {
84                Some(_) => "-",
85                None => "",
86            }
87            .to_string()
88                + d.as_ref();
89            Ok((
90                s,
91                Lang::Integer {
92                    value: symbol.parse::<i32>().unwrap(),
93                    help_data: d.into(),
94                },
95            ))
96        }
97        Err(r) => Err(r),
98    }
99}
100
101fn get_value(l: LocatedSpan<&str, String>) -> Lang {
102    match l.clone().into_fragment() {
103        "true" | "TRUE" => Lang::Bool {
104            value: true,
105            help_data: l.into(),
106        },
107        "false" | "FALSE" => Lang::Bool {
108            value: false,
109            help_data: l.into(),
110        },
111        _ => panic!("No other boolean notation alolwed"),
112    }
113}
114
115fn null_value(s: Span) -> IResult<Span, Lang> {
116    let res = alt((
117        terminated(terminated(tag("NULL"), not(body_char)), multispace0),
118        terminated(terminated(tag("null"), not(body_char)), multispace0),
119    ))
120    .parse(s);
121    match res {
122        Ok((s, n)) => Ok((s, Lang::Null(n.into()))),
123        Err(r) => Err(r),
124    }
125}
126
127fn na_value(s: Span) -> IResult<Span, Lang> {
128    let res = alt((
129        terminated(terminated(tag("NA"), not(body_char)), multispace0),
130        terminated(terminated(tag("na"), not(body_char)), multispace0),
131    ))
132    .parse(s);
133    match res {
134        Ok((s, n)) => Ok((s, Lang::NA(n.into()))),
135        Err(r) => Err(r),
136    }
137}
138
139fn boolean(s: Span) -> IResult<Span, Lang> {
140    let res = alt((
141        terminated(terminated(tag("true"), not(body_char)), multispace0),
142        terminated(terminated(tag("TRUE"), not(body_char)), multispace0),
143        terminated(terminated(tag("false"), not(body_char)), multispace0),
144        terminated(terminated(tag("FALSE"), not(body_char)), multispace0),
145    ))
146    .parse(s);
147    match res {
148        Ok((s, ls)) => Ok((s, get_value(ls))),
149        Err(r) => Err(r),
150    }
151}
152
153pub fn chars(s: Span) -> IResult<Span, Lang> {
154    terminated(alt((double_quotes, single_quotes)), multispace0).parse(s)
155}
156
157pub fn double_quotes(input: Span) -> IResult<Span, Lang> {
158    let res = delimited(
159        char('"'),
160        opt(escaped(is_not("\\\""), '\\', alt((char('"'), char('\''))))),
161        char('"'),
162    )
163    .parse(input);
164    match res {
165        Ok((s, st)) => {
166            let content = st.clone().map(|span| span.to_string()).unwrap_or_default();
167            let location = st
168                .map(|span| span.into())
169                .unwrap_or_else(|| s.clone().into());
170            Ok((
171                s,
172                Lang::Char {
173                    value: content,
174                    help_data: location,
175                },
176            ))
177        }
178        Err(r) => Err(r),
179    }
180}
181
182pub fn single_quotes(input: Span) -> IResult<Span, Lang> {
183    let res = delimited(
184        char('\''),
185        opt(escaped(is_not("\\'"), '\\', alt((char('"'), char('\''))))),
186        char('\''),
187    )
188    .parse(input);
189    match res {
190        Ok((s, st)) => {
191            let content = st.clone().map(|span| span.to_string()).unwrap_or_default();
192            let location = st
193                .map(|span| span.into())
194                .unwrap_or_else(|| s.clone().into());
195            Ok((
196                s,
197                Lang::Char {
198                    value: content,
199                    help_data: location,
200                },
201            ))
202        }
203        Err(r) => Err(r),
204    }
205}
206
207fn starting_char(s: Span) -> IResult<Span, (char, HelpData)> {
208    let res = one_of("abcdefghijklmnopqrstuvwxyz_")(s);
209    match res {
210        Ok((s, val)) => Ok((s.clone(), (val, s.into()))),
211        Err(r) => Err(r),
212    }
213}
214
215fn body_char(s: Span) -> IResult<Span, (char, HelpData)> {
216    let res = one_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789")(s);
217    match res {
218        Ok((s, val)) => Ok((s.clone(), (val, s.into()))),
219        Err(r) => Err(r),
220    }
221}
222
223pub fn variable_exp(s: Span) -> IResult<Span, (String, HelpData)> {
224    let res = (starting_char, many0(body_char)).parse(s);
225    match res {
226        Ok((s, ((s1, h), v))) => {
227            let res2 = v.iter().map(|(val, _h)| *val).collect::<String>();
228            Ok((s, (format!("{}{}", s1, res2), h.clone())))
229        }
230        Err(r) => Err(r),
231    }
232}
233
234fn type_annotation(s: Span) -> IResult<Span, Type> {
235    delimited(tag("<"), ltype, tag(">")).parse(s)
236}
237
238pub enum Case {
239    Maj,
240    Min,
241}
242
243fn variable_exp_2(s: Span) -> IResult<Span, (String, Case, HelpData)> {
244    let res = variable_exp.parse(s);
245    match res {
246        Ok((s, (name, h))) => Ok((s, (name, Case::Min, h))),
247        Err(r) => Err(r),
248    }
249}
250
251fn pascal_case_2(s: Span) -> IResult<Span, (String, Case, HelpData)> {
252    let res = pascal_case.parse(s);
253    match res {
254        Ok((s, (name, h))) => Ok((s, (name, Case::Maj, h))),
255        Err(r) => Err(r),
256    }
257}
258
259fn quoted_variable(s: Span) -> IResult<Span, (String, Case, HelpData)> {
260    let res = delimited(char('`'), is_not("`"), char('`')).parse(s);
261
262    match res {
263        Ok((s, st)) => Ok((s, (format!("`{}`", st.clone()), Case::Min, st.into()))),
264        Err(r) => Err(r),
265    }
266}
267
268pub fn variable_recognizer(s: Span) -> IResult<Span, (String, HelpData)> {
269    let res = alt((quoted_variable, pascal_case_2, variable_exp_2)).parse(s);
270    match res {
271        Ok((s, (s1, _case, h))) => Ok((s, (s1, h))),
272        Err(r) => Err(r),
273    }
274}
275
276fn variable_helper(s: Span) -> IResult<Span, (Lang, Case)> {
277    let res = (
278        alt((quoted_variable, pascal_case_2, variable_exp_2)),
279        opt(type_annotation),
280    )
281        .parse(s);
282    match res {
283        Ok((s, ((v, case, h), typ))) => {
284            let res = Var::from_name(&v)
285                .set_type(typ.unwrap_or(builder::empty_type()))
286                .set_help_data(h);
287            Ok((s, (res.into(), case)))
288        }
289        Err(r) => Err(r),
290    }
291}
292
293pub fn variable(s: Span) -> IResult<Span, (Lang, Case)> {
294    terminated(variable_helper, multispace0).parse(s)
295}
296
297pub fn argument(s: Span) -> IResult<Span, ArgumentType> {
298    let res = (
299        terminated(label, multispace0),
300        terminated(tag(":"), multispace0),
301        ltype,
302        opt(terminated(tag(","), multispace0)),
303    )
304        .parse(s);
305    match res {
306        Ok((s, (e1, _, e2, _))) => Ok((s, ArgumentType(e1, e2, false))),
307        Err(r) => Err(r),
308    }
309}
310
311fn equality_params(s: Span) -> IResult<Span, Span> {
312    terminated(alt((tag("="), tag(":"))), multispace0).parse(s)
313}
314
315fn argument_val(s: Span) -> IResult<Span, ArgumentValue> {
316    let res = (
317        terminated(alphanumeric1, multispace0),
318        equality_params,
319        single_element,
320        opt(terminated(tag(","), multispace0)),
321    )
322        .parse(s);
323    match res {
324        Ok((s, (e1, _, e2, _))) => Ok((s, ArgumentValue(e1.to_string(), e2))),
325        Err(r) => Err(r),
326    }
327}
328
329pub fn parse_block(input: Span) -> IResult<Span, Span> {
330    recognize(parse_nested_braces).parse(input)
331}
332
333fn parse_nested_braces(input: Span) -> IResult<Span, Span> {
334    recognize(delimited(
335        tag("{"),
336        many0(alt((
337            parse_nested_braces,
338            recognize(take_while1(|c| c != '{' && c != '}')),
339        ))),
340        tag("}"),
341    ))
342    .parse(input)
343}
344
345pub fn r_function(s: Span) -> IResult<Span, Lang> {
346    let res = (
347        terminated(alt((tag("function"), tag("\\"))), multispace0),
348        terminated(tag("("), multispace0),
349        many0(terminated(terminated(variable, opt(tag(","))), multispace0)),
350        terminated(tag(")"), multispace0),
351        terminated(parse_block, multispace0),
352    )
353        .parse(s);
354    match res {
355        Ok((_s, (id, _op, _args, _cl, _exp))) if *id.fragment() == "fn" => {
356            panic!("{}", SyntaxError::FunctionWithoutType(id.into()).display())
357        }
358        Ok((s, (id, _op, args, _cl, exp))) => {
359            let args = args.iter().map(|(arg, _)| arg).cloned().collect::<Vec<_>>();
360            Ok((
361                s,
362                Lang::RFunction {
363                    parameters: args,
364                    body: exp.to_string(),
365                    help_data: id.into(),
366                },
367            ))
368        }
369        Err(r) => Err(r),
370    }
371}
372
373pub fn simple_function(s: Span) -> IResult<Span, Lang> {
374    let res = (
375        terminated(tag("fn"), multispace0),
376        terminated(tag("("), multispace0),
377        many0(argument),
378        terminated(tag(")"), multispace0),
379        opt(terminated(tag(":"), multispace0)),
380        opt(terminated(alt((if_type, ltype)), multispace0)),
381        //alt((scope, parse_elements))
382        scope,
383    )
384        .parse(s);
385    match res {
386        Ok((s, (_, _, args, _, Some(_), Some(typ), exp))) => Ok((
387            s,
388            Lang::Function {
389                parameters: args,
390                return_type: typ,
391                body: Box::new(exp),
392                help_data: HelpData::default(),
393            },
394        )),
395        Ok((_s, (_, _, _args, _cp, None, None, _exp))) => {
396            panic!("You forgot to specify the function return type: 'fn(...): Type'");
397        }
398        Ok((_s, (_, _, _args, _, Some(tag), None, _exp))) => {
399            panic!(
400                "{}",
401                SyntaxError::FunctionWithoutReturnType(tag.into()).display()
402            );
403        }
404        Ok((_s, (_, _, _args, _, None, Some(typ), _exp))) => {
405            eprintln!(
406                "The type '{}' should be preceded by a ':' :\n 'fn(...): {}'",
407                typ.clone(),
408                typ.clone()
409            );
410            exit(1)
411        }
412        Err(r) => Err(r),
413    }
414}
415
416fn function(s: Span) -> IResult<Span, Lang> {
417    simple_function.parse(s)
418}
419
420fn key_value(s: Span) -> IResult<Span, Lang> {
421    let res = (
422        recognize(variable),
423        terminated(tag("="), multispace0),
424        single_element,
425    )
426        .parse(s);
427    match res {
428        Ok((s, (v, _eq, el))) => Ok((
429            s,
430            Lang::KeyValue {
431                key: (*v).into(),
432                value: Box::new(el),
433                help_data: v.into(),
434            },
435        )),
436        Err(r) => Err(r),
437    }
438}
439
440fn values(s: Span) -> IResult<Span, Vec<Lang>> {
441    many0(terminated(
442        alt((key_value, parse_elements)),
443        terminated(opt(tag(",")), multispace0),
444    ))
445    .parse(s)
446}
447
448pub fn variable2(s: Span) -> IResult<Span, Lang> {
449    let res = variable.parse(s);
450    match res {
451        Ok((s, (lang, _))) => Ok((s, lang)),
452        Err(r) => Err(r),
453    }
454}
455
456fn array_indexing(s: Span) -> IResult<Span, Lang> {
457    let res = (alt((scope, variable2)), array).parse(s);
458
459    match res {
460        Ok((s, (lang1, lang2))) => Ok((
461            s,
462            Lang::ArrayIndexing {
463                identifier: Box::new(lang1.clone()),
464                indexing: Box::new(lang2),
465                help_data: lang1.into(),
466            },
467        )),
468        Err(r) => Err(r),
469    }
470}
471
472fn dataframe_exp(s: Span) -> IResult<Span, Lang> {
473    let res = (
474        alt((tag("data__frame"), tag("data.frame"))),
475        terminated(tag("("), multispace0),
476        many0(argument_val),
477        terminated(tag(")"), multispace0),
478    )
479        .parse(s);
480    match res {
481        Ok((s, (start, _, args, _))) => Ok((
482            s,
483            Lang::DataFrame {
484                value: args.clone(),
485                help_data: start.into(),
486            },
487        )),
488        Err(r) => Err(r),
489    }
490}
491
492fn function_application(s: Span) -> IResult<Span, Lang> {
493    let res = (
494        alt((scope, variable2)),
495        terminated(tag("("), multispace0),
496        values,
497        terminated(tag(")"), multispace0),
498    )
499        .parse(s);
500    match res {
501        Ok((s, (exp, _, v, _))) => Ok((
502            s,
503            Lang::FunctionApp {
504                identifier: Box::new(exp.clone()),
505                arguments: v.clone(),
506                help_data: exp.into(),
507            },
508        )),
509        Err(r) => Err(r),
510    }
511}
512
513fn array(s: Span) -> IResult<Span, Lang> {
514    let res = (
515        terminated(tag("["), multispace0),
516        values,
517        terminated(tag("]"), multispace0),
518    )
519        .parse(s);
520    match res {
521        Ok((s, (_, v, _))) => Ok((
522            s,
523            Lang::Array {
524                value: v.clone(),
525                help_data: v.into(),
526            },
527        )),
528        Err(r) => Err(r),
529    }
530}
531
532pub fn vector(s: Span) -> IResult<Span, Lang> {
533    let res = (
534        terminated(tag("c("), multispace0),
535        values,
536        terminated(tag(")"), multispace0),
537    )
538        .parse(s);
539    match res {
540        Ok((s, (_, v, _))) => Ok((
541            s,
542            Lang::Vector {
543                value: v.clone(),
544                help_data: v.into(),
545            },
546        )),
547        Err(r) => Err(r),
548    }
549}
550
551fn sequence(s: Span) -> IResult<Span, Lang> {
552    let res = (
553        terminated(tag("seq["), multispace0),
554        values,
555        terminated(tag("]"), multispace0),
556    )
557        .parse(s);
558    match res {
559        Ok((s, (_, v, _))) => Ok((
560            s,
561            Lang::Sequence {
562                body: v.clone(),
563                help_data: v.into(),
564            },
565        )),
566        Err(r) => Err(r),
567    }
568}
569
570fn constructor_call(s: Span) -> IResult<Span, Lang> {
571    let res = (
572        pascal_case,
573        terminated(tag(":"), multispace0),
574        terminated(tag("{"), multispace0),
575        many0(argument_val),
576        terminated(tag("}"), multispace0),
577    )
578    .parse(s);
579    match res {
580        Ok((s, ((name, h), _, _, args, _))) => Ok((
581            s,
582            Lang::ConstructorCall {
583                type_name: name,
584                fields: args,
585                help_data: h,
586            },
587        )),
588        Err(r) => Err(r),
589    }
590}
591
592fn array_constructor_call(s: Span) -> IResult<Span, Lang> {
593    let res = (
594        pascal_case,
595        tag(":["),
596        multispace0,
597        values,
598        terminated(tag("]"), multispace0),
599    )
600    .parse(s);
601    match res {
602        Ok((s, ((name, h), _, _, elems, _))) => Ok((
603            s,
604            Lang::ArrayConstructorCall {
605                type_name: name,
606                elements: elems,
607                help_data: h,
608            },
609        )),
610        Err(r) => Err(r),
611    }
612}
613
614fn record_identifier(s: Span) -> IResult<Span, Span> {
615    alt((tag("record"), tag("object"), tag("list"), tag(":"))).parse(s)
616}
617
618pub fn record(s: Span) -> IResult<Span, Lang> {
619    let res = (
620        opt(record_identifier),
621        terminated(alt((tag("{"), tag("("))), multispace0),
622        many0(argument_val),
623        terminated(alt((tag("}"), tag(")"))), multispace0),
624    )
625        .parse(s);
626    match res {
627        Ok((s, (Some(start), _, args, _))) => Ok((
628            s,
629            Lang::List {
630                value: args.clone(),
631                help_data: start.into(),
632            },
633        )),
634        Ok((_s, (None, _ob, args, _))) => {
635            if args.is_empty() {
636                panic!("Error: the scope shouldn't be empty")
637            } else {
638                eprintln!("{}", _s);
639                panic!("You forgot to put a record identifier before the bracket: ':{{...}}'");
640            }
641        }
642        Err(r) => Err(r),
643    }
644}
645
646fn pascal_case_helper(s: Span) -> IResult<Span, (String, HelpData)> {
647    let res = (one_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), alpha1).parse(s);
648    match res {
649        Ok((s, (t1, t2))) => Ok((s.clone(), (format!("{}{}", t1, t2), s.into()))),
650        Err(r) => Err(r),
651    }
652}
653
654fn pascal_case(s: Span) -> IResult<Span, (String, HelpData)> {
655    pascal_case_helper.parse(s)
656}
657
658fn union_constructor(s: Span) -> IResult<Span, Lang> {
659    let res = (
660        pascal_case,
661        terminated(tag("."), multispace0),
662        pascal_case,
663        opt((
664            terminated(tag(":"), multispace0),
665            terminated(tag("{"), multispace0),
666            many0(argument_val),
667            terminated(tag("}"), multispace0),
668        )),
669    )
670    .parse(s);
671    match res {
672        Ok((s, ((union_name, h), _, (variant_name, _), None))) => Ok((
673            s,
674            Lang::UnionConstructor {
675                union_name,
676                variant_name,
677                fields: vec![],
678                help_data: h,
679            },
680        )),
681        Ok((s, ((union_name, h), _, (variant_name, _), Some((_, _, fields, _))))) => Ok((
682            s,
683            Lang::UnionConstructor {
684                union_name,
685                variant_name,
686                fields,
687                help_data: h,
688            },
689        )),
690        Err(r) => Err(r),
691    }
692}
693
694fn parenthese_value(s: Span) -> IResult<Span, Lang> {
695    delimited(
696        terminated(tag("("), multispace0),
697        parse_elements,
698        terminated(tag(")"), multispace0),
699    )
700    .parse(s)
701}
702
703pub fn tag_exp(s: Span) -> IResult<Span, Lang> {
704    let res = terminated((tag("."), pascal_case, opt(parenthese_value)), multispace0).parse(s);
705    match res {
706        Ok((s, (dot, (n, _h), None))) => Ok((
707            s,
708            Lang::Tag {
709                name: n,
710                value: Box::new(Lang::Empty(dot.clone().into())),
711                help_data: dot.into(),
712            },
713        )),
714        Ok((s, (dot, (n, _h), Some(val)))) => Ok((
715            s,
716            Lang::Tag {
717                name: n,
718                value: Box::new(val),
719                help_data: dot.into(),
720            },
721        )),
722        Err(r) => Err(r),
723    }
724}
725
726fn dotdotdot(s: Span) -> IResult<Span, Lang> {
727    let res = terminated(tag("..."), multispace0).parse(s);
728    match res {
729        Ok((s, d)) => Ok((s, Lang::Empty(d.into()))),
730        Err(r) => Err(r),
731    }
732}
733
734fn else_exp(s: Span) -> IResult<Span, Lang> {
735    let res = (
736        terminated(tag("else"), multispace0),
737        terminated(tag("{"), multispace0),
738        parse_elements,
739        terminated(tag("}"), multispace0),
740    )
741        .parse(s);
742    match res {
743        Ok((s, (_else, _o, exp, _c))) => Ok((s, exp)),
744        Err(r) => Err(r),
745    }
746}
747
748fn else_if_exp(s: Span) -> IResult<Span, Lang> {
749    preceded(terminated(tag("else"), multispace1), if_exp).parse(s)
750}
751
752fn if_exp(s: Span) -> IResult<Span, Lang> {
753    let res = (
754        terminated(tag("if"), multispace0),
755        terminated(tag("("), multispace0),
756        parse_elements,
757        terminated(tag(")"), multispace0),
758        terminated(tag("{"), multispace0),
759        parse_elements,
760        terminated(tag("}"), multispace0),
761        opt(alt((else_if_exp, else_exp))),
762    )
763        .parse(s);
764    match res {
765        Ok((s, (_if, _op, cond, _cp, _o, exp, _c, els))) => Ok((
766            s,
767            Lang::If {
768                condition: Box::new(cond),
769                if_block: Box::new(exp),
770                else_block: Box::new(els.unwrap_or(Lang::Empty(HelpData::default()))),
771                help_data: _if.into(),
772            },
773        )),
774        Err(r) => Err(r),
775    }
776}
777
778/// Parse a tag pattern with a variable binding in parentheses: `.Some(a)`
779fn tag_pattern_with_var(s: Span) -> IResult<Span, Lang> {
780    let res = (
781        tag("."),
782        pascal_case,
783        delimited(
784            terminated(tag("("), multispace0),
785            variable2,
786            terminated(tag(")"), multispace0),
787        ),
788    )
789        .parse(s);
790    match res {
791        Ok((s, (dot, (n, _h), var))) => Ok((
792            s,
793            Lang::Tag {
794                name: n,
795                value: Box::new(var),
796                help_data: dot.into(),
797            },
798        )),
799        Err(r) => Err(r),
800    }
801}
802
803/// Parse a tag pattern without binding: `.None`
804fn tag_pattern_no_var(s: Span) -> IResult<Span, Lang> {
805    let res = (tag("."), pascal_case).parse(s);
806    match res {
807        Ok((s, (dot, (n, _h)))) => Ok((
808            s,
809            Lang::Tag {
810                name: n,
811                value: Box::new(Lang::Empty(dot.clone().into())),
812                help_data: dot.into(),
813            },
814        )),
815        Err(r) => Err(r),
816    }
817}
818
819/// Parse a wildcard pattern: `_`
820fn wildcard_pattern(s: Span) -> IResult<Span, Lang> {
821    let res = terminated(tag("_"), multispace0).parse(s);
822    match res {
823        Ok((s, underscore)) => Ok((
824            s,
825            Lang::Variable {
826                name: "_".to_string(),
827                is_opaque: false,
828                related_type: builder::empty_type(),
829                help_data: underscore.into(),
830            },
831        )),
832        Err(r) => Err(r),
833    }
834}
835
836/// Parse a type pattern with a variable binding: `x as int`, `y as bool`, etc.
837fn type_pattern(s: Span) -> IResult<Span, Lang> {
838    let res = (
839        terminated(variable_exp, multispace0),
840        terminated(tag("as"), multispace1),
841        terminated(primitive_types, multispace0),
842    )
843        .parse(s);
844    match res {
845        Ok((s, ((name, h), _as, typ))) => Ok((
846            s,
847            Lang::TypePattern {
848                variable_name: name,
849                matched_type: typ,
850                help_data: h,
851            },
852        )),
853        Err(r) => Err(r),
854    }
855}
856
857/// Parse a match pattern: `.Some(a)`, `.None`, `x as int`, `:{nom: n}`, `:{a, b}`, `_`, or a variable
858fn match_pattern(s: Span) -> IResult<Span, Lang> {
859    terminated(
860        alt((
861            tag_pattern_with_var,
862            tag_pattern_no_var,
863            record,
864            tuple_exp,
865            type_pattern,
866            wildcard_pattern,
867            variable2,
868        )),
869        multispace0,
870    )
871    .parse(s)
872}
873
874/// Parse a pattern branch: `pattern => expression,`
875fn pattern_branch(s: Span) -> IResult<Span, (Lang, Box<Lang>)> {
876    let res = (
877        terminated(match_pattern, multispace0),
878        terminated(tag("=>"), multispace0),
879        terminated(parse_elements, multispace0),
880        opt(terminated(tag(","), multispace0)),
881    )
882        .parse(s);
883    match res {
884        Ok((s, (pat, _arr, lang, _vir))) => Ok((s, (pat, Box::new(lang)))),
885        Err(r) => Err(r),
886    }
887}
888
889/// Parse a match expression with pattern matching:
890/// `match expr { .Some(a) => a, .None => 0, _ => default }`
891fn match_exp(s: Span) -> IResult<Span, Lang> {
892    let res = (
893        terminated(tag("match"), multispace1),
894        terminated(alt((scope, variable2)), multispace0),
895        terminated(tag("{"), multispace0),
896        many1(pattern_branch),
897        terminated(tag("}"), multispace0),
898    )
899        .parse(s);
900    match res {
901        Ok((s, (_m, exp, _o, bs, _c))) => Ok((
902            s,
903            Lang::Match {
904                target: Box::new(exp),
905                branches: bs,
906                help_data: _m.into(),
907            },
908        )),
909        Err(r) => Err(r),
910    }
911}
912
913pub fn tuple_exp(s: Span) -> IResult<Span, Lang> {
914    let res = (
915        terminated(alt((tag("list"), tag(":"))), multispace0),
916        terminated(alt((tag("{"), tag("("))), multispace0),
917        values,
918        terminated(alt((tag("}"), tag(")"))), multispace0),
919    )
920        .parse(s);
921    match res {
922        Ok((s, (id, _op, vals, _cl))) => Ok((
923            s,
924            Lang::Tuple {
925                value: vals,
926                help_data: id.into(),
927            },
928        )),
929        Err(r) => Err(r),
930    }
931}
932
933fn int_or_var(s: Span) -> IResult<Span, Lang> {
934    alt((integer, variable2)).parse(s)
935}
936
937fn create_range(params: &[Lang]) -> Lang {
938    if params.len() == 2 {
939        Lang::FunctionApp {
940            identifier: Box::new(Var::from_name("seq").to_language()),
941            arguments: vec![
942                params[0].clone(),
943                params[1].clone(),
944                Lang::Integer {
945                    value: 1,
946                    help_data: HelpData::default(),
947                },
948            ],
949            help_data: params.to_vec().into(),
950        }
951    } else {
952        Lang::FunctionApp {
953            identifier: Box::new(Var::from_name("seq").to_language()),
954            arguments: vec![params[0].clone(), params[1].clone(), params[2].clone()],
955            help_data: params.to_vec().into(),
956        }
957    }
958}
959
960fn range(s: Span) -> IResult<Span, Lang> {
961    let res = (
962        int_or_var,
963        tag(":"),
964        opt(terminated(int_or_var, tag(":"))),
965        int_or_var,
966    )
967        .parse(s);
968    //from_name().to_language()
969    match res {
970        Ok((s, (iv1, _sep, None, iv2))) => Ok((s, create_range(&[iv1.clone(), iv2.clone()]))),
971        Ok((s, (iv1, _sep, Some(iv0), iv2))) => {
972            Ok((s, create_range(&[iv1.clone(), iv2.clone(), iv0.clone()])))
973        }
974        Err(r) => Err(r),
975    }
976}
977
978fn function_application2(s: Span) -> IResult<Span, Lang> {
979    let res = recognize(function_application).parse(s);
980    match res {
981        Ok((s, fun_app)) => Ok((
982            s,
983            Lang::Exp {
984                value: fun_app.to_string(),
985                help_data: fun_app.into(),
986            },
987        )),
988        Err(r) => Err(r),
989    }
990}
991
992fn dot_variable(s: Span) -> IResult<Span, Lang> {
993    let res = preceded(tag("."), variable2).parse(s);
994    match res {
995        Ok((
996            s,
997            Lang::Variable {
998                name: n,
999                is_opaque: b,
1000                related_type: c,
1001                help_data: d,
1002            },
1003        )) => Ok((
1004            s,
1005            Lang::Variable {
1006                name: format!(".{}", n),
1007                is_opaque: b,
1008                related_type: c,
1009                help_data: d,
1010            },
1011        )),
1012        Ok((_s, _)) => todo!(),
1013        Err(r) => Err(r),
1014    }
1015}
1016
1017fn element_operator2(s: Span) -> IResult<Span, (Lang, Op)> {
1018    let res = (
1019        opt(op),
1020        alt((
1021            function_application2,
1022            null_value,
1023            number,
1024            integer,
1025            chars,
1026            boolean,
1027            variable2,
1028            dot_variable,
1029        )),
1030    )
1031        .parse(s);
1032    match res {
1033        Ok((s, (Some(ope), ele))) => Ok((s, (ele, ope))),
1034        Ok((s, (None, ele))) => Ok((s.clone(), (ele, Op::Empty(s.into())))),
1035        Err(r) => Err(r),
1036    }
1037}
1038
1039fn vectorial_bloc(s: Span) -> IResult<Span, Lang> {
1040    let res = (
1041        terminated(tag("@{"), multispace0),
1042        recognize(many1(element_operator2)),
1043        terminated(tag("}@"), multispace0),
1044    )
1045        .parse(s);
1046    match res {
1047        Ok((s, (_start, bloc, _end))) => Ok((
1048            s,
1049            Lang::VecBlock {
1050                value: bloc.fragment().to_string(),
1051                help_data: bloc.into(),
1052            },
1053        )),
1054        Err(r) => Err(r),
1055    }
1056}
1057
1058fn lambda(s: Span) -> IResult<Span, Lang> {
1059    let res = (
1060        tag("\\"),
1061        terminated(tag("("), multispace0),
1062        many0(terminated(variable, opt((tag(","), multispace0)))),
1063        terminated(tag(")"), multispace0),
1064        parse_elements,
1065    )
1066        .parse(s);
1067    match res {
1068        Ok((s, (start, _, v, _, body))) => Ok((
1069            s,
1070            Lang::Lambda {
1071                parameters: v.iter().map(|(var, _)| var).cloned().collect(),
1072                body: Box::new(body.clone()),
1073                help_data: start.into(),
1074            },
1075        )),
1076        Err(r) => Err(r),
1077    }
1078}
1079
1080fn not_exp(s: Span) -> IResult<Span, Lang> {
1081    let res = (
1082        tag("!"),
1083        alt((
1084            tag_exp,
1085            range,
1086            lambda,
1087            boolean,
1088            number,
1089            integer,
1090            chars,
1091            match_exp,
1092            if_exp,
1093            dotdotdot,
1094            vector,
1095            record,
1096            r_function,
1097            function,
1098            tuple_exp,
1099            function_application,
1100            array_indexing,
1101            variable2,
1102            scope,
1103            array,
1104        )),
1105    )
1106        .parse(s);
1107    match res {
1108        Ok((s, (not_op, lang))) => Ok((
1109            s,
1110            Lang::Not {
1111                value: Box::new(lang),
1112                help_data: not_op.into(),
1113            },
1114        )),
1115        Err(r) => Err(r),
1116    }
1117}
1118
1119fn array_variant(s: Span) -> IResult<Span, Lang> {
1120    alt((vector, sequence)).parse(s)
1121}
1122
1123fn js_block(s: Span) -> IResult<Span, Lang> {
1124    let res = (terminated(tag("JS"), multispace0), scope).parse(s);
1125
1126    match res {
1127        Ok((s, (js, body))) => Ok((s, Lang::JSBlock(Box::new(body), 0, js.into()))),
1128        Err(r) => Err(r),
1129    }
1130}
1131
1132fn primitive(s: Span) -> IResult<Span, Lang> {
1133    alt((null_value, na_value, boolean, number, integer, chars)).parse(s)
1134}
1135
1136pub fn return_exp(s: Span) -> IResult<Span, Lang> {
1137    let res = terminated(
1138        delimited(tag("return "), parse_elements, tag(";")),
1139        multispace0,
1140    )
1141    .parse(s);
1142    match res {
1143        Ok((s, el)) => Ok((
1144            s,
1145            Lang::Return {
1146                value: Box::new(el.clone()),
1147                help_data: el.into(),
1148            },
1149        )),
1150        Err(r) => Err(r),
1151    }
1152}
1153
1154pub fn break_exp(s: Span) -> IResult<Span, Vec<Lang>> {
1155    let res = tag("break;").parse(s);
1156    match res {
1157        Ok((s, el)) => Ok((s, vec![Lang::Break(el.into())])),
1158        Err(r) => Err(r),
1159    }
1160}
1161
1162// main
1163pub fn single_element(s: Span) -> IResult<Span, Lang> {
1164    alt((
1165        alt((
1166            not_exp,
1167            tag_exp,
1168            union_constructor,
1169            range,
1170            lambda,
1171            primitive,
1172            js_block,
1173            return_exp,
1174            match_exp,
1175            if_exp,
1176            dotdotdot,
1177            array_variant,
1178        )),
1179        alt((
1180            dataframe_exp,
1181            array_constructor_call,
1182            constructor_call,
1183            record,
1184            r_function,
1185            function,
1186            tuple_exp,
1187            function_application,
1188            array_indexing,
1189            variable2,
1190            scope,
1191            array,
1192        )),
1193    ))
1194    .parse(s)
1195}
1196
1197pub fn scope(s: Span) -> IResult<Span, Lang> {
1198    let res = (
1199        terminated(alt((tag("("), tag("{"))), multispace0),
1200        opt(base_parse),
1201        terminated(alt((tag(")"), tag("}"))), multispace0),
1202    )
1203    .parse(s);
1204    match res {
1205        Ok((s, (open, Some(v), _))) if v.is_empty() => Ok((
1206            s,
1207            Lang::Scope {
1208                body: vec![],
1209                help_data: open.into(),
1210            },
1211        )),
1212        Ok((s, (_, Some(v), _))) => Ok((
1213            s,
1214            Lang::Scope {
1215                body: v.clone(),
1216                help_data: v.into(),
1217            },
1218        )),
1219        Ok((_s, (_, None, _))) => panic!("Error: the scope shouldn't be empty"),
1220        Err(r) => Err(r),
1221    }
1222}
1223
1224fn element_operator_token(s: Span) -> IResult<Span, LangToken> {
1225    match op.parse(s) {
1226        Ok((s, op)) => Ok((s, LangToken::Operator(op))),
1227        Err(r) => Err(r),
1228    }
1229}
1230
1231fn single_element_token(s: Span) -> IResult<Span, LangToken> {
1232    match single_element.parse(s) {
1233        Ok((s, op)) => Ok((s, LangToken::Expression(op))),
1234        Err(r) => Err(r),
1235    }
1236}
1237
1238pub fn elements(s: Span) -> IResult<Span, Lang> {
1239    let res = many1(alt((single_element_token, element_operator_token))).parse(s);
1240    match res {
1241        Ok((s, v)) => {
1242            if v.len() == 1 {
1243                Ok((s, v[0].clone().into()))
1244            } else {
1245                Ok((s, VectorPriority::from(v).run()))
1246            }
1247        }
1248        Err(r) => Err(r),
1249    }
1250}
1251
1252// main
1253pub fn parse_elements(s: Span) -> IResult<Span, Lang> {
1254    alt((vectorial_bloc, elements)).parse(s)
1255}
1256
1257#[cfg(test)]
1258mod tests {
1259    use super::*;
1260    use crate::utils::fluent_parser::FluentParser;
1261
1262    #[test]
1263    #[should_panic]
1264    fn test_empty_scope() {
1265        let _ = "{  }".parse::<Lang>();
1266    }
1267
1268    #[test]
1269    fn test_function_with_empty_scope3() {
1270        let res = simple_function("fn(): int { 5 }".into()).unwrap().1;
1271        assert_eq!(res.simple_print(), "Function");
1272    }
1273
1274    #[test]
1275    fn test_variable1() {
1276        let res = variable_exp("hello".into()).unwrap().1 .0;
1277        assert_eq!(res, "hello", "Should return the variable name 'hello'");
1278    }
1279
1280    #[test]
1281    fn test_simple_variable1() {
1282        let res = variable_exp("hello".into()).unwrap().1 .0;
1283        assert_eq!(res, "hello", "Should return the variable name 'hello'");
1284    }
1285
1286    #[test]
1287    fn test_addition1() {
1288        let res = "1 + 2".parse::<Lang>().unwrap();
1289        dbg!(&res);
1290        assert_eq!(res.simple_print(), "Operator", "Should parse 1 + 2");
1291    }
1292
1293    #[test]
1294    fn test_addition2() {
1295        let res = "1 + 2 + 3".parse::<Lang>().unwrap();
1296        dbg!(&res);
1297        assert_eq!(res.simple_print(), "Operator", "Should parse 1 + 2 + 3");
1298    }
1299
1300    #[test]
1301    fn test_multiplication1() {
1302        let res = "1 + 2 * 3".parse::<Lang>().unwrap();
1303        dbg!(&res);
1304        assert_eq!(
1305            res.simple_print(),
1306            "Operator",
1307            "Should put multiplication first 1 + 2 * 3"
1308        );
1309    }
1310
1311    #[test]
1312    fn test_multiplication2() {
1313        let res = "1 * 2 + 3".parse::<Lang>().unwrap();
1314        dbg!(&res);
1315        assert_eq!(
1316            res.simple_print(),
1317            "Operator",
1318            "Should put multiplication first 1 * 2 + 3"
1319        );
1320    }
1321
1322    #[test]
1323    fn test_multiplication3() {
1324        let res = "1 * 2 + 3 * 4".parse::<Lang>().unwrap();
1325        dbg!(&res);
1326        assert_eq!(
1327            res.simple_print(),
1328            "Operator",
1329            "Should put multiplication first 1 * 2 + 3 * 4"
1330        );
1331    }
1332
1333    #[test]
1334    fn test_accessor1() {
1335        let res = "3 + personne$age ".parse::<Lang>().unwrap();
1336        dbg!(&res);
1337        assert_eq!(
1338            res.simple_print(),
1339            "Operator",
1340            "Should put multiplication first 1 * 2 + 3 * 4"
1341        );
1342    }
1343
1344    #[test]
1345    fn test_and1() {
1346        let res = "true & true".parse::<Lang>().unwrap();
1347        dbg!(&res);
1348        assert_eq!(res.simple_print(), "Operator", "Should accept '&&'");
1349    }
1350
1351    #[test]
1352    fn test_array_indexing0() {
1353        let res = array_indexing("name[1, 2, 3]".into()).unwrap().1;
1354        dbg!(&res);
1355        assert!(true);
1356    }
1357
1358    #[test]
1359    fn test_array_indexing() {
1360        let fp = FluentParser::new().push("name[1, 2, 3]").parse_next();
1361        println!("fp: {}", fp);
1362        assert!(true);
1363    }
1364
1365    #[test]
1366    fn test_quoted_variable() {
1367        let res = quoted_variable("`+`".into()).unwrap().1;
1368        assert_eq!(res.0, "`+`");
1369    }
1370
1371    #[test]
1372    fn test_uniform_function_call() {
1373        let res = FluentParser::new().push("true.not()").parse_next();
1374        dbg!(&res.next_code());
1375        assert!(true);
1376    }
1377
1378    #[test]
1379    fn test_key_value1() {
1380        let res = key_value("sep = '3'".into()).unwrap().1;
1381        dbg!(&res);
1382        assert!(true);
1383    }
1384
1385    #[test]
1386    fn test_empty_char0() {
1387        let res = single_element("''".into()).unwrap().1;
1388        dbg!(&res);
1389        assert!(true);
1390    }
1391
1392    #[test]
1393    fn test_empty_char1() {
1394        let res = primitive("''".into()).unwrap().1;
1395        dbg!(&res);
1396        assert!(true);
1397    }
1398
1399    #[test]
1400    fn test_empty_char2() {
1401        let res = chars("''".into()).unwrap().1;
1402        dbg!(&res);
1403        assert!(true);
1404    }
1405
1406    // ==================== Null Tests ====================
1407
1408    #[test]
1409    fn test_null_value_lowercase() {
1410        let res = null_value("null ".into()).unwrap().1;
1411        assert_eq!(res.simple_print(), "Null");
1412    }
1413
1414    #[test]
1415    fn test_null_value_uppercase() {
1416        let res = null_value("NULL ".into()).unwrap().1;
1417        assert_eq!(res.simple_print(), "Null");
1418    }
1419
1420    #[test]
1421    fn test_null_via_primitive() {
1422        let res = primitive("null ".into()).unwrap().1;
1423        assert_eq!(res.simple_print(), "Null");
1424    }
1425
1426    #[test]
1427    fn test_null_via_single_element() {
1428        let res = single_element("null ".into()).unwrap().1;
1429        assert_eq!(res.simple_print(), "Null");
1430    }
1431
1432    #[test]
1433    fn test_null_parse_lang() {
1434        let res = "null".parse::<Lang>().unwrap();
1435        assert_eq!(res.simple_print(), "Null");
1436    }
1437
1438    #[test]
1439    fn test_null_type_check() {
1440        let fp = FluentParser::new()
1441            .push("let x: null <- null;")
1442            .parse_type_next()
1443            .push("x")
1444            .parse_next();
1445        assert_eq!(fp.get_last_type(), crate::utils::builder::null_type());
1446    }
1447
1448    // ==================== Match Pattern Tests ====================
1449
1450    #[test]
1451    fn test_match_pattern_tag_with_binding() {
1452        let input = "match x { .Some(a) => a, .None => 0 }";
1453        let res = match_exp(input.into()).unwrap().1;
1454        dbg!(&res);
1455        assert_eq!(res.simple_print(), "Match");
1456    }
1457
1458    #[test]
1459    fn test_match_pattern_with_wildcard() {
1460        let input = "match x { .Some(a) => a, _ => 0 }";
1461        let res = match_exp(input.into()).unwrap().1;
1462        dbg!(&res);
1463        assert_eq!(res.simple_print(), "Match");
1464    }
1465
1466    #[test]
1467    fn test_match_pattern_tag_without_binding() {
1468        let input = "match x { .None => 7 }";
1469        let res = match_exp(input.into()).unwrap().1;
1470        assert_eq!(res.simple_print(), "Match");
1471    }
1472
1473    #[test]
1474    fn test_match_pattern_multiple_branches() {
1475        let input = "match value { .Some(a) => a + 1, .None => 0, _ => 9 }";
1476        let res = match_exp(input.into()).unwrap().1;
1477        assert_eq!(res.simple_print(), "Match");
1478        // Verify we have 3 branches
1479        if let Lang::Match { branches, .. } = &res {
1480            assert_eq!(branches.len(), 3, "Should have 3 branches");
1481        } else {
1482            panic!("Expected Match variant");
1483        }
1484    }
1485
1486    #[test]
1487    fn test_match_pattern_via_single_element() {
1488        let input = "match x { .Some(a) => a, .None => 0 } ";
1489        let res = single_element(input.into()).unwrap().1;
1490        assert_eq!(res.simple_print(), "Match");
1491    }
1492
1493    #[test]
1494    fn test_match_pattern_branch_tag_with_var() {
1495        let input = ".Some(a) => a + 1, ";
1496        let res = pattern_branch(input.into()).unwrap().1;
1497        let (pattern, _body) = res;
1498        assert_eq!(pattern.simple_print(), "Tag");
1499    }
1500
1501    #[test]
1502    fn test_match_pattern_branch_wildcard() {
1503        let input = "_ => 42 ";
1504        let res = pattern_branch(input.into()).unwrap().1;
1505        let (pattern, _body) = res;
1506        assert_eq!(pattern.simple_print(), "Variable(_)");
1507    }
1508
1509    #[test]
1510    fn test_match_pattern_branch_tag_no_binding() {
1511        let input = ".None => 7, ";
1512        let res = pattern_branch(input.into()).unwrap().1;
1513        let (pattern, body) = res;
1514        assert_eq!(pattern.simple_print(), "Tag");
1515        assert_eq!(body.simple_print(), "Integer");
1516    }
1517
1518    #[test]
1519    fn test_wildcard_pattern() {
1520        let input = "_ ";
1521        let res = wildcard_pattern(input.into()).unwrap().1;
1522        assert_eq!(res.simple_print(), "Variable(_)");
1523    }
1524
1525    #[test]
1526    fn test_tag_pattern_with_var() {
1527        let input = ".Some(a)";
1528        let res = tag_pattern_with_var(input.into()).unwrap().1;
1529        assert_eq!(res.simple_print(), "Tag");
1530        if let Lang::Tag {
1531            name, value: inner, ..
1532        } = &res
1533        {
1534            assert_eq!(name, "Some");
1535            assert_eq!(inner.simple_print(), "Variable(a)");
1536        } else {
1537            panic!("Expected Tag variant");
1538        }
1539    }
1540
1541    #[test]
1542    fn test_tag_pattern_no_var() {
1543        let input = ".None ";
1544        let res = tag_pattern_no_var(input.into()).unwrap().1;
1545        assert_eq!(res.simple_print(), "Tag");
1546        if let Lang::Tag {
1547            name, value: inner, ..
1548        } = &res
1549        {
1550            assert_eq!(name, "None");
1551            assert_eq!(inner.simple_print(), "Empty");
1552        } else {
1553            panic!("Expected Tag variant");
1554        }
1555    }
1556
1557    #[test]
1558    fn test_match_pattern_multiline() {
1559        let input = "match result {
1560            .Some(value) => value + 1,
1561            .None => 0,
1562            _ => 99
1563        } ";
1564        let res = match_exp(input.into()).unwrap().1;
1565        assert_eq!(res.simple_print(), "Match");
1566        if let Lang::Match { branches, .. } = &res {
1567            assert_eq!(branches.len(), 3);
1568        } else {
1569            panic!("Expected Match variant");
1570        }
1571    }
1572
1573    // ==================== Type Pattern Tests ====================
1574
1575    #[test]
1576    fn test_type_pattern_int() {
1577        let input = "x as int ";
1578        let res = type_pattern(input.into()).unwrap().1;
1579        assert!(
1580            res.simple_print().starts_with("TypePattern"),
1581            "Should parse 'x as int' as TypePattern"
1582        );
1583        if let Lang::TypePattern { variable_name: name, .. } = &res {
1584            assert_eq!(name, "x");
1585        } else {
1586            panic!("Expected TypePattern variant");
1587        }
1588    }
1589
1590    #[test]
1591    fn test_type_pattern_bool() {
1592        let input = "y as bool ";
1593        let res = type_pattern(input.into()).unwrap().1;
1594        if let Lang::TypePattern { variable_name: name, .. } = &res {
1595            assert_eq!(name, "y");
1596        } else {
1597            panic!("Expected TypePattern variant");
1598        }
1599    }
1600
1601    #[test]
1602    fn test_type_pattern_num() {
1603        let input = "val as num ";
1604        let res = type_pattern(input.into()).unwrap().1;
1605        if let Lang::TypePattern { variable_name: name, .. } = &res {
1606            assert_eq!(name, "val");
1607        } else {
1608            panic!("Expected TypePattern variant");
1609        }
1610    }
1611
1612    #[test]
1613    fn test_type_pattern_char() {
1614        let input = "s as char ";
1615        let res = type_pattern(input.into()).unwrap().1;
1616        if let Lang::TypePattern { variable_name: name, .. } = &res {
1617            assert_eq!(name, "s");
1618        } else {
1619            panic!("Expected TypePattern variant");
1620        }
1621    }
1622
1623    #[test]
1624    fn test_match_with_type_patterns() {
1625        let input = "match x { y as int => y + 1, z as bool => 0 } ";
1626        let res = match_exp(input.into()).unwrap().1;
1627        assert_eq!(res.simple_print(), "Match");
1628        if let Lang::Match { branches, .. } = &res {
1629            assert_eq!(branches.len(), 2, "Should have 2 branches");
1630            assert!(
1631                branches[0].0.simple_print().starts_with("TypePattern"),
1632                "First branch should be a TypePattern"
1633            );
1634            assert!(
1635                branches[1].0.simple_print().starts_with("TypePattern"),
1636                "Second branch should be a TypePattern"
1637            );
1638        } else {
1639            panic!("Expected Match variant");
1640        }
1641    }
1642
1643    #[test]
1644    fn test_match_mixed_tag_and_type_patterns() {
1645        let input = "match value {
1646            .Some(a) => a,
1647            x as int => x + 1,
1648            _ => 0
1649        } ";
1650        let res = match_exp(input.into()).unwrap().1;
1651        assert_eq!(res.simple_print(), "Match");
1652        if let Lang::Match { branches, .. } = &res {
1653            assert_eq!(branches.len(), 3, "Should have 3 branches");
1654            assert_eq!(branches[0].0.simple_print(), "Tag");
1655            assert!(branches[1].0.simple_print().starts_with("TypePattern"));
1656            assert_eq!(branches[2].0.simple_print(), "Variable(_)");
1657        } else {
1658            panic!("Expected Match variant");
1659        }
1660    }
1661
1662    #[test]
1663    fn test_type_pattern_in_match_pattern() {
1664        let input = "x as int ";
1665        let res = match_pattern(input.into()).unwrap().1;
1666        assert!(
1667            res.simple_print().starts_with("TypePattern"),
1668            "match_pattern should accept type patterns"
1669        );
1670    }
1671
1672    // ==================== List/Record Pattern Tests ====================
1673
1674    #[test]
1675    fn test_record_pattern_colon_syntax() {
1676        let input = ":{nom: n, age: a} ";
1677        let res = match_pattern(input.into()).unwrap().1;
1678        assert_eq!(
1679            res.simple_print(),
1680            "Record",
1681            "Should parse record pattern as Record"
1682        );
1683        if let Lang::List { value: fields, .. } = &res {
1684            assert_eq!(fields.len(), 2);
1685            assert_eq!(fields[0].get_argument(), "nom");
1686            assert_eq!(fields[1].get_argument(), "age");
1687        } else {
1688            panic!("Expected List variant");
1689        }
1690    }
1691
1692    #[test]
1693    fn test_record_pattern_list_syntax() {
1694        let input = "list(nom = n, age = a) ";
1695        let res = match_pattern(input.into()).unwrap().1;
1696        assert_eq!(res.simple_print(), "Record");
1697        if let Lang::List { value: fields, .. } = &res {
1698            assert_eq!(fields.len(), 2);
1699            assert_eq!(fields[0].get_argument(), "nom");
1700            assert_eq!(fields[1].get_argument(), "age");
1701        } else {
1702            panic!("Expected List variant");
1703        }
1704    }
1705
1706    #[test]
1707    fn test_match_with_record_pattern() {
1708        let input = "match x { :{nom: n, age: a} => a, _ => 0 } ";
1709        let res = match_exp(input.into()).unwrap().1;
1710        assert_eq!(res.simple_print(), "Match");
1711        if let Lang::Match { branches, .. } = &res {
1712            assert_eq!(branches.len(), 2, "Should have 2 branches");
1713            assert_eq!(
1714                branches[0].0.simple_print(),
1715                "Record",
1716                "First branch should be a Record pattern"
1717            );
1718            assert_eq!(branches[1].0.simple_print(), "Variable(_)");
1719        } else {
1720            panic!("Expected Match variant");
1721        }
1722    }
1723
1724    #[test]
1725    fn test_match_with_list_pattern() {
1726        let input = "match x { list(nom = n, age = a) => a, _ => 0 } ";
1727        let res = match_exp(input.into()).unwrap().1;
1728        assert_eq!(res.simple_print(), "Match");
1729        if let Lang::Match { branches, .. } = &res {
1730            assert_eq!(branches.len(), 2);
1731            assert_eq!(branches[0].0.simple_print(), "Record");
1732        } else {
1733            panic!("Expected Match variant");
1734        }
1735    }
1736
1737    #[test]
1738    fn test_match_mixed_record_tag_type_patterns() {
1739        let input = "match value {
1740            .Some(a) => a,
1741            :{nom: n, age: a} => a,
1742            x as int => x + 1,
1743            _ => 0
1744        } ";
1745        let res = match_exp(input.into()).unwrap().1;
1746        assert_eq!(res.simple_print(), "Match");
1747        if let Lang::Match { branches, .. } = &res {
1748            assert_eq!(branches.len(), 4);
1749            assert_eq!(branches[0].0.simple_print(), "Tag");
1750            assert_eq!(branches[1].0.simple_print(), "Record");
1751            assert!(branches[2].0.simple_print().starts_with("TypePattern"));
1752            assert_eq!(branches[3].0.simple_print(), "Variable(_)");
1753        } else {
1754            panic!("Expected Match variant");
1755        }
1756    }
1757
1758    #[test]
1759    fn test_record_pattern_single_field() {
1760        let input = ":{nom: n} ";
1761        let res = match_pattern(input.into()).unwrap().1;
1762        assert_eq!(res.simple_print(), "Record");
1763        if let Lang::List { value: fields, .. } = &res {
1764            assert_eq!(fields.len(), 1);
1765            assert_eq!(fields[0].get_argument(), "nom");
1766        } else {
1767            panic!("Expected List variant");
1768        }
1769    }
1770
1771    // ==================== Tuple Pattern Tests ====================
1772
1773    #[test]
1774    fn test_tuple_pattern_colon_syntax() {
1775        let input = ":{a, b, c} ";
1776        let res = match_pattern(input.into()).unwrap().1;
1777        assert_eq!(res.simple_print(), "Tuple");
1778        if let Lang::Tuple {
1779            value: elements, ..
1780        } = &res
1781        {
1782            assert_eq!(elements.len(), 3);
1783        } else {
1784            panic!("Expected Tuple variant");
1785        }
1786    }
1787
1788    #[test]
1789    fn test_tuple_pattern_list_syntax() {
1790        let input = "list(a, b, c) ";
1791        let res = match_pattern(input.into()).unwrap().1;
1792        assert_eq!(res.simple_print(), "Tuple");
1793        if let Lang::Tuple {
1794            value: elements, ..
1795        } = &res
1796        {
1797            assert_eq!(elements.len(), 3);
1798        } else {
1799            panic!("Expected Tuple variant");
1800        }
1801    }
1802
1803    #[test]
1804    fn test_tuple_pattern_two_elements() {
1805        let input = ":{x, y} ";
1806        let res = match_pattern(input.into()).unwrap().1;
1807        assert_eq!(res.simple_print(), "Tuple");
1808        if let Lang::Tuple {
1809            value: elements, ..
1810        } = &res
1811        {
1812            assert_eq!(elements.len(), 2);
1813        } else {
1814            panic!("Expected Tuple variant");
1815        }
1816    }
1817
1818    #[test]
1819    fn test_match_with_tuple_pattern() {
1820        let input = "match x { :{a, b, c} => a + c, _ => 0 } ";
1821        let res = match_exp(input.into()).unwrap().1;
1822        assert_eq!(res.simple_print(), "Match");
1823        if let Lang::Match { branches, .. } = &res {
1824            assert_eq!(branches.len(), 2);
1825            assert_eq!(branches[0].0.simple_print(), "Tuple");
1826            assert_eq!(branches[1].0.simple_print(), "Variable(_)");
1827        } else {
1828            panic!("Expected Match variant");
1829        }
1830    }
1831
1832    #[test]
1833    fn test_match_with_list_tuple_pattern() {
1834        let input = "match x { list(a, b, c) => a + c, _ => 0 } ";
1835        let res = match_exp(input.into()).unwrap().1;
1836        assert_eq!(res.simple_print(), "Match");
1837        if let Lang::Match { branches, .. } = &res {
1838            assert_eq!(branches.len(), 2);
1839            assert_eq!(branches[0].0.simple_print(), "Tuple");
1840        } else {
1841            panic!("Expected Match variant");
1842        }
1843    }
1844
1845    #[test]
1846    fn test_match_mixed_all_pattern_types() {
1847        let input = "match value {
1848            .Some(a) => a,
1849            :{nom: n, age: a} => a,
1850            :{x, y} => x + y,
1851            z as int => z + 1,
1852            _ => 0
1853        } ";
1854        let res = match_exp(input.into()).unwrap().1;
1855        assert_eq!(res.simple_print(), "Match");
1856        if let Lang::Match { branches, .. } = &res {
1857            assert_eq!(branches.len(), 5);
1858            assert_eq!(branches[0].0.simple_print(), "Tag");
1859            assert_eq!(branches[1].0.simple_print(), "Record");
1860            assert_eq!(branches[2].0.simple_print(), "Tuple");
1861            assert!(branches[3].0.simple_print().starts_with("TypePattern"));
1862            assert_eq!(branches[4].0.simple_print(), "Variable(_)");
1863        } else {
1864            panic!("Expected Match variant");
1865        }
1866    }
1867
1868    #[test]
1869    fn test_character_constructor_fn() {
1870        let input = "fn(name: char, attack: int, health: int): Character {\n    :{ name: name, attack: attack, health: health }\n}";
1871        let res = simple_function(input.into());
1872        match &res {
1873            Ok((remaining, _)) => {
1874                println!("SUCCESS, remaining: {:?}", **remaining);
1875                assert!(remaining.is_empty(), "Should consume entire input, remaining: {:?}", **remaining);
1876            }
1877            Err(e) => panic!("Parse failed: {:?}", e),
1878        }
1879    }
1880
1881    #[test]
1882    fn test_scope_with_record_body() {
1883        let input = "{\n    :{ name: name, attack: attack, health: health }\n}";
1884        let res = scope(input.into());
1885        match &res {
1886            Ok((remaining, _)) => {
1887                println!("scope SUCCESS, remaining: {:?}", **remaining);
1888            }
1889            Err(e) => println!("scope FAILED: {:?}", e),
1890        }
1891        assert!(res.is_ok(), "scope should succeed");
1892    }
1893
1894    #[test]
1895    fn test_record_parse_directly() {
1896        use crate::processes::parsing::base_parse;
1897        let input = ":{ name: name, attack: attack, health: health }";
1898        let res = base_parse(input.into());
1899        println!("base_parse result: {:?}", res.as_ref().map(|(r, v): &(_, Vec<_>)| (*r.fragment(), v.len())));
1900        assert!(res.is_ok());
1901        let (remaining, elems) = res.unwrap();
1902        println!("  remaining: {:?}", *remaining.fragment());
1903        println!("  elements count: {}", elems.len());
1904        for (i, el) in elems.iter().enumerate() {
1905            println!("  elem[{}]: {}", i, el.simple_print());
1906        }
1907    }
1908
1909    #[test]
1910    fn test_parse_elements_record() {
1911        let input = ":{ name: name, attack: attack, health: health }";
1912        let res = parse_elements(input.into());
1913        match &res {
1914            Ok((remaining, lang)) => println!("parse_elements OK: {}, remaining: {:?}", lang.simple_print(), **remaining),
1915            Err(e) => println!("parse_elements FAILED: {:?}", e),
1916        }
1917        assert!(res.is_ok(), "parse_elements should succeed on record");
1918    }
1919
1920    #[test]
1921    fn test_single_element_record() {
1922        let input = ":{ name: name, attack: attack, health: health }";
1923        let res = single_element(input.into());
1924        match &res {
1925            Ok((remaining, lang)) => println!("single_element OK: {}, remaining: {:?}", lang.simple_print(), **remaining),
1926            Err(e) => println!("single_element FAILED: {:?}", e),
1927        }
1928        assert!(res.is_ok(), "single_element should succeed on record");
1929    }
1930
1931    #[test]
1932    fn test_record_logic_inline() {
1933        let input = ":{ name: name, attack: attack, health: health }";
1934        let res = record(input.into());
1935        match &res {
1936            Ok((remaining, lang)) => println!("record OK: {}, remaining: {:?}", lang.simple_print(), **remaining),
1937            Err(e) => println!("record FAILED: {:?}", e),
1938        }
1939        assert!(res.is_ok(), "record should succeed");
1940    }
1941}