Skip to main content

typr_core/processes/parsing/
mod.rs

1#![allow(dead_code)]
2
3pub mod elements;
4pub mod indexation;
5pub mod lang_token;
6pub mod operation_priority;
7pub mod type_token;
8pub mod types;
9pub mod vector_priority;
10
11use crate::components::context::config::Config;
12use crate::components::error_message::help_data::HelpData;
13use crate::components::error_message::syntax_error::SyntaxError;
14use crate::components::language::operators::custom_op;
15use crate::components::language::operators::Op;
16use crate::components::language::var::Var;
17use crate::components::language::Lang;
18use crate::components::language::ModulePosition;
19use crate::components::r#type::Type;
20use crate::processes::parsing::elements::break_exp;
21use crate::processes::parsing::elements::chars;
22use crate::processes::parsing::elements::parse_elements;
23use crate::processes::parsing::elements::return_exp;
24use crate::processes::parsing::elements::scope;
25use crate::processes::parsing::elements::single_element;
26use crate::processes::parsing::elements::tag_exp;
27use crate::processes::parsing::elements::tuple_exp;
28use crate::processes::parsing::elements::variable;
29use crate::processes::parsing::elements::variable2;
30use crate::processes::parsing::elements::variable_exp;
31use crate::processes::parsing::elements::variable_recognizer;
32use crate::processes::parsing::elements::vector;
33use crate::processes::parsing::elements::Case;
34use crate::processes::parsing::types::ltype;
35use crate::processes::parsing::types::type_alias;
36use nom::branch::alt;
37use nom::bytes::complete::tag;
38use nom::character::complete::line_ending;
39use nom::character::complete::multispace0;
40use nom::character::complete::not_line_ending;
41use nom::combinator::map;
42use nom::combinator::opt;
43use nom::multi::many0;
44use nom::multi::separated_list0;
45use nom::sequence::delimited;
46use nom::sequence::pair;
47use nom::sequence::preceded;
48use nom::sequence::terminated;
49use nom::IResult;
50use nom::Parser;
51use nom_locate::LocatedSpan;
52use std::ops::Deref;
53
54type Span<'a> = LocatedSpan<&'a str, String>;
55
56use std::cell::RefCell;
57
58thread_local! {
59    static PARSE_ERRORS: RefCell<Vec<SyntaxError>> = RefCell::new(Vec::new());
60}
61
62fn push_parse_error(err: SyntaxError) {
63    PARSE_ERRORS.with(|e| e.borrow_mut().push(err));
64}
65
66fn take_parse_errors() -> Vec<SyntaxError> {
67    PARSE_ERRORS.with(|e| e.borrow_mut().drain(..).collect())
68}
69
70/// Result of parsing containing the AST and any syntax errors collected
71#[derive(Debug, Clone)]
72pub struct ParseResult {
73    pub ast: Lang,
74    pub errors: Vec<SyntaxError>,
75}
76
77impl ParseResult {
78    pub fn new(ast: Lang) -> Self {
79        let errors = take_parse_errors();
80        ParseResult { ast, errors }
81    }
82
83    pub fn has_errors(&self) -> bool {
84        !self.errors.is_empty()
85    }
86
87    pub fn get_ast(&self) -> &Lang {
88        &self.ast
89    }
90
91    pub fn get_clean_ast(&self) -> Lang {
92        self.ast.clone()
93    }
94}
95
96fn pattern_var(s: Span) -> IResult<Span, (Vec<Lang>, Option<String>)> {
97    let res = alt((tag_exp, variable2)).parse(s);
98    match res {
99        Ok((
100            s,
101            Lang::Tag {
102                name, value: val, ..
103            },
104        )) => {
105            if let Lang::Variable {
106                name: name2,
107                is_opaque: mutopa,
108                related_type: typ,
109                help_data: h,
110            } = *val
111            {
112                Ok((
113                    s,
114                    (
115                        vec![Lang::Variable {
116                            name: name2.to_string(),
117                            is_opaque: mutopa,
118                            related_type: typ,
119                            help_data: h.clone(),
120                        }],
121                        Some(name.to_string()),
122                    ),
123                ))
124            } else {
125                Ok((s, (vec![], Some(name.to_string()))))
126            }
127        }
128        Ok((
129            s,
130            Lang::Variable {
131                name,
132                is_opaque: mutopa,
133                related_type: typ,
134                help_data: h,
135            },
136        )) => Ok((
137            s,
138            (
139                vec![Lang::Variable {
140                    name,
141                    is_opaque: mutopa,
142                    related_type: typ,
143                    help_data: h.clone(),
144                }],
145                None,
146            ),
147        )),
148        Err(r) => Err(r),
149        _ => todo!(),
150    }
151}
152
153fn single_parse(s: Span) -> IResult<Span, Lang> {
154    let res = (parse_elements, opt(terminated(tag(";"), multispace0))).parse(s);
155    match res {
156        Ok((s, (exp, Some(_)))) => Ok((s, exp)),
157        Ok((s, (exp, None))) => {
158            push_parse_error(SyntaxError::ForgottenSemicolon(exp.clone().into()));
159            Ok((s, exp))
160        }
161        Err(r) => Err(r),
162    }
163}
164
165fn equality_operator(s: Span) -> IResult<Span, Span> {
166    terminated(alt((tag("="), tag("<-"))), multispace0).parse(s)
167}
168
169fn base_let_exp(s: Span) -> IResult<Span, Vec<Lang>> {
170    let res = (
171        terminated(tag("let"), multispace0),
172        pattern_var,
173        opt(preceded(terminated(tag(":"), multispace0), ltype)),
174        equality_operator,
175        single_parse,
176    )
177        .parse(s);
178    match res {
179        Ok((
180            s,
181            (
182                _let,
183                (pat_var, None),
184                typ,
185                _eq,
186                Lang::Function {
187                    parameters: params,
188                    return_type: ty,
189                    body,
190                    help_data: h,
191                },
192            ),
193        )) if !params.is_empty() => {
194            let newvar = Var::from_language(pat_var[0].clone())
195                .unwrap()
196                .set_type(params[0].1.clone());
197            Ok((
198                s,
199                vec![Lang::Let {
200                    variable: Box::new(newvar.to_language()),
201                    r#type: typ.unwrap_or(Type::Empty(HelpData::default())),
202                    expression: Box::new(Lang::Function {
203                        parameters: params,
204                        return_type: ty,
205                        body,
206                        help_data: h,
207                    }),
208                    is_public: false,
209                    help_data: _let.into(),
210                }],
211            ))
212        }
213        Ok((s, (_let, (pat_var, None), typ, _eq, body))) => Ok((
214            s,
215            vec![Lang::Let {
216                variable: Box::new(pat_var[0].clone()),
217                r#type: typ.clone().unwrap_or(Type::Empty(HelpData::default())),
218                expression: Box::new(body),
219                is_public: false,
220                help_data: _let.into(),
221            }],
222        )),
223        Ok((s, (_let, (pat_var, Some(_)), typ, eq, body))) => {
224            if pat_var.len() == 1 {
225                Ok((
226                    s,
227                    vec![Lang::Let {
228                        variable: Box::new(pat_var[0].clone()),
229                        r#type: typ.clone().unwrap_or(Type::Empty(HelpData::default())),
230                        expression: Box::new(Lang::Operator {
231                            operator: Op::Dollar(HelpData::default()),
232                            rhs: Box::new(Lang::Number {
233                                value: 0.0,
234                                help_data: eq.into(),
235                            }),
236                            lhs: Box::new(body),
237                            help_data: pat_var.into(),
238                        }),
239                        is_public: false,
240                        help_data: _let.into(),
241                    }],
242                ))
243            } else {
244                Ok((
245                    s,
246                    pat_var
247                        .iter()
248                        .map(|x| Lang::Let {
249                            variable: Box::new(x.clone()),
250                            r#type: typ.clone().unwrap_or(Type::Empty(HelpData::default())),
251                            expression: Box::new(body.clone()),
252                            is_public: false,
253                            help_data: HelpData::default(),
254                        })
255                        .collect::<Vec<_>>(),
256                ))
257            }
258        }
259        Err(r) => Err(r),
260    }
261}
262
263fn let_tuple_exp(s: Span) -> IResult<Span, Vec<Lang>> {
264    let res = (
265        terminated(tag("let"), multispace0),
266        tuple_exp,
267        opt(preceded(terminated(tag(":"), multispace0), ltype)),
268        equality_operator,
269        single_parse,
270    )
271        .parse(s);
272    match res {
273        Ok((
274            s,
275            (
276                _let,
277                Lang::Tuple {
278                    value: elements,
279                    help_data: _th,
280                },
281                typ,
282                _eq,
283                body,
284            ),
285        )) => {
286            let tmp_name = "__tuple_tmp__";
287            let tmp_var = Var::from_name(tmp_name).to_language();
288
289            // First: let __tuple_tmp__ <- body;
290            let tmp_let = Lang::Let {
291                variable: Box::new(tmp_var.clone()),
292                r#type: typ.unwrap_or(Type::Empty(HelpData::default())),
293                expression: Box::new(body),
294                is_public: false,
295                help_data: _let.into(),
296            };
297
298            // Then: let a <- 1.__tuple_tmp__; let b <- 2.__tuple_tmp__; ...
299            let mut result = vec![tmp_let];
300            for (i, elem) in elements.iter().enumerate() {
301                if let Lang::Variable { name, .. } = elem {
302                    if name == "_" {
303                        continue; // skip wildcard
304                    }
305                }
306                result.push(Lang::Let {
307                    variable: Box::new(elem.clone()),
308                    r#type: Type::Empty(HelpData::default()),
309                    expression: Box::new(Lang::Operator {
310                        operator: Op::Dot(HelpData::default()),
311                        rhs: Box::new(Lang::Integer {
312                            value: (i + 1) as i32,
313                            help_data: HelpData::default(),
314                        }),
315                        lhs: Box::new(tmp_var.clone()),
316                        help_data: HelpData::default(),
317                    }),
318                    is_public: false,
319                    help_data: HelpData::default(),
320                });
321            }
322
323            Ok((s, result))
324        }
325        Ok(_) => unreachable!("tuple_exp always returns Lang::Tuple"),
326        Err(r) => Err(r),
327    }
328}
329
330fn let_exp(s: Span) -> IResult<Span, Vec<Lang>> {
331    let res = (opt(terminated(tag("@pub"), multispace0)), base_let_exp).parse(s);
332    match res {
333        Ok((s, (None, le))) => Ok((s, le)),
334        Ok((s, (Some(_pu), le))) => {
335            let new_le = le
336                .iter()
337                .map(|x| match x {
338                    Lang::Let {
339                        variable: var,
340                        r#type: typ,
341                        expression: body,
342                        is_public: _,
343                        help_data: h,
344                    } => {
345                        let vari = Var::from_language(var.deref().clone())
346                            .unwrap()
347                            .to_language();
348                        Lang::Let {
349                            variable: Box::new(vari),
350                            r#type: typ.clone(),
351                            expression: body.clone(),
352                            is_public: true,
353                            help_data: h.clone(),
354                        }
355                    }
356                    lan => lan.clone(),
357                })
358                .collect();
359            Ok((s, new_le))
360        }
361        Err(r) => Err(r),
362    }
363}
364
365fn base_type_exp(s: Span) -> IResult<Span, Lang> {
366    let res = (
367        terminated(tag("type"), multispace0),
368        type_alias,
369        equality_operator,
370        ltype,
371        terminated(tag(";"), multispace0),
372    )
373        .parse(s);
374    match res {
375        Ok((s, (_ty, Type::Alias(name, params, _, h), _eq, ty, _))) => {
376            let h2 = if !params.is_empty() {
377                params[0].clone().into()
378            } else {
379                HelpData::default()
380            };
381            let vari = Var::from_name(&name)
382                .set_type(Type::Params(params.clone(), h2))
383                .to_language();
384            Ok((
385                s,
386                Lang::Alias {
387                    identifier: Box::new(vari),
388                    parameters: params,
389                    target_type: ty,
390                    is_public: false,
391                    help_data: h,
392                },
393            ))
394        }
395        Ok((s, (_ty, _, _eq, _ty2, _))) => Ok((s, Lang::Empty(_ty.into()))),
396        Err(r) => Err(r),
397    }
398}
399
400fn type_exp(s: Span) -> IResult<Span, Vec<Lang>> {
401    let res = (opt(terminated(tag("@pub"), multispace0)), base_type_exp).parse(s);
402    match res {
403        Ok((
404            s,
405            (
406                Some(_pu),
407                Lang::Alias {
408                    identifier: var,
409                    parameters: params,
410                    target_type: typ,
411                    help_data: h,
412                    ..
413                },
414            ),
415        )) => Ok((
416            s,
417            vec![Lang::Alias {
418                identifier: var,
419                parameters: params,
420                target_type: typ,
421                is_public: true,
422                help_data: h,
423            }],
424        )),
425        Ok((
426            s,
427            (
428                None,
429                Lang::Alias {
430                    identifier: var,
431                    parameters: params,
432                    target_type: typ,
433                    help_data: h,
434                    ..
435                },
436            ),
437        )) => {
438            let vari = Var::from_language(var.deref().clone())
439                .unwrap()
440                .to_language();
441            Ok((
442                s,
443                vec![Lang::Alias {
444                    identifier: Box::new(vari),
445                    parameters: params,
446                    target_type: typ,
447                    is_public: false,
448                    help_data: h,
449                }],
450            ))
451        }
452        Err(r) => Err(r),
453        _ => todo!(),
454    }
455}
456
457fn base_opaque_exp(s: Span) -> IResult<Span, Lang> {
458    let res = (
459        terminated(tag("opaque"), multispace0),
460        type_alias,
461        equality_operator,
462        ltype,
463        terminated(tag(";"), multispace0),
464    )
465        .parse(s);
466    match res {
467        Ok((s, (_ty, Type::Alias(name, params, _, h), _eq, ty, _))) => {
468            let vari = Var::from_name(&name)
469                .set_type(Type::Params(params.clone(), params.clone().into()))
470                .set_opacity(true)
471                .to_language();
472            Ok((
473                s,
474                Lang::Alias {
475                    identifier: Box::new(vari),
476                    parameters: params,
477                    target_type: ty,
478                    is_public: false,
479                    help_data: h,
480                },
481            ))
482        }
483        Ok((s, (_ty, _, _eq, _ty2, _))) => Ok((s, Lang::Empty(_ty.into()))),
484        Err(r) => Err(r),
485    }
486}
487
488fn opaque_exp(s: Span) -> IResult<Span, Vec<Lang>> {
489    let res = (opt(terminated(tag("@pub"), multispace0)), base_opaque_exp).parse(s);
490    match res {
491        Ok((
492            s,
493            (
494                Some(_pu),
495                Lang::Alias {
496                    identifier: var,
497                    parameters: params,
498                    target_type: typ,
499                    help_data: h,
500                    ..
501                },
502            ),
503        )) => {
504            let vari = Var::from_language(var.deref().clone())
505                .unwrap()
506                .set_opacity(true)
507                .to_language();
508            Ok((
509                s,
510                vec![Lang::Alias {
511                    identifier: Box::new(vari),
512                    parameters: params,
513                    target_type: typ,
514                    is_public: true,
515                    help_data: h,
516                }],
517            ))
518        }
519        Ok((
520            s,
521            (
522                None,
523                Lang::Alias {
524                    identifier: var,
525                    parameters: params,
526                    target_type: typ,
527                    help_data: h,
528                    ..
529                },
530            ),
531        )) => {
532            let vari = Var::from_language(var.deref().clone())
533                .unwrap()
534                .set_opacity(true)
535                .to_language();
536            Ok((
537                s,
538                vec![Lang::Alias {
539                    identifier: Box::new(vari),
540                    parameters: params,
541                    target_type: typ,
542                    is_public: false,
543                    help_data: h,
544                }],
545            ))
546        }
547        Err(r) => Err(r),
548        _ => todo!(),
549    }
550}
551
552pub fn module(s: Span) -> IResult<Span, Vec<Lang>> {
553    let res = (
554        terminated(tag("module"), multispace0),
555        terminated(variable_recognizer, multispace0),
556        terminated(tag("{"), multispace0),
557        base_parse,
558        terminated(tag("}"), multispace0),
559        opt(terminated(tag(";"), multispace0)),
560    )
561        .parse(s);
562    match res {
563        Ok((s, (modu, (name, _), _op, v, _cl, _dv))) => Ok((
564            s,
565            vec![Lang::Module {
566                name,
567                body: v,
568                module_position: ModulePosition::Internal,
569                config: Config::default(),
570                help_data: modu.into(),
571            }],
572        )),
573        Err(r) => Err(r),
574    }
575}
576
577fn import_module(s: Span) -> IResult<Span, Vec<Lang>> {
578    let res = (
579        terminated(tag("import"), multispace0),
580        terminated(variable_recognizer, multispace0),
581        opt((
582            terminated(tag("as"), multispace0),
583            terminated(variable_recognizer, multispace0),
584        )),
585        opt(terminated(tag(";"), multispace0)),
586    )
587        .parse(s);
588    match res {
589        Ok((s, (import_kw, (name, _), None, _))) => Ok((
590            s,
591            vec![Lang::ModuleImport {
592                value: name,
593                help_data: import_kw.into(),
594            }],
595        )),
596        Ok((s, (_, (name, h), Some((_, (alias, _))), _))) => {
597            let module_var = Lang::Variable {
598                name,
599                is_opaque: false,
600                related_type: Type::Empty(HelpData::default()),
601                help_data: h.clone(),
602            };
603            let alias_var = Var::from_name(&alias).to_language();
604            Ok((
605                s,
606                vec![Lang::Let {
607                    variable: Box::new(alias_var),
608                    r#type: Type::Empty(HelpData::default()),
609                    expression: Box::new(module_var),
610                    is_public: false,
611                    help_data: h,
612                }],
613            ))
614        }
615        Err(r) => Err(r),
616    }
617}
618
619fn assign(s: Span) -> IResult<Span, Vec<Lang>> {
620    let res = (
621        variable,
622        alt((
623            terminated(tag("="), multispace0),
624            terminated(tag("<-"), multispace0),
625        )),
626        parse_elements,
627        opt(terminated(tag(";"), multispace0)),
628    )
629        .parse(s);
630    match res {
631        Ok((s, ((var, _), _eq, exp, Some(_)))) => Ok((
632            s,
633            vec![Lang::Assign {
634                identifier: Box::new(var.clone()),
635                expression: Box::new(exp),
636                help_data: var.into(),
637            }],
638        )),
639        Ok((s, ((var, _), _eq, exp, None))) => {
640            push_parse_error(SyntaxError::ForgottenSemicolon(exp.clone().into()));
641            let assign = Lang::Assign {
642                identifier: Box::new(var.clone()),
643                expression: Box::new(exp),
644                help_data: var.into(),
645            };
646            Ok((s, vec![assign]))
647        }
648        Err(r) => Err(r),
649    }
650}
651
652fn comment(s: Span) -> IResult<Span, Vec<Lang>> {
653    let res = (tag("#"), not_line_ending, opt(line_ending), multispace0).parse(s);
654    match res {
655        Ok((s, (_hashtag, txt, _, _))) => Ok((
656            s,
657            vec![Lang::Comment {
658                value: txt.to_string(),
659                help_data: _hashtag.into(),
660            }],
661        )),
662        Err(r) => Err(r),
663    }
664}
665
666pub fn simple_exp(s: Span) -> IResult<Span, Vec<Lang>> {
667    let res = (parse_elements, opt(terminated(tag(";"), multispace0))).parse(s);
668    match res {
669        Ok((s, (lang, Some(_)))) => Ok((s, vec![lang])),
670        Ok((s, (lang, None))) => {
671            push_parse_error(SyntaxError::ForgottenSemicolon(lang.clone().into()));
672            Ok((s, vec![lang]))
673        }
674        Err(r) => Err(r),
675    }
676}
677
678fn mod_imp(s: Span) -> IResult<Span, Vec<Lang>> {
679    let res = (
680        terminated(tag("mod"), multispace0),
681        terminated(variable_exp, multispace0),
682        terminated(tag(";"), multispace0),
683    )
684        .parse(s);
685    match res {
686        Ok((s, (_mod, (name, _), _sc))) => Ok((
687            s,
688            vec![Lang::ModuleImport {
689                value: name.to_string(),
690                help_data: _mod.into(),
691            }],
692        )),
693        Err(r) => Err(r),
694    }
695}
696
697fn import_var(s: Span) -> IResult<Span, Vec<Lang>> {
698    let res = (
699        terminated(tag("use"), multispace0),
700        variable,
701        terminated(tag(";"), multispace0),
702    )
703        .parse(s);
704    match res {
705        Ok((s, (_use, (lang, case), _sc))) => {
706            let res = match case {
707                Case::Maj => Var::from_language(lang).unwrap().to_alias_lang(),
708                _ => Var::from_language(lang).unwrap().to_let(),
709            };
710            Ok((s, vec![res]))
711        }
712        Err(r) => Err(r),
713    }
714}
715
716fn import_type(s: Span) -> IResult<Span, Vec<Lang>> {
717    let res = (
718        terminated(tag("use"), multispace0),
719        type_alias,
720        terminated(tag(";"), multispace0),
721    )
722        .parse(s);
723
724    match res {
725        Ok((s, (_use, alias, _sc))) => Ok((
726            s,
727            vec![Lang::Import {
728                value: alias,
729                help_data: _use.into(),
730            }],
731        )),
732        Err(r) => Err(r),
733    }
734}
735
736fn tests(s: Span) -> IResult<Span, Vec<Lang>> {
737    let res = (tag("Test"), delimited(tag("["), base_parse, tag("]"))).parse(s);
738    match res {
739        Ok((s, (_t, body))) => Ok((
740            s,
741            vec![Lang::Test {
742                value: body,
743                help_data: _t.into(),
744            }],
745        )),
746        Err(r) => Err(r),
747    }
748}
749
750fn library(s: Span) -> IResult<Span, Vec<Lang>> {
751    let res = (
752        tag("library("),
753        variable_exp,
754        tag(")"),
755        opt(tag(";")),
756        multispace0,
757    )
758        .parse(s);
759
760    match res {
761        Ok((s, (_lib, (var, h), _cl, Some(_col), _))) => Ok((
762            s,
763            vec![Lang::Library {
764                value: var,
765                help_data: h.clone(),
766            }],
767        )),
768        Ok((_, (_lib, _var, _cl, None, _))) => {
769            panic!("You forgot to put a ';' at the end of the line")
770        }
771        Err(r) => Err(r),
772    }
773}
774
775fn use_item_exp(s: Span) -> IResult<Span, crate::components::language::use_lang::UseItem> {
776    use crate::components::language::use_lang::UseItem;
777    // Parse: Ident (as Ident)?
778    let res = (
779        terminated(variable_recognizer, multispace0),
780        opt(preceded(
781            pair(tag("as"), multispace0),
782            terminated(variable_recognizer, multispace0),
783        )),
784    )
785        .parse(s);
786    match res {
787        Ok((s, ((name, _), alias_opt))) => {
788            let alias = alias_opt.map(|(alias_name, _)| alias_name);
789            Ok((s, UseItem { name, alias }))
790        }
791        Err(r) => Err(r),
792    }
793}
794
795fn use_items_selector(
796    s: Span,
797) -> IResult<Span, crate::components::language::use_lang::UseSelector> {
798    use crate::components::language::use_lang::UseSelector;
799    let res = (
800        pair(tag("{"), multispace0),
801        separated_list0(pair(tag(","), multispace0), use_item_exp),
802        opt(pair(tag(","), multispace0)),
803        pair(tag("}"), multispace0),
804    )
805        .parse(s);
806    match res {
807        Ok((s, (_, items, _, _))) => Ok((s, UseSelector::Items(items))),
808        Err(r) => Err(r),
809    }
810}
811
812fn use_selector_exp(s: Span) -> IResult<Span, crate::components::language::use_lang::UseSelector> {
813    use crate::components::language::use_lang::UseSelector;
814    alt((
815        map(terminated(tag("*"), multispace0), |_| UseSelector::Wildcard),
816        use_items_selector,
817    ))
818    .parse(s)
819}
820
821fn use_module_directive(s: Span) -> IResult<Span, Vec<Lang>> {
822    use crate::components::language::use_lang::UseSelector;
823
824    // Parse: use FirstSeg :: ...
825    let res = (
826        terminated(tag("use"), multispace0),
827        terminated(variable_recognizer, multispace0),
828        pair(tag("::"), multispace0),
829    )
830        .parse(s);
831
832    let (s, (use_kw, (first_seg, _), _)) = match res {
833        Ok(r) => r,
834        Err(r) => return Err(r),
835    };
836
837    let mut path = vec![first_seg];
838    let mut current_s = s;
839    let selector;
840
841    loop {
842        match use_selector_exp(current_s.clone()) {
843            Ok((s2, sel)) => {
844                selector = sel;
845                current_s = s2;
846                break;
847            }
848            Err(_) => match terminated(variable_recognizer, multispace0).parse(current_s.clone()) {
849                Ok((s2, (seg, _))) => {
850                    let colon_res: IResult<Span, (Span, Span)> =
851                        pair(tag("::"), multispace0).parse(s2.clone());
852                    match colon_res {
853                        Ok((s3, _)) => {
854                            path.push(seg);
855                            current_s = s3;
856                        }
857                        Err(_) => {
858                            use crate::components::language::use_lang::UseItem;
859                            selector = UseSelector::Items(vec![UseItem {
860                                name: seg,
861                                alias: None,
862                            }]);
863                            current_s = s2;
864                            break;
865                        }
866                    }
867                }
868                Err(e) => return Err(e),
869            },
870        }
871    }
872
873    let res = terminated(tag(";"), multispace0).parse(current_s);
874    let (s, _) = match res {
875        Ok(r) => r,
876        Err(r) => return Err(r),
877    };
878
879    Ok((
880        s,
881        vec![Lang::UseModule {
882            module_path: path,
883            selector,
884            help_data: use_kw.into(),
885        }],
886    ))
887}
888
889fn use_exp(s: Span) -> IResult<Span, Vec<Lang>> {
890    let res = (
891        tag("use("),
892        chars,
893        tag(", "),
894        alt((vector, chars)),
895        terminated(tag(");"), multispace0),
896    )
897        .parse(s);
898    match res {
899        Ok((s, (us, lib, _, members, _))) => Ok((
900            s,
901            vec![Lang::Use {
902                lang: Box::new(lib),
903                members: Box::new(members),
904                help_data: us.into(),
905            }],
906        )),
907        Err(r) => Err(r),
908    }
909}
910
911fn custom_operators(s: Span) -> IResult<Span, (String, HelpData)> {
912    let res = custom_op.parse(s);
913    match res {
914        Ok((s, co)) => Ok((s, (co.clone().to_string(), co.into()))),
915        Err(r) => Err(r),
916    }
917}
918
919fn return_stmt(s: Span) -> IResult<Span, Vec<Lang>> {
920    let (s, e) = return_exp(s)?;
921    Ok((s, vec![e]))
922}
923
924fn stmt_exp(s: Span) -> IResult<Span, Vec<Lang>> {
925    let res = (parse_elements, terminated(tag(";"), multispace0)).parse(s);
926    match res {
927        Ok((s, (lang, _))) => Ok((s, vec![lang])),
928        Err(r) => Err(r),
929    }
930}
931
932fn signature_variable(s: Span) -> IResult<Span, Vec<Lang>> {
933    let res = (
934        tag("@"),
935        alt((variable_recognizer, custom_operators)),
936        terminated(tag(":"), multispace0),
937        ltype,
938        terminated(tag(";"), multispace0),
939    )
940        .parse(s);
941    match res {
942        Ok((s, (at, (name, h), _col, typ, _))) => {
943            let var2 = Var::from_name(&name).set_help_data(h).set_type(typ.clone());
944            Ok((
945                s,
946                vec![Lang::Signature {
947                    identifier: var2,
948                    target_type: typ,
949                    help_data: at.into(),
950                }],
951            ))
952        }
953        Err(r) => Err(r),
954    }
955}
956
957fn signature_opaque(s: Span) -> IResult<Span, Vec<Lang>> {
958    let res = (
959        tag("@"),
960        type_alias,
961        terminated(tag(":"), multispace0),
962        ltype,
963        terminated(tag(";"), multispace0),
964    )
965        .parse(s);
966    match res {
967        Ok((s, (at, Type::Alias(name, _params, _, h), _, typ, _))) => {
968            let var2 = Var::from_name(&name)
969                .set_help_data(h.clone())
970                .set_type(typ.clone());
971            Ok((
972                s,
973                vec![Lang::Signature {
974                    identifier: var2,
975                    target_type: typ,
976                    help_data: at.into(),
977                }],
978            ))
979        }
980        Ok((_s, (_, _, _, _, _))) => todo!(),
981        Err(r) => Err(r),
982    }
983}
984
985pub fn signature(s: Span) -> IResult<Span, Vec<Lang>> {
986    alt((signature_opaque, signature_variable)).parse(s)
987}
988
989fn for_loop(s: Span) -> IResult<Span, Vec<Lang>> {
990    let res = (
991        terminated(tag("for"), multispace0),
992        terminated(tag("("), multispace0),
993        terminated(variable_exp, multispace0),
994        terminated(tag("in"), multispace0),
995        terminated(single_element, multispace0),
996        terminated(tag(")"), multispace0),
997        scope,
998        terminated(tag(";"), multispace0),
999    )
1000        .parse(s);
1001    match res {
1002        Ok((s, (_for, _op, (var_str, _h), _in, iterator, _cl, scop, _semi))) => Ok((
1003            s,
1004            vec![Lang::ForLoop {
1005                identifier: Var::from_name(&var_str),
1006                expression: Box::new(iterator),
1007                body: Box::new(scop),
1008                help_data: _for.into(),
1009            }],
1010        )),
1011        Err(r) => Err(r),
1012    }
1013}
1014
1015fn while_loop(s: Span) -> IResult<Span, Vec<Lang>> {
1016    let res = (
1017        terminated(tag("while"), multispace0),
1018        terminated(tag("("), multispace0),
1019        terminated(single_element, multispace0),
1020        terminated(tag(")"), multispace0),
1021        scope,
1022        terminated(tag(";"), multispace0),
1023    )
1024        .parse(s);
1025    match res {
1026        Ok((s, (_while, _op, condition, _cl, scop, _semi))) => Ok((
1027            s,
1028            vec![Lang::WhileLoop {
1029                condition: Box::new(condition),
1030                body: Box::new(scop),
1031                help_data: _while.into(),
1032            }],
1033        )),
1034        Err(r) => Err(r),
1035    }
1036}
1037
1038fn loop_loop(s: Span) -> IResult<Span, Vec<Lang>> {
1039    let res = (
1040        terminated(tag("loop"), multispace0),
1041        scope,
1042        terminated(tag(";"), multispace0),
1043    )
1044        .parse(s);
1045    match res {
1046        Ok((s, (_loop, scop, _semi))) => Ok((
1047            s,
1048            vec![Lang::Loop {
1049                body: Box::new(scop),
1050                help_data: _loop.into(),
1051            }],
1052        )),
1053        Err(r) => Err(r),
1054    }
1055}
1056
1057fn test_block(s: Span) -> IResult<Span, Vec<Lang>> {
1058    let res = (terminated(tag("Test"), multispace0), scope).parse(s);
1059    //parse_block).parse(s);
1060
1061    match res {
1062        Ok((s, (tst, body))) => Ok((
1063            s,
1064            vec![Lang::TestBlock {
1065                value: Box::new(body),
1066                help_data: tst.into(),
1067            }],
1068        )),
1069        Err(r) => Err(r),
1070    }
1071}
1072
1073// main
1074pub fn base_parse(s: Span) -> IResult<Span, Vec<Lang>> {
1075    let res = (
1076        opt(multispace0),
1077        many0(alt((
1078            alt((
1079                library,
1080                break_exp,
1081                use_exp,
1082                test_block,
1083                while_loop,
1084                loop_loop,
1085                for_loop,
1086                signature,
1087                tests,
1088                import_module,
1089                use_module_directive,
1090                import_type,
1091            )),
1092            alt((
1093                import_var,
1094                mod_imp,
1095                comment,
1096                type_exp,
1097                opaque_exp,
1098                let_tuple_exp,
1099                let_exp,
1100                module,
1101                assign,
1102                return_stmt,
1103                stmt_exp,
1104            )),
1105        ))),
1106        opt(parse_elements),
1107    )
1108        .parse(s);
1109    match res {
1110        // Case 1: nothing → empty vec (truly empty, distinct from `...`)
1111        Ok((s, (_, v, None))) if v.is_empty() => Ok((s, vec![])),
1112        // Case 2: no statements, one trailing expression (no ";") → return it directly
1113        Ok((s, (_, v, Some(expr)))) if v.is_empty() => Ok((s, vec![expr])),
1114        // Case 3: one or more statements + optional trailing expression
1115        Ok((s, (_, v, trailing))) => {
1116            let mut result: Vec<Lang> = v.into_iter().flatten().collect();
1117            if let Some(expr) = trailing {
1118                result.push(expr);
1119            }
1120            Ok((s, result))
1121        }
1122        Err(r) => Err(r),
1123    }
1124}
1125
1126/// Parse source code and return a ParseResult containing the AST and any syntax errors
1127///
1128/// This function collects syntax errors instead of panicking, allowing the caller
1129/// to handle errors appropriately (e.g., display all errors, continue with partial AST)
1130pub fn parse(s: Span) -> ParseResult {
1131    let res = base_parse(s.clone());
1132    match res {
1133        Ok((remaining, v)) => {
1134            if !remaining.fragment().is_empty() {
1135                let element = remaining
1136                    .fragment()
1137                    .lines()
1138                    .next()
1139                    .unwrap_or("")
1140                    .trim()
1141                    .to_string();
1142                let line = remaining.location_line();
1143                let help_data = HelpData::from(remaining);
1144                push_parse_error(SyntaxError::UnknownElement {
1145                    element,
1146                    line,
1147                    help_data,
1148                });
1149            }
1150            ParseResult::new(Lang::Lines {
1151                value: v.clone(),
1152                help_data: v.into(),
1153            })
1154        }
1155        Err(_) => panic!("Can't parse string {}", s),
1156    }
1157}
1158
1159/// Parse source code and return just the Lang AST (legacy behavior)
1160///
1161/// This function is kept for backwards compatibility. It returns the AST directly
1162/// and will panic if parsing fails completely.
1163pub fn parse_legacy(s: Span) -> Lang {
1164    parse(s).ast
1165}
1166
1167pub fn parse2(s: Span) -> Result<Lang, String> {
1168    let res = base_parse(s.clone());
1169    // Drain any parse errors collected during parsing (e.g. ForgottenSemicolon, FunctionTypeSyntax)
1170    let _ = take_parse_errors();
1171    match res {
1172        Ok((_, v)) => Ok(v[0].clone()),
1173        Err(_) => Err(format!("Can't parse string {}", s)),
1174    }
1175}
1176
1177/// Parse source code from a string with a filename for error reporting
1178///
1179/// This is the main entry point for parsing source code in the public API.
1180/// It registers the source for error display and returns the AST.
1181pub fn parse_from_string(source: &str, filename: &str) -> Lang {
1182    use crate::components::error_message::help_data::register_source;
1183
1184    // Register source for error display
1185    register_source(filename, source);
1186
1187    // Create a span with the filename as extra data
1188    let span: Span = LocatedSpan::new_extra(source, filename.to_string());
1189
1190    // Parse and return the AST
1191    parse(span).ast
1192}
1193
1194/// Parse source code from a string with a filename, returning full ParseResult
1195pub fn parse_from_string_with_errors(source: &str, filename: &str) -> ParseResult {
1196    use crate::components::error_message::help_data::register_source;
1197
1198    // Register source for error display
1199    register_source(filename, source);
1200
1201    // Create a span with the filename as extra data
1202    let span: Span = LocatedSpan::new_extra(source, filename.to_string());
1203
1204    // Parse and return full result
1205    parse(span)
1206}
1207
1208// main test
1209#[cfg(test)]
1210mod tesus {
1211    use super::*;
1212
1213    #[test]
1214    fn test_semicolon1() {
1215        let res = parse("let a <- 5".into());
1216        // This should now collect a ForgottenSemicolon error
1217        assert!(
1218            res.has_errors(),
1219            "Missing semicolon should produce a syntax error"
1220        );
1221        assert_eq!(res.errors.len(), 1, "Should have exactly one error");
1222        match &res.errors[0] {
1223            SyntaxError::ForgottenSemicolon(_) => (),
1224            _ => panic!("Expected ForgottenSemicolon error"),
1225        }
1226    }
1227
1228    #[test]
1229    fn test_semicolon_standalone_exp() {
1230        let res = parse("f(x)".into());
1231        // Case 2: a single expression without ";" is valid — no error
1232        assert!(
1233            !res.has_errors(),
1234            "A standalone expression without semicolon is valid (case 2)"
1235        );
1236    }
1237
1238    #[test]
1239    fn test_semicolon_assign() {
1240        let res = parse("a <- 12".into());
1241        assert!(
1242            res.has_errors(),
1243            "An assign expression without semicolon should produce a syntax error"
1244        );
1245        match &res.errors[0] {
1246            SyntaxError::ForgottenSemicolon(_) => (),
1247            _ => panic!("Expected ForgottenSemicolon error"),
1248        }
1249    }
1250
1251    #[test]
1252    fn test_assign1() {
1253        let res = assign("a <- 12;".into()).unwrap().1;
1254        assert_eq!(
1255            "Assign",
1256            res[0].simple_print(),
1257            "The expression 'a <- 12;' should be identified as an assignation"
1258        );
1259    }
1260
1261    // ==================== Let Tuple Destructuring Tests ====================
1262
1263    #[test]
1264    fn test_let_tuple_basic() {
1265        let res = let_tuple_exp("let :{a, b, c} <- :{1, 2, 3};".into())
1266            .unwrap()
1267            .1;
1268        // Should produce 4 Let statements: 1 tmp + 3 bindings
1269        assert_eq!(
1270            res.len(),
1271            4,
1272            "Should produce 4 Let statements (1 tmp + 3 bindings)"
1273        );
1274        for item in &res {
1275            assert!(
1276                item.simple_print().starts_with("let"),
1277                "Each item should be a Let, got: {}",
1278                item.simple_print()
1279            );
1280        }
1281    }
1282
1283    #[test]
1284    fn test_let_tuple_tmp_variable() {
1285        let res = let_tuple_exp("let :{a, b} <- :{1, 2};".into()).unwrap().1;
1286        // First Let should bind __tuple_tmp__
1287        if let Lang::Let { variable: var, .. } = &res[0] {
1288            if let Lang::Variable { name, .. } = var.as_ref() {
1289                assert_eq!(name, "__tuple_tmp__");
1290            } else {
1291                panic!("Expected Variable in first Let");
1292            }
1293        } else {
1294            panic!("Expected Let");
1295        }
1296    }
1297
1298    #[test]
1299    fn test_let_tuple_bindings() {
1300        let res = let_tuple_exp("let :{x, y} <- :{10, 20};".into()).unwrap().1;
1301        // Second Let should bind 'x' using Dot access
1302        if let Lang::Let {
1303            variable: var,
1304            expression: body,
1305            ..
1306        } = &res[1]
1307        {
1308            if let Lang::Variable { name, .. } = var.as_ref() {
1309                assert_eq!(name, "x");
1310            } else {
1311                panic!("Expected Variable 'x'");
1312            }
1313            assert_eq!(
1314                body.simple_print(),
1315                "Operator",
1316                "Body should be a Dot operator"
1317            );
1318        } else {
1319            panic!("Expected Let");
1320        }
1321        // Third Let should bind 'y'
1322        if let Lang::Let { variable: var, .. } = &res[2] {
1323            if let Lang::Variable { name, .. } = var.as_ref() {
1324                assert_eq!(name, "y");
1325            } else {
1326                panic!("Expected Variable 'y'");
1327            }
1328        } else {
1329            panic!("Expected Let");
1330        }
1331    }
1332
1333    #[test]
1334    fn test_let_tuple_wildcard() {
1335        let res = let_tuple_exp("let :{a, _, c} <- :{1, 2, 3};".into())
1336            .unwrap()
1337            .1;
1338        // Should produce 3 Let statements: 1 tmp + 2 bindings (wildcard skipped)
1339        assert_eq!(
1340            res.len(),
1341            3,
1342            "Should produce 3 Let statements (wildcard skipped)"
1343        );
1344        // Second Let should bind 'a'
1345        if let Lang::Let { variable: var, .. } = &res[1] {
1346            if let Lang::Variable { name, .. } = var.as_ref() {
1347                assert_eq!(name, "a");
1348            } else {
1349                panic!("Expected Variable 'a'");
1350            }
1351        } else {
1352            panic!("Expected Let");
1353        }
1354        // Third Let should bind 'c'
1355        if let Lang::Let { variable: var, .. } = &res[2] {
1356            if let Lang::Variable { name, .. } = var.as_ref() {
1357                assert_eq!(name, "c");
1358            } else {
1359                panic!("Expected Variable 'c'");
1360            }
1361        } else {
1362            panic!("Expected Let");
1363        }
1364    }
1365
1366    #[test]
1367    fn test_let_tuple_in_full_parse() {
1368        let res = parse("let :{a, b, c} <- :{1, 2, 3};".into());
1369        assert!(
1370            !res.has_errors(),
1371            "Let tuple destructuring should parse without errors"
1372        );
1373    }
1374
1375    #[test]
1376    fn test_let_tuple_with_equals() {
1377        let res = let_tuple_exp("let :{a, b} = :{1, 2};".into()).unwrap().1;
1378        assert_eq!(res.len(), 3, "Should work with '=' operator too");
1379    }
1380
1381    #[test]
1382    fn test_let_tuple_type_check() {
1383        use crate::components::context::Context;
1384        use crate::processes::type_checking::typing;
1385        use crate::utils::builder;
1386
1387        let ast = parse("let :{a, b, c} <- :{1, 2, 3};".into()).ast;
1388        let context = Context::empty();
1389        let tc = typing(&context, &ast);
1390
1391        // After type-checking, 'a', 'b', 'c' should be in the context as integers
1392        let ty_a = tc
1393            .context
1394            .get_type_from_existing_variable(crate::components::language::var::Var::from_name("a"));
1395        let ty_b = tc
1396            .context
1397            .get_type_from_existing_variable(crate::components::language::var::Var::from_name("b"));
1398        let ty_c = tc
1399            .context
1400            .get_type_from_existing_variable(crate::components::language::var::Var::from_name("c"));
1401
1402        assert_eq!(
1403            ty_a,
1404            builder::integer_type(1),
1405            "Variable 'a' should be Integer(1)"
1406        );
1407        assert_eq!(
1408            ty_b,
1409            builder::integer_type(2),
1410            "Variable 'b' should be Integer(2)"
1411        );
1412        assert_eq!(
1413            ty_c,
1414            builder::integer_type(3),
1415            "Variable 'c' should be Integer(3)"
1416        );
1417    }
1418
1419    #[test]
1420    fn test_let_tuple_type_check_mixed_types() {
1421        use crate::components::context::Context;
1422        use crate::processes::type_checking::typing;
1423        use crate::utils::builder;
1424
1425        let ast = parse("let :{x, y} <- :{1, 'hello'};".into()).ast;
1426        let context = Context::empty();
1427        let tc = typing(&context, &ast);
1428
1429        let ty_x = tc
1430            .context
1431            .get_type_from_existing_variable(crate::components::language::var::Var::from_name("x"));
1432        let ty_y = tc
1433            .context
1434            .get_type_from_existing_variable(crate::components::language::var::Var::from_name("y"));
1435
1436        assert_eq!(
1437            ty_x,
1438            builder::integer_type(1),
1439            "Variable 'x' should be Integer(1)"
1440        );
1441        assert_eq!(
1442            ty_y,
1443            builder::character_type("hello"),
1444            "Variable 'y' should be Character('hello')"
1445        );
1446    }
1447
1448    #[test]
1449    fn test_fn_function_type_syntax_error() {
1450        let res = parse("let f: fn(a: int) -> int <- fn(x: int): int { x };".into());
1451        assert!(
1452            res.has_errors(),
1453            "Using 'fn(...)' in type position should produce a syntax error"
1454        );
1455        let fn_type_error = res
1456            .errors
1457            .iter()
1458            .any(|e| matches!(e, SyntaxError::FunctionTypeSyntax(_)));
1459        assert!(
1460            fn_type_error,
1461            "Expected FunctionTypeSyntax error, got: {:?}",
1462            res.errors
1463        );
1464    }
1465
1466    #[test]
1467    fn test_use_wildcard_parses() {
1468        use crate::components::language::use_lang::UseSelector;
1469        let lang = parse2("use Math::*;".into()).expect("parse failed");
1470        match lang {
1471            Lang::UseModule {
1472                module_path,
1473                selector,
1474                ..
1475            } => {
1476                assert_eq!(module_path, vec!["Math".to_string()]);
1477                assert_eq!(selector, UseSelector::Wildcard);
1478            }
1479            other => panic!("Expected UseModule, got {:?}", other),
1480        }
1481    }
1482
1483    #[test]
1484    fn test_use_items_parses() {
1485        use crate::components::language::use_lang::{UseItem, UseSelector};
1486        let lang = parse2("use Math::{pi, sin as s};".into()).expect("parse failed");
1487        match lang {
1488            Lang::UseModule {
1489                module_path,
1490                selector,
1491                ..
1492            } => {
1493                assert_eq!(module_path, vec!["Math".to_string()]);
1494                assert_eq!(
1495                    selector,
1496                    UseSelector::Items(vec![
1497                        UseItem {
1498                            name: "pi".to_string(),
1499                            alias: None
1500                        },
1501                        UseItem {
1502                            name: "sin".to_string(),
1503                            alias: Some("s".to_string())
1504                        },
1505                    ])
1506                );
1507            }
1508            other => panic!("Expected UseModule, got {:?}", other),
1509        }
1510    }
1511
1512    #[test]
1513    fn test_use_nested_path_parses() {
1514        use crate::components::language::use_lang::UseSelector;
1515        let lang = parse2("use Aa::Bb::Cc::*;".into()).expect("parse failed");
1516        match lang {
1517            Lang::UseModule {
1518                module_path,
1519                selector,
1520                ..
1521            } => {
1522                assert_eq!(
1523                    module_path,
1524                    vec!["Aa".to_string(), "Bb".to_string(), "Cc".to_string()]
1525                );
1526                assert_eq!(selector, UseSelector::Wildcard);
1527            }
1528            other => panic!("Expected UseModule, got {:?}", other),
1529        }
1530    }
1531}