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 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
778fn 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
803fn 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
819fn 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
836fn 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
857fn 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
874fn 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
889fn 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 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
1162pub 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
1252pub 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 #[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 #[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 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 #[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 #[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 #[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}