1use crate::components::error_message::help_data::HelpData;
2use crate::components::error_message::syntax_error::SyntaxError;
3use crate::components::language::argument_value::ArgumentValue;
4use crate::components::language::operators::op;
5use crate::components::language::operators::Op;
6use crate::components::language::var::Var;
7use crate::components::language::Lang;
8use crate::components::r#type::argument_type::ArgumentType;
9use crate::components::r#type::Type;
10use crate::processes::parsing::base_parse;
11use crate::processes::parsing::lang_token::LangToken;
12use crate::processes::parsing::operation_priority::PriorityTokens;
13use crate::processes::parsing::push_parse_error;
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;
19use crate::processes::parsing::types::single_type;
20
21use crate::processes::parsing::vector_priority::VectorPriority;
22use crate::utils::builder;
23use nom::branch::alt;
24use nom::bytes::complete::escaped;
25use nom::bytes::complete::is_not;
26use nom::bytes::complete::tag;
27use nom::bytes::complete::take_until;
28use nom::bytes::complete::take_while1;
29use nom::character::complete::alpha1;
30use nom::character::complete::alphanumeric1;
31use nom::character::complete::anychar;
32use nom::character::complete::char;
33use nom::character::complete::digit1;
34use nom::character::complete::line_ending;
35use nom::character::complete::multispace0;
36use nom::character::complete::multispace1;
37use nom::character::complete::not_line_ending;
38use nom::character::complete::one_of;
39use nom::combinator::map;
40use nom::combinator::not;
41use nom::combinator::opt;
42use nom::combinator::recognize;
43use nom::multi::many0;
44use nom::multi::many1;
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::process::exit;
53
54type Span<'a> = LocatedSpan<&'a str, String>;
55
56pub fn is_pascal_case(name: &str) -> bool {
57 let res = recognize(pascal_case_no_space).parse(name.into());
58 match res {
59 Ok((_, _)) => true,
60 Err(_) => false,
61 }
62}
63
64fn number_helper(s: Span) -> IResult<Span, Lang> {
65 let res = (opt(tag("-")), digit1, tag("."), digit1).parse(s);
66 match res {
67 Ok((s, (sign, d1, _dot, d2))) => {
68 let sign2 = sign.unwrap_or(LocatedSpan::new_extra("", d1.clone().extra));
69 let n = format!("{}{}.{}", sign2, d1, d2).parse::<f32>().unwrap();
70 Ok((
71 s,
72 Lang::Number {
73 value: n,
74 help_data: sign2.into(),
75 },
76 ))
77 }
78 Err(r) => Err(r),
79 }
80}
81
82pub fn number(s: Span) -> IResult<Span, Lang> {
83 terminated(number_helper, multispace0).parse(s)
84}
85
86fn integer(s: Span) -> IResult<Span, Lang> {
87 let res = terminated((opt(tag("-")), digit1), multispace0).parse(s);
88 match res {
89 Ok((s, (minus, d))) => {
90 let symbol = match minus {
91 Some(_) => "-",
92 None => "",
93 }
94 .to_string()
95 + d.as_ref();
96 Ok((
97 s,
98 Lang::Integer {
99 value: symbol.parse::<i32>().unwrap(),
100 help_data: d.into(),
101 },
102 ))
103 }
104 Err(r) => Err(r),
105 }
106}
107
108fn get_value(l: LocatedSpan<&str, String>) -> Lang {
109 match l.clone().into_fragment() {
110 "true" | "TRUE" => Lang::Bool {
111 value: true,
112 help_data: l.into(),
113 },
114 "false" | "FALSE" => Lang::Bool {
115 value: false,
116 help_data: l.into(),
117 },
118 _ => panic!("No other boolean notation alolwed"),
119 }
120}
121
122fn null_value(s: Span) -> IResult<Span, Lang> {
123 let res = alt((
124 terminated(terminated(tag("NULL"), not(body_char)), multispace0),
125 terminated(terminated(tag("null"), not(body_char)), multispace0),
126 ))
127 .parse(s);
128 match res {
129 Ok((s, n)) => Ok((s, Lang::Null(n.into()))),
130 Err(r) => Err(r),
131 }
132}
133
134fn na_value(s: Span) -> IResult<Span, Lang> {
135 let res = alt((
136 terminated(terminated(tag("NA"), not(body_char)), multispace0),
137 terminated(terminated(tag("na"), not(body_char)), multispace0),
138 ))
139 .parse(s);
140 match res {
141 Ok((s, n)) => Ok((s, Lang::NA(n.into()))),
142 Err(r) => Err(r),
143 }
144}
145
146fn boolean(s: Span) -> IResult<Span, Lang> {
147 let res = alt((
148 terminated(terminated(tag("true"), not(body_char)), multispace0),
149 terminated(terminated(tag("TRUE"), not(body_char)), multispace0),
150 terminated(terminated(tag("false"), not(body_char)), multispace0),
151 terminated(terminated(tag("FALSE"), not(body_char)), multispace0),
152 ))
153 .parse(s);
154 match res {
155 Ok((s, ls)) => Ok((s, get_value(ls))),
156 Err(r) => Err(r),
157 }
158}
159
160pub fn chars(s: Span) -> IResult<Span, Lang> {
161 terminated(alt((double_quotes, single_quotes)), multispace0).parse(s)
162}
163
164pub fn decode_escapes(s: &str) -> String {
169 let mut out = String::with_capacity(s.len());
170 let mut chars = s.chars();
171 while let Some(c) = chars.next() {
172 if c == '\\' {
173 match chars.next() {
174 Some('"') => out.push('"'),
175 Some('\'') => out.push('\''),
176 Some('\\') => out.push('\\'),
177 Some('n') => out.push('\n'),
178 Some('t') => out.push('\t'),
179 Some('r') => out.push('\r'),
180 Some(other) => {
181 out.push('\\');
182 out.push(other);
183 }
184 None => out.push('\\'),
185 }
186 } else {
187 out.push(c);
188 }
189 }
190 out
191}
192
193pub fn double_quotes(input: Span) -> IResult<Span, Lang> {
194 let res = delimited(char('"'), opt(escaped(is_not("\\\""), '\\', anychar)), char('"')).parse(input);
195 match res {
196 Ok((s, st)) => {
197 let content = st.clone().map(|span| decode_escapes(span.as_ref())).unwrap_or_default();
198 let location = st.map(|span| span.into()).unwrap_or_else(|| s.clone().into());
199 Ok((
200 s,
201 Lang::Char {
202 value: content,
203 help_data: location,
204 },
205 ))
206 }
207 Err(r) => Err(r),
208 }
209}
210
211pub fn single_quotes(input: Span) -> IResult<Span, Lang> {
212 let res = delimited(char('\''), opt(escaped(is_not("\\'"), '\\', anychar)), char('\'')).parse(input);
213 match res {
214 Ok((s, st)) => {
215 let content = st.clone().map(|span| decode_escapes(span.as_ref())).unwrap_or_default();
216 let location = st.map(|span| span.into()).unwrap_or_else(|| s.clone().into());
217 Ok((
218 s,
219 Lang::Char {
220 value: content,
221 help_data: location,
222 },
223 ))
224 }
225 Err(r) => Err(r),
226 }
227}
228
229fn starting_char(s: Span) -> IResult<Span, (char, HelpData)> {
230 let res = one_of("abcdefghijklmnopqrstuvwxyz_")(s);
231 match res {
232 Ok((s, val)) => Ok((s.clone(), (val, s.into()))),
233 Err(r) => Err(r),
234 }
235}
236
237fn body_char(s: Span) -> IResult<Span, (char, HelpData)> {
238 let res = one_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789")(s);
239 match res {
240 Ok((s, val)) => Ok((s.clone(), (val, s.into()))),
241 Err(r) => Err(r),
242 }
243}
244
245pub fn variable_exp(s: Span) -> IResult<Span, (String, HelpData)> {
246 let res = (starting_char, many0(body_char)).parse(s);
247 match res {
248 Ok((s, ((s1, h), v))) => {
249 let res2 = v.iter().map(|(val, _h)| *val).collect::<String>();
250 Ok((s, (format!("{}{}", s1, res2), h.clone())))
251 }
252 Err(r) => Err(r),
253 }
254}
255
256fn type_annotation(s: Span) -> IResult<Span, Type> {
257 delimited(tag("<"), ltype, tag(">")).parse(s)
258}
259
260pub enum Case {
261 Maj,
262 Min,
263}
264
265fn variable_exp_2(s: Span) -> IResult<Span, (String, Case, HelpData)> {
266 let res = variable_exp.parse(s);
267 match res {
268 Ok((s, (name, h))) => Ok((s, (name, Case::Min, h))),
269 Err(r) => Err(r),
270 }
271}
272
273fn pascal_case_2(s: Span) -> IResult<Span, (String, Case, HelpData)> {
274 let res = pascal_case.parse(s);
275 match res {
276 Ok((s, (name, h))) => Ok((s, (name, Case::Maj, h))),
277 Err(r) => Err(r),
278 }
279}
280
281fn quoted_variable(s: Span) -> IResult<Span, (String, Case, HelpData)> {
282 let res = delimited(char('`'), is_not("`"), char('`')).parse(s);
283
284 match res {
285 Ok((s, st)) => Ok((s, (format!("`{}`", st.clone()), Case::Min, st.into()))),
286 Err(r) => Err(r),
287 }
288}
289
290pub fn variable_recognizer(s: Span) -> IResult<Span, (String, HelpData)> {
291 let res = alt((quoted_variable, pascal_case_2, variable_exp_2)).parse(s);
292 match res {
293 Ok((s, (s1, _case, h))) => Ok((s, (s1, h))),
294 Err(r) => Err(r),
295 }
296}
297
298fn variable_helper(s: Span) -> IResult<Span, (Lang, Case)> {
299 let res = (
300 alt((quoted_variable, pascal_case_2, variable_exp_2)),
301 opt(type_annotation),
302 )
303 .parse(s);
304 match res {
305 Ok((s, ((v, case, h), typ))) => {
306 let res = Var::from_name(&v)
307 .set_type(typ.unwrap_or(builder::empty_type()))
308 .set_help_data(h);
309 Ok((s, (res.into(), case)))
310 }
311 Err(r) => Err(r),
312 }
313}
314
315pub fn variable(s: Span) -> IResult<Span, (Lang, Case)> {
316 terminated(variable_helper, multispace0).parse(s)
317}
318
319pub fn argument(s: Span) -> IResult<Span, ArgumentType> {
320 let variadic = (
322 terminated(tag("..."), multispace0),
323 terminated(label, multispace0),
324 terminated(tag(":"), multispace0),
325 ltype,
326 opt(terminated(tag(","), multispace0)),
327 )
328 .parse(s.clone());
329 if let Ok((s2, (_, e1, _, e2, _))) = variadic {
330 return Ok((s2, ArgumentType(e1, e2, false, true, None)));
331 }
332
333 let res = (
335 terminated(label, multispace0),
336 terminated(tag(":"), multispace0),
337 ltype,
338 opt(preceded(terminated(tag("="), multispace0), parse_elements)),
339 opt(terminated(tag(","), multispace0)),
340 )
341 .parse(s);
342 match res {
343 Ok((s, (e1, _, e2, default, _))) => Ok((s, ArgumentType(e1, e2, false, false, default.map(Box::new)))),
344 Err(r) => Err(r),
345 }
346}
347
348fn equality_params(s: Span) -> IResult<Span, Span> {
349 terminated(alt((tag("="), tag(":"))), multispace0).parse(s)
350}
351
352fn argument_val(s: Span) -> IResult<Span, ArgumentValue> {
353 let res = (
354 terminated(alphanumeric1, multispace0),
355 equality_params,
356 parse_elements,
357 opt(terminated(tag(","), multispace0)),
358 )
359 .parse(s);
360 match res {
361 Ok((s, (e1, _, e2, _))) => Ok((s, ArgumentValue(e1.to_string(), e2))),
362 Err(r) => Err(r),
363 }
364}
365
366pub fn parse_block(input: Span) -> IResult<Span, Span> {
367 recognize(parse_nested_braces).parse(input)
368}
369
370fn parse_nested_braces(input: Span) -> IResult<Span, Span> {
371 recognize(delimited(
372 tag("{"),
373 many0(alt((
374 parse_nested_braces,
375 recognize(take_while1(|c| c != '{' && c != '}')),
376 ))),
377 tag("}"),
378 ))
379 .parse(input)
380}
381
382pub fn r_function(s: Span) -> IResult<Span, Lang> {
383 let res = (
384 terminated(alt((tag("function"), tag("\\"))), multispace0),
385 terminated(tag("("), multispace0),
386 many0(terminated(terminated(variable, opt(tag(","))), multispace0)),
387 terminated(tag(")"), multispace0),
388 terminated(parse_block, multispace0),
389 )
390 .parse(s);
391 match res {
392 Ok((_s, (id, _op, _args, _cl, _exp))) if *id.fragment() == "fn" => {
393 std::panic::panic_any(SyntaxError::FunctionWithoutType(id.into()))
394 }
395 Ok((s, (id, _op, args, _cl, exp))) => {
396 let args = args.iter().map(|(arg, _)| arg).cloned().collect::<Vec<_>>();
397 Ok((
398 s,
399 Lang::RFunction {
400 parameters: args,
401 body: exp.to_string(),
402 help_data: id.into(),
403 },
404 ))
405 }
406 Err(r) => Err(r),
407 }
408}
409
410pub fn r_block(s: Span) -> IResult<Span, Lang> {
421 let res = (terminated(tag("R"), multispace0), terminated(parse_block, multispace0)).parse(s);
422 match res {
423 Ok((s, (kw, body))) => Ok((
424 s,
425 Lang::RBlock {
426 value: body.to_string(),
427 help_data: kw.into(),
428 },
429 )),
430 Err(r) => Err(r),
431 }
432}
433
434fn raw_r_string(s: Span) -> IResult<Span, String> {
437 let (s, _) = tag("r#\"")(s)?;
438 let (s, body) = take_until("\"#")(s)?;
439 let (s, _) = tag("\"#")(s)?;
440 Ok((s, body.fragment().to_string()))
441}
442
443pub fn extern_block(s: Span) -> IResult<Span, Lang> {
449 let res = (
450 terminated(tag("extern"), multispace1),
451 terminated(tag("("), multispace0),
452 many0(argument),
453 terminated(tag(")"), multispace0),
454 terminated(alt((tag("->"), tag(":"))), multispace0),
455 single_type,
456 raw_r_string,
457 )
458 .parse(s);
459 match res {
460 Ok((s, (kw, _op, params, _cl, _arrow, ret_ty, body))) => Ok((
461 s,
462 Lang::ExternBlock {
463 parameters: params,
464 return_type: ret_ty,
465 body,
466 help_data: kw.into(),
467 },
468 )),
469 Err(r) => Err(r),
470 }
471}
472
473pub fn simple_function(s: Span) -> IResult<Span, Lang> {
474 let res = (
475 terminated(tag("fn"), multispace0),
476 terminated(tag("("), multispace0),
477 many0(argument),
478 terminated(tag(")"), multispace0),
479 opt(terminated(alt((tag("->"), tag(":"))), multispace0)),
480 opt(terminated(alt((if_type, ltype)), multispace0)),
481 scope,
483 )
484 .parse(s);
485 match res {
486 Ok((s, (_, _, args, _, Some(_), Some(typ), exp))) => Ok((
487 s,
488 Lang::Function {
489 parameters: args,
490 return_type: typ,
491 body: Box::new(exp),
492 help_data: HelpData::default(),
493 },
494 )),
495 Ok((_s, (_, _, _args, _cp, None, None, _exp))) => {
496 panic!("You forgot to specify the function return type: 'fn(...): Type'");
497 }
498 Ok((_s, (_, _, _args, _, Some(tag), None, _exp))) => {
499 std::panic::panic_any(SyntaxError::FunctionWithoutReturnType(tag.into()));
500 }
501 Ok((_s, (_, _, _args, _, None, Some(typ), _exp))) => {
502 eprintln!(
503 "The type '{}' should be preceded by a ':' :\n 'fn(...): {}'",
504 typ.clone(),
505 typ.clone()
506 );
507 exit(1)
508 }
509 Err(r) => Err(r),
510 }
511}
512
513fn function(s: Span) -> IResult<Span, Lang> {
514 simple_function.parse(s)
515}
516
517fn key_value(s: Span) -> IResult<Span, Lang> {
518 let res = (recognize(variable), terminated(tag("="), multispace0), single_element).parse(s);
519 match res {
520 Ok((s, (v, _eq, el))) => Ok((
521 s,
522 Lang::KeyValue {
523 key: (*v).into(),
524 value: Box::new(el),
525 help_data: v.into(),
526 },
527 )),
528 Err(r) => Err(r),
529 }
530}
531
532fn values(s: Span) -> IResult<Span, Vec<Lang>> {
533 many0(terminated(
534 alt((key_value, parse_elements)),
535 terminated(opt(tag(",")), multispace0),
536 ))
537 .parse(s)
538}
539
540pub fn variable2(s: Span) -> IResult<Span, Lang> {
541 let res = variable.parse(s);
542 match res {
543 Ok((s, (lang, _))) => Ok((s, lang)),
544 Err(r) => Err(r),
545 }
546}
547
548fn array_indexing(s: Span) -> IResult<Span, Lang> {
549 let res = (alt((scope, variable2)), array).parse(s);
550
551 match res {
552 Ok((s, (lang1, lang2))) => Ok((
553 s,
554 Lang::ArrayIndexing {
555 identifier: Box::new(lang1.clone()),
556 indexing: Box::new(lang2),
557 help_data: lang1.into(),
558 },
559 )),
560 Err(r) => Err(r),
561 }
562}
563
564fn dataframe_exp(s: Span) -> IResult<Span, Lang> {
565 let res = (
566 alt((tag("data__frame"), tag("data.frame"))),
567 terminated(tag("("), multispace0),
568 many0(argument_val),
569 terminated(tag(")"), multispace0),
570 )
571 .parse(s);
572 match res {
573 Ok((s, (start, _, args, _))) => Ok((
574 s,
575 Lang::DataFrame {
576 value: args.clone(),
577 help_data: start.into(),
578 },
579 )),
580 Err(r) => Err(r),
581 }
582}
583
584fn function_application(s: Span) -> IResult<Span, Lang> {
585 let res = (
586 alt((scope, variable2)),
587 terminated(tag("("), multispace0),
588 values,
589 terminated(tag(")"), multispace0),
590 )
591 .parse(s);
592 match res {
593 Ok((s, (exp, _, v, _))) => Ok((
594 s,
595 Lang::FunctionApp {
596 identifier: Box::new(exp.clone()),
597 arguments: v.clone(),
598 help_data: exp.into(),
599 },
600 )),
601 Err(r) => Err(r),
602 }
603}
604
605fn array(s: Span) -> IResult<Span, Lang> {
606 let res = (
607 terminated(tag("["), multispace0),
608 values,
609 terminated(tag("]"), multispace0),
610 )
611 .parse(s);
612 match res {
613 Ok((s, (_, v, _))) => Ok((
614 s,
615 Lang::Array {
616 value: v.clone(),
617 help_data: v.into(),
618 },
619 )),
620 Err(r) => Err(r),
621 }
622}
623
624pub fn vector(s: Span) -> IResult<Span, Lang> {
625 let res = (
626 terminated(tag("c("), multispace0),
627 values,
628 terminated(tag(")"), multispace0),
629 )
630 .parse(s);
631 match res {
632 Ok((s, (_, v, _))) => Ok((
633 s,
634 Lang::Vector {
635 value: v.clone(),
636 help_data: v.into(),
637 },
638 )),
639 Err(r) => Err(r),
640 }
641}
642
643fn sequence(s: Span) -> IResult<Span, Lang> {
644 let res = (
645 terminated(tag("seq["), multispace0),
646 values,
647 terminated(tag("]"), multispace0),
648 )
649 .parse(s);
650 match res {
651 Ok((s, (_, v, _))) => Ok((
652 s,
653 Lang::Sequence {
654 body: v.clone(),
655 help_data: v.into(),
656 },
657 )),
658 Err(r) => Err(r),
659 }
660}
661
662fn ws0(s: Span) -> IResult<Span, ()> {
667 many0(alt((
668 map(multispace1, |_| ()),
669 map((char('#'), not_line_ending, opt(line_ending)), |_| ()),
670 )))
671 .parse(s)
672 .map(|(s, _)| (s, ()))
673}
674
675enum ConstructorElement {
679 Field(Box<ArgumentValue>),
680 Spread(Vec<String>, String, HelpData),
681 RuntimeSpread(Box<Lang>),
682}
683
684fn runtime_spread_field(s: Span) -> IResult<Span, ConstructorElement> {
687 let res = (
688 terminated(tag("..."), multispace0),
689 single_element,
690 opt(terminated(tag(","), multispace0)),
691 )
692 .parse(s);
693 match res {
694 Ok((s, (_, e, _))) => Ok((s, ConstructorElement::RuntimeSpread(Box::new(e)))),
695 Err(r) => Err(r),
696 }
697}
698
699fn spread_field(s: Span) -> IResult<Span, ConstructorElement> {
703 let res = (
704 terminated(terminated(tag(".."), not(char('.'))), multispace0),
705 many0(terminated(variable_exp, tag("$"))),
706 terminated(variable_exp, multispace0),
707 opt(terminated(tag(","), multispace0)),
708 )
709 .parse(s);
710 match res {
711 Ok((s, (_, path, (name, h), _))) => Ok((
712 s,
713 ConstructorElement::Spread(path.into_iter().map(|(seg, _)| seg).collect(), name, h),
714 )),
715 Err(r) => Err(r),
716 }
717}
718
719fn constructor_field(s: Span) -> IResult<Span, ConstructorElement> {
720 if let Ok((s2, spread)) = spread_field(s.clone()) {
721 return Ok((s2, spread));
722 }
723 if let Ok((s2, spread)) = runtime_spread_field(s.clone()) {
724 return Ok((s2, spread));
725 }
726 let (s2, field) = argument_val(s)?;
727 Ok((s2, ConstructorElement::Field(Box::new(field))))
728}
729
730fn constructor_call(s: Span) -> IResult<Span, Lang> {
731 let res = (
732 many0(terminated(variable_exp, tag("$"))),
733 pascal_case,
734 terminated(tag(":"), multispace0),
735 terminated(tag("{"), multispace0),
736 many0(preceded(ws0, constructor_field)),
737 preceded(ws0, terminated(tag("}"), multispace0)),
738 )
739 .parse(s);
740 match res {
741 Ok((s, (path, (name, h), _, _, elements, _))) => {
742 let mut fields = Vec::new();
743 let mut spreads = Vec::new();
744 let mut runtime_spreads = Vec::new();
745 for el in elements {
746 match el {
747 ConstructorElement::Field(f) => fields.push(*f),
748 ConstructorElement::Spread(p, n, sh) => spreads.push((p, n, sh)),
749 ConstructorElement::RuntimeSpread(e) => runtime_spreads.push(*e),
750 }
751 }
752 if spreads.len() > 1 || runtime_spreads.len() > 1 {
757 return Err(nom::Err::Error(nom::error::Error::new(s, nom::error::ErrorKind::Many1)));
758 }
759 Ok((
760 s,
761 Lang::ConstructorCall {
762 module_path: path.into_iter().map(|(seg, _)| seg).collect(),
763 type_name: name,
764 fields,
765 spread: spreads.into_iter().next(),
766 spreads: runtime_spreads,
767 help_data: h,
768 },
769 ))
770 }
771 Err(r) => Err(r),
772 }
773}
774
775fn array_constructor_call(s: Span) -> IResult<Span, Lang> {
776 let res = (
777 pascal_case,
778 tag(":["),
779 multispace0,
780 values,
781 terminated(tag("]"), multispace0),
782 )
783 .parse(s);
784 match res {
785 Ok((s, ((name, h), _, _, elems, _))) => Ok((
786 s,
787 Lang::ArrayConstructorCall {
788 type_name: name,
789 elements: elems,
790 help_data: h,
791 },
792 )),
793 Err(r) => Err(r),
794 }
795}
796
797fn record_identifier(s: Span) -> IResult<Span, Span> {
798 alt((tag("record"), tag("object"), tag("list"), tag(":"))).parse(s)
799}
800
801enum RecordElement {
804 Field(Box<ArgumentValue>),
805 Spread(Box<Lang>),
806}
807
808fn record_spread_field(s: Span) -> IResult<Span, RecordElement> {
810 let res = (
811 terminated(tag("..."), multispace0),
812 single_element,
813 opt(terminated(tag(","), multispace0)),
814 )
815 .parse(s);
816 match res {
817 Ok((s, (_, e, _))) => Ok((s, RecordElement::Spread(Box::new(e)))),
818 Err(r) => Err(r),
819 }
820}
821
822fn record_field(s: Span) -> IResult<Span, RecordElement> {
823 if let Ok((s2, spread)) = record_spread_field(s.clone()) {
824 return Ok((s2, spread));
825 }
826 let (s2, field) = argument_val(s)?;
827 Ok((s2, RecordElement::Field(Box::new(field))))
828}
829
830pub fn record(s: Span) -> IResult<Span, Lang> {
831 let res = (
832 opt(terminated(record_identifier, multispace0)),
833 terminated(alt((tag("{"), tag("("))), multispace0),
834 many0(preceded(ws0, record_field)),
835 preceded(ws0, terminated(alt((tag("}"), tag(")"))), multispace0)),
836 )
837 .parse(s);
838 match res {
839 Ok((s, (Some(start), _, elements, _))) => {
840 let mut fields = Vec::new();
841 let mut spreads = Vec::new();
842 for el in elements {
843 match el {
844 RecordElement::Field(f) => fields.push(*f),
845 RecordElement::Spread(e) => spreads.push(*e),
846 }
847 }
848 Ok((
849 s,
850 Lang::List {
851 value: fields,
852 spreads,
853 help_data: start.into(),
854 },
855 ))
856 }
857 Ok((_s, (None, _ob, _elements, _))) => Err(nom::Err::Error(nom::error::Error::new(
858 _s,
859 nom::error::ErrorKind::Many1,
860 ))),
861 Err(r) => Err(r),
862 }
863}
864
865fn keyword_positional_record_exp(s: Span) -> IResult<Span, Lang> {
883 let res = (
884 terminated(alt((tag("list"), tag("record"), tag("object"))), multispace0),
885 terminated(tag("{"), multispace0),
886 values,
887 preceded(ws0, terminated(tag("}"), multispace0)),
888 )
889 .parse(s);
890 match res {
891 Ok((s, (kw, _ob, vals, _cb))) => {
892 let keyword = kw.to_string();
893 let h: HelpData = kw.into();
894 push_parse_error(SyntaxError::KeywordRecordPositionalElements {
895 keyword,
896 help_data: h.clone(),
897 });
898 Ok((
899 s,
900 Lang::Tuple {
901 value: vals,
902 help_data: h,
903 },
904 ))
905 }
906 Err(r) => Err(r),
907 }
908}
909
910fn pascal_case_helper(s: Span) -> IResult<Span, (String, HelpData)> {
911 let res = (one_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), opt(alpha1)).parse(s);
912 match res {
913 Ok((s, (t1, Some(t2)))) => Ok((s.clone(), (format!("{}{}", t1, t2), s.into()))),
914 Ok((s, (t1, None))) => Ok((s.clone(), (t1.to_string(), s.into()))),
915 Err(r) => Err(r),
916 }
917}
918
919fn pascal_case(s: Span) -> IResult<Span, (String, HelpData)> {
920 pascal_case_helper.parse(s)
921}
922
923fn union_constructor(s: Span) -> IResult<Span, Lang> {
924 let res = (
925 pascal_case,
926 terminated(tag("."), multispace0),
927 pascal_case,
928 opt((
929 terminated(tag(":"), multispace0),
930 terminated(tag("{"), multispace0),
931 many0(argument_val),
932 terminated(tag("}"), multispace0),
933 )),
934 )
935 .parse(s);
936 match res {
937 Ok((s, ((union_name, h), _, (variant_name, _), None))) => Ok((
938 s,
939 Lang::UnionConstructor {
940 union_name,
941 variant_name,
942 fields: vec![],
943 help_data: h,
944 },
945 )),
946 Ok((s, ((union_name, h), _, (variant_name, _), Some((_, _, fields, _))))) => Ok((
947 s,
948 Lang::UnionConstructor {
949 union_name,
950 variant_name,
951 fields,
952 help_data: h,
953 },
954 )),
955 Err(r) => Err(r),
956 }
957}
958
959fn parenthese_value(s: Span) -> IResult<Span, Lang> {
960 delimited(
961 terminated(tag("("), multispace0),
962 parse_elements,
963 terminated(tag(")"), multispace0),
964 )
965 .parse(s)
966}
967
968pub fn tag_exp(s: Span) -> IResult<Span, Lang> {
969 let res = terminated((tag("."), pascal_case, opt(parenthese_value)), multispace0).parse(s);
970 match res {
971 Ok((s, (dot, (n, _h), None))) => Ok((
972 s,
973 Lang::Tag {
974 name: n,
975 value: Box::new(Lang::Empty(dot.clone().into())),
976 help_data: dot.into(),
977 },
978 )),
979 Ok((s, (dot, (n, _h), Some(val)))) => Ok((
980 s,
981 Lang::Tag {
982 name: n,
983 value: Box::new(val),
984 help_data: dot.into(),
985 },
986 )),
987 Err(r) => Err(r),
988 }
989}
990
991fn dotdotdot(s: Span) -> IResult<Span, Lang> {
992 let res = terminated(tag("..."), multispace0).parse(s);
993 match res {
994 Ok((s, d)) => Ok((s, Lang::Empty(d.into()))),
995 Err(r) => Err(r),
996 }
997}
998
999fn else_exp(s: Span) -> IResult<Span, Lang> {
1000 let res = (
1001 terminated(tag("else"), multispace0),
1002 terminated(tag("{"), multispace0),
1003 parse_elements,
1004 terminated(tag("}"), multispace0),
1005 )
1006 .parse(s);
1007 match res {
1008 Ok((s, (_else, _o, exp, _c))) => Ok((s, exp)),
1009 Err(r) => Err(r),
1010 }
1011}
1012
1013fn else_if_exp(s: Span) -> IResult<Span, Lang> {
1014 preceded(terminated(tag("else"), multispace1), if_exp).parse(s)
1015}
1016
1017fn if_exp(s: Span) -> IResult<Span, Lang> {
1018 let res = (
1019 terminated(tag("if"), multispace0),
1020 terminated(tag("("), multispace0),
1021 parse_elements,
1022 terminated(tag(")"), multispace0),
1023 terminated(tag("{"), multispace0),
1024 parse_elements,
1025 terminated(tag("}"), multispace0),
1026 opt(alt((else_if_exp, else_exp))),
1027 )
1028 .parse(s);
1029 match res {
1030 Ok((s, (_if, _op, cond, _cp, _o, exp, _c, els))) => Ok((
1031 s,
1032 Lang::If {
1033 condition: Box::new(cond),
1034 if_block: Box::new(exp),
1035 else_block: Box::new(els.unwrap_or(Lang::Empty(HelpData::default()))),
1036 help_data: _if.into(),
1037 },
1038 )),
1039 Err(r) => Err(r),
1040 }
1041}
1042
1043fn tag_pattern_with_var(s: Span) -> IResult<Span, Lang> {
1045 let res = (
1046 tag("."),
1047 pascal_case,
1048 delimited(
1049 terminated(tag("("), multispace0),
1050 variable2,
1051 terminated(tag(")"), multispace0),
1052 ),
1053 )
1054 .parse(s);
1055 match res {
1056 Ok((s, (dot, (n, _h), var))) => Ok((
1057 s,
1058 Lang::Tag {
1059 name: n,
1060 value: Box::new(var),
1061 help_data: dot.into(),
1062 },
1063 )),
1064 Err(r) => Err(r),
1065 }
1066}
1067
1068fn tag_pattern_no_var(s: Span) -> IResult<Span, Lang> {
1070 let res = (tag("."), pascal_case).parse(s);
1071 match res {
1072 Ok((s, (dot, (n, _h)))) => Ok((
1073 s,
1074 Lang::Tag {
1075 name: n,
1076 value: Box::new(Lang::Empty(dot.clone().into())),
1077 help_data: dot.into(),
1078 },
1079 )),
1080 Err(r) => Err(r),
1081 }
1082}
1083
1084fn wildcard_pattern(s: Span) -> IResult<Span, Lang> {
1086 let res = terminated(tag("_"), multispace0).parse(s);
1087 match res {
1088 Ok((s, underscore)) => Ok((
1089 s,
1090 Lang::Variable {
1091 name: "_".to_string(),
1092 is_opaque: false,
1093 related_type: builder::empty_type(),
1094 help_data: underscore.into(),
1095 },
1096 )),
1097 Err(r) => Err(r),
1098 }
1099}
1100
1101fn type_pattern(s: Span) -> IResult<Span, Lang> {
1103 let res = (
1104 terminated(variable_exp, multispace0),
1105 terminated(tag("as"), multispace1),
1106 terminated(primitive_types, multispace0),
1107 )
1108 .parse(s);
1109 match res {
1110 Ok((s, ((name, h), _as, typ))) => Ok((
1111 s,
1112 Lang::TypePattern {
1113 variable_name: name,
1114 matched_type: typ,
1115 help_data: h,
1116 },
1117 )),
1118 Err(r) => Err(r),
1119 }
1120}
1121
1122fn match_pattern(s: Span) -> IResult<Span, Lang> {
1124 terminated(
1125 alt((
1126 tag_pattern_with_var,
1127 tag_pattern_no_var,
1128 record,
1129 keyword_positional_record_exp,
1130 tuple_exp,
1131 type_pattern,
1132 wildcard_pattern,
1133 variable2,
1134 )),
1135 multispace0,
1136 )
1137 .parse(s)
1138}
1139
1140fn pattern_branch(s: Span) -> IResult<Span, (Lang, Box<Lang>)> {
1142 let res = (
1143 terminated(match_pattern, multispace0),
1144 terminated(tag("=>"), multispace0),
1145 terminated(parse_elements, multispace0),
1146 opt(terminated(tag(","), multispace0)),
1147 )
1148 .parse(s);
1149 match res {
1150 Ok((s, (pat, _arr, lang, _vir))) => Ok((s, (pat, Box::new(lang)))),
1151 Err(r) => Err(r),
1152 }
1153}
1154
1155fn match_exp(s: Span) -> IResult<Span, Lang> {
1158 let res = (
1159 terminated(tag("match"), multispace1),
1160 terminated(alt((scope, variable2)), multispace0),
1161 terminated(tag("{"), multispace0),
1162 many1(pattern_branch),
1163 terminated(tag("}"), multispace0),
1164 )
1165 .parse(s);
1166 match res {
1167 Ok((s, (_m, exp, _o, bs, _c))) => Ok((
1168 s,
1169 Lang::Match {
1170 target: Box::new(exp),
1171 branches: bs,
1172 help_data: _m.into(),
1173 },
1174 )),
1175 Err(r) => Err(r),
1176 }
1177}
1178
1179pub fn tuple_exp(s: Span) -> IResult<Span, Lang> {
1180 let res = (
1181 terminated(alt((tag("list"), tag(":"))), multispace0),
1182 terminated(alt((tag("{"), tag("("))), multispace0),
1183 values,
1184 terminated(alt((tag("}"), tag(")"))), multispace0),
1185 )
1186 .parse(s);
1187 match res {
1188 Ok((s, (id, _op, vals, _cl))) => Ok((
1189 s,
1190 Lang::Tuple {
1191 value: vals,
1192 help_data: id.into(),
1193 },
1194 )),
1195 Err(r) => Err(r),
1196 }
1197}
1198
1199fn int_or_var(s: Span) -> IResult<Span, Lang> {
1200 alt((integer, variable2)).parse(s)
1201}
1202
1203fn create_range(params: &[Lang]) -> Lang {
1204 if params.len() == 2 {
1205 Lang::FunctionApp {
1206 identifier: Box::new(Var::from_name("seq").to_language()),
1207 arguments: vec![
1208 params[0].clone(),
1209 params[1].clone(),
1210 Lang::Integer {
1211 value: 1,
1212 help_data: HelpData::default(),
1213 },
1214 ],
1215 help_data: params.to_vec().into(),
1216 }
1217 } else {
1218 Lang::FunctionApp {
1219 identifier: Box::new(Var::from_name("seq").to_language()),
1220 arguments: vec![params[0].clone(), params[1].clone(), params[2].clone()],
1221 help_data: params.to_vec().into(),
1222 }
1223 }
1224}
1225
1226fn range(s: Span) -> IResult<Span, Lang> {
1227 let res = (int_or_var, tag(":"), opt(terminated(int_or_var, tag(":"))), int_or_var).parse(s);
1228 match res {
1230 Ok((s, (iv1, _sep, None, iv2))) => Ok((s, create_range(&[iv1.clone(), iv2.clone()]))),
1231 Ok((s, (iv1, _sep, Some(iv0), iv2))) => Ok((s, create_range(&[iv1.clone(), iv2.clone(), iv0.clone()]))),
1232 Err(r) => Err(r),
1233 }
1234}
1235
1236fn function_application2(s: Span) -> IResult<Span, Lang> {
1237 let res = recognize(function_application).parse(s);
1238 match res {
1239 Ok((s, fun_app)) => Ok((
1240 s,
1241 Lang::Exp {
1242 value: fun_app.to_string(),
1243 help_data: fun_app.into(),
1244 },
1245 )),
1246 Err(r) => Err(r),
1247 }
1248}
1249
1250fn dot_variable(s: Span) -> IResult<Span, Lang> {
1251 let res = preceded(tag("."), variable2).parse(s);
1252 match res {
1253 Ok((
1254 s,
1255 Lang::Variable {
1256 name: n,
1257 is_opaque: b,
1258 related_type: c,
1259 help_data: d,
1260 },
1261 )) => Ok((
1262 s,
1263 Lang::Variable {
1264 name: format!(".{}", n),
1265 is_opaque: b,
1266 related_type: c,
1267 help_data: d,
1268 },
1269 )),
1270 Ok((_s, _)) => todo!(),
1271 Err(r) => Err(r),
1272 }
1273}
1274
1275fn element_operator2(s: Span) -> IResult<Span, (Lang, Op)> {
1276 let res = (
1277 opt(op),
1278 alt((
1279 function_application2,
1280 null_value,
1281 number,
1282 integer,
1283 chars,
1284 boolean,
1285 variable2,
1286 dot_variable,
1287 )),
1288 )
1289 .parse(s);
1290 match res {
1291 Ok((s, (Some(ope), ele))) => Ok((s, (ele, ope))),
1292 Ok((s, (None, ele))) => Ok((s.clone(), (ele, Op::Empty(s.into())))),
1293 Err(r) => Err(r),
1294 }
1295}
1296
1297fn vectorial_bloc(s: Span) -> IResult<Span, Lang> {
1298 let res = (
1299 terminated(tag("@{"), multispace0),
1300 recognize(many1(element_operator2)),
1301 terminated(tag("}@"), multispace0),
1302 )
1303 .parse(s);
1304 match res {
1305 Ok((s, (_start, bloc, _end))) => Ok((
1306 s,
1307 Lang::VecBlock {
1308 value: bloc.fragment().to_string(),
1309 help_data: bloc.into(),
1310 },
1311 )),
1312 Err(r) => Err(r),
1313 }
1314}
1315
1316fn partial_application(s: Span) -> IResult<Span, Lang> {
1322 let res = (
1323 tag("\\"),
1324 variable2,
1325 terminated(tag("("), multispace0),
1326 many0(terminated(key_value, terminated(opt(tag(",")), multispace0))),
1327 terminated(tag(")"), multispace0),
1328 )
1329 .parse(s);
1330 match res {
1331 Ok((s, (start, ident, _, args, _))) => Ok((
1332 s,
1333 Lang::PartialApp {
1334 function: Box::new(ident),
1335 arguments: args,
1336 help_data: start.into(),
1337 },
1338 )),
1339 Err(r) => Err(r),
1340 }
1341}
1342
1343fn partial_constructor_application(s: Span) -> IResult<Span, Lang> {
1354 let res = (
1355 tag("\\"),
1356 pascal_case,
1357 terminated(tag(":"), multispace0),
1358 terminated(tag("{"), multispace0),
1359 many0(preceded(ws0, argument_val)),
1360 preceded(ws0, terminated(tag("}"), multispace0)),
1361 )
1362 .parse(s);
1363 match res {
1364 Ok((s, (start, (name, h), _, _, fields, _))) => {
1365 let arguments = fields
1366 .into_iter()
1367 .map(|ArgumentValue(key, value)| Lang::KeyValue {
1368 key,
1369 value: Box::new(value),
1370 help_data: h.clone(),
1371 })
1372 .collect();
1373 Ok((
1374 s,
1375 Lang::PartialApp {
1376 function: Box::new(Lang::Variable {
1377 name,
1378 is_opaque: false,
1379 related_type: Type::Empty(h.clone()),
1380 help_data: h,
1381 }),
1382 arguments,
1383 help_data: start.into(),
1384 },
1385 ))
1386 }
1387 Err(r) => Err(r),
1388 }
1389}
1390
1391fn lambda(s: Span) -> IResult<Span, Lang> {
1392 let res = (
1393 tag("\\"),
1394 terminated(tag("("), multispace0),
1395 many0(terminated(variable, opt((tag(","), multispace0)))),
1396 terminated(tag(")"), multispace0),
1397 parse_elements,
1398 )
1399 .parse(s);
1400 match res {
1401 Ok((s, (start, _, v, _, body))) => Ok((
1402 s,
1403 Lang::Lambda {
1404 parameters: v.iter().map(|(var, _)| var).cloned().collect(),
1405 body: Box::new(body.clone()),
1406 help_data: start.into(),
1407 },
1408 )),
1409 Err(r) => Err(r),
1410 }
1411}
1412
1413fn not_exp(s: Span) -> IResult<Span, Lang> {
1414 let res = (
1415 tag("!"),
1416 alt((
1417 tag_exp,
1418 range,
1419 lambda,
1420 boolean,
1421 number,
1422 integer,
1423 chars,
1424 match_exp,
1425 if_exp,
1426 dotdotdot,
1427 vector,
1428 record,
1429 keyword_positional_record_exp,
1430 r_function,
1431 function,
1432 tuple_exp,
1433 function_application,
1434 array_indexing,
1435 variable2,
1436 scope,
1437 array,
1438 )),
1439 )
1440 .parse(s);
1441 match res {
1442 Ok((s, (not_op, lang))) => Ok((
1443 s,
1444 Lang::Not {
1445 value: Box::new(lang),
1446 help_data: not_op.into(),
1447 },
1448 )),
1449 Err(r) => Err(r),
1450 }
1451}
1452
1453fn array_variant(s: Span) -> IResult<Span, Lang> {
1454 alt((vector, sequence)).parse(s)
1455}
1456
1457fn js_block(s: Span) -> IResult<Span, Lang> {
1458 let res = (terminated(tag("JS"), multispace0), scope).parse(s);
1459
1460 match res {
1461 Ok((s, (js, body))) => Ok((s, Lang::JSBlock(Box::new(body), 0, js.into()))),
1462 Err(r) => Err(r),
1463 }
1464}
1465
1466fn primitive(s: Span) -> IResult<Span, Lang> {
1467 alt((null_value, na_value, boolean, number, integer, chars)).parse(s)
1468}
1469
1470pub fn return_exp(s: Span) -> IResult<Span, Lang> {
1471 let res = terminated(delimited(tag("return "), parse_elements, tag(";")), multispace0).parse(s);
1472 match res {
1473 Ok((s, el)) => Ok((
1474 s,
1475 Lang::Return {
1476 value: Box::new(el.clone()),
1477 help_data: el.into(),
1478 },
1479 )),
1480 Err(r) => Err(r),
1481 }
1482}
1483
1484pub fn break_exp(s: Span) -> IResult<Span, Vec<Lang>> {
1485 let res = tag("break;").parse(s);
1486 match res {
1487 Ok((s, el)) => Ok((s, vec![Lang::Break(el.into())])),
1488 Err(r) => Err(r),
1489 }
1490}
1491
1492pub fn next_exp(s: Span) -> IResult<Span, Vec<Lang>> {
1493 let res = tag("next;").parse(s);
1494 match res {
1495 Ok((s, el)) => Ok((s, vec![Lang::Next(el.into())])),
1496 Err(r) => Err(r),
1497 }
1498}
1499
1500pub fn single_element(s: Span) -> IResult<Span, Lang> {
1502 alt((
1503 alt((
1504 not_exp,
1505 tag_exp,
1506 union_constructor,
1507 range,
1508 partial_application,
1509 partial_constructor_application,
1510 lambda,
1511 primitive,
1512 js_block,
1513 return_exp,
1514 match_exp,
1515 if_exp,
1516 dotdotdot,
1517 array_variant,
1518 )),
1519 alt((
1520 dataframe_exp,
1521 array_constructor_call,
1522 constructor_call,
1523 record,
1524 keyword_positional_record_exp,
1525 r_function,
1526 r_block,
1527 extern_block,
1528 function,
1529 tuple_exp,
1530 function_application,
1531 array_indexing,
1532 variable2,
1533 scope,
1534 array,
1535 )),
1536 ))
1537 .parse(s)
1538}
1539
1540pub fn scope(s: Span) -> IResult<Span, Lang> {
1541 let res = (
1542 terminated(alt((tag("("), tag("{"))), multispace0),
1543 opt(base_parse),
1544 terminated(preceded(multispace0, alt((tag(")"), tag("}")))), multispace0),
1545 )
1546 .parse(s);
1547 match res {
1548 Ok((s, (open, Some(v), _))) if v.is_empty() => Ok((
1549 s,
1550 Lang::Scope {
1551 body: vec![],
1552 help_data: open.into(),
1553 },
1554 )),
1555 Ok((s, (_, Some(v), _))) => Ok((
1556 s,
1557 Lang::Scope {
1558 body: v.clone(),
1559 help_data: v.into(),
1560 },
1561 )),
1562 Ok((s, (open, None, _))) => Ok((
1563 s,
1564 Lang::Scope {
1565 body: vec![],
1566 help_data: open.into(),
1567 },
1568 )),
1569 Err(r) => Err(r),
1570 }
1571}
1572
1573fn element_operator_token(s: Span) -> IResult<Span, LangToken> {
1574 match op.parse(s) {
1575 Ok((s, op)) => Ok((s, LangToken::Operator(op))),
1576 Err(r) => Err(r),
1577 }
1578}
1579
1580fn single_element_token(s: Span) -> IResult<Span, LangToken> {
1581 match single_element.parse(s) {
1582 Ok((s, op)) => Ok((s, LangToken::Expression(op))),
1583 Err(r) => Err(r),
1584 }
1585}
1586
1587fn as_excl_operator_token(s: Span) -> IResult<Span, LangToken> {
1588 let res = terminated(tag("as!"), multispace0).parse(s);
1589 match res {
1590 Ok((s, tok)) => Ok((s, LangToken::Operator(Op::AsExcl(tok.into())))),
1591 Err(r) => Err(r),
1592 }
1593}
1594
1595fn single_equals_recovery_token(s: Span) -> IResult<Span, LangToken> {
1612 let res = terminated(terminated(recognize(char('=')), not(char('>'))), multispace0).parse(s);
1613 match res {
1614 Ok((s, eq)) => {
1615 push_parse_error(SyntaxError::SingleEqualsComparison(eq.clone().into()));
1616 Ok((s, LangToken::Operator(Op::Eq(eq.into()))))
1617 }
1618 Err(r) => Err(r),
1619 }
1620}
1621
1622fn operator_like_token(s: Span) -> IResult<Span, LangToken> {
1635 alt((
1636 as_excl_operator_token,
1637 element_operator_token,
1638 single_equals_recovery_token,
1639 ))
1640 .parse(s)
1641}
1642
1643pub fn elements(s: Span) -> IResult<Span, Lang> {
1644 let res = (
1645 single_element_token,
1646 many0(pair(operator_like_token, single_element_token)),
1647 )
1648 .parse(s);
1649 match res {
1650 Ok((s, (first, rest))) => {
1651 if rest.is_empty() {
1652 Ok((s, first.into()))
1653 } else {
1654 let mut v = vec![first];
1655 for (op, ex) in rest {
1656 v.push(op);
1657 v.push(ex);
1658 }
1659 Ok((s, VectorPriority::from(v).run()))
1660 }
1661 }
1662 Err(r) => Err(r),
1663 }
1664}
1665
1666pub fn parse_elements(s: Span) -> IResult<Span, Lang> {
1668 alt((vectorial_bloc, elements)).parse(s)
1669}
1670
1671#[cfg(test)]
1672mod tests {
1673 use super::*;
1674 use crate::utils::fluent_parser::FluentParser;
1675
1676 #[test]
1677 fn test_extern_block_parse() {
1678 let res = r##"extern (x: int, y: char) -> char r#"paste0(x, y)"#"##.parse::<Lang>();
1679 println!("extern_block parse: {:?}", res.as_ref().map(|l| l.simple_print()));
1680 assert!(res.is_ok(), "extern_block should parse successfully");
1681 assert!(
1682 matches!(res.unwrap(), Lang::ExternBlock { .. }),
1683 "should be ExternBlock"
1684 );
1685 }
1686
1687 #[test]
1688 fn test_extern_block_no_params_parse() {
1689 let res = r##"extern () -> int r#"42L"#"##.parse::<Lang>();
1690 println!("extern_block no-params: {:?}", res.as_ref().map(|l| l.simple_print()));
1691 assert!(res.is_ok(), "extern_block no-params should parse");
1692 assert!(matches!(res.unwrap(), Lang::ExternBlock { .. }));
1693 }
1694
1695 #[test]
1696 fn test_r_block_parse() {
1697 let res = "R { sum(c(1,2,3)) }".parse::<Lang>();
1698 assert!(res.is_ok(), "r_block should parse successfully");
1699 match res.unwrap() {
1700 Lang::RBlock { value, .. } => assert_eq!(value, "{ sum(c(1,2,3)) }"),
1701 other => panic!("expected RBlock, got {}", other.simple_print()),
1702 }
1703 }
1704
1705 #[test]
1706 fn test_r_block_multiline_with_pipe() {
1707 let src = "R {\n df %>%\n filter(x > 1) %>%\n mutate(z = if (y) { 1 } else { 2 })\n}";
1711 let res = src.parse::<Lang>();
1712 assert!(res.is_ok(), "multiline r_block with nested braces should parse");
1713 assert!(matches!(res.unwrap(), Lang::RBlock { .. }));
1714 }
1715
1716 #[test]
1717 fn test_r_block_transpiles_to_bare_r_block() {
1718 let fp = FluentParser::new().push("R { 1 + 2 }").run();
1719 let r_code = fp.get_r_code().iter().cloned().collect::<Vec<_>>().join("\n");
1720 assert_eq!(r_code.trim(), "{ 1 + 2 }");
1721 }
1722
1723 #[test]
1724 fn test_empty_scope() {
1725 let res = "{ }".parse::<Lang>().unwrap();
1726 assert!(matches!(res, Lang::Scope { body, .. } if body.is_empty()));
1727 }
1728
1729 #[test]
1730 fn test_decode_escapes() {
1731 assert_eq!(decode_escapes("hello"), "hello");
1732 assert_eq!(decode_escapes(r#"say \"hi\""#), r#"say "hi""#);
1733 assert_eq!(decode_escapes(r"it\'s"), "it's");
1734 assert_eq!(decode_escapes(r"a\\b"), r"a\b");
1735 assert_eq!(decode_escapes(r"line1\nline2"), "line1\nline2");
1736 }
1737
1738 #[test]
1739 fn test_backslash_escapes_parse_in_string_literals() {
1740 for (src, expected) in [
1744 (r#""\n""#, "\n"),
1745 (r#""\t""#, "\t"),
1746 (r#""a\\b""#, r"a\b"),
1747 (r#"'\n'"#, "\n"),
1748 (r#""line1\nline2""#, "line1\nline2"),
1749 ] {
1750 match src.parse::<Lang>() {
1751 Ok(Lang::Char { value, .. }) => assert_eq!(value, expected, "wrong decoded value for {src}"),
1752 other => panic!("expected Lang::Char for {src}, got {:?}", other),
1753 }
1754 }
1755 }
1756
1757 #[test]
1758 fn test_char_value_is_decoded() {
1759 let from_double = r#""say \"hi\"""#.parse::<Lang>().unwrap();
1761 let from_single = r#"'say "hi"'"#.parse::<Lang>().unwrap();
1762 match (from_double, from_single) {
1763 (Lang::Char { value: d, .. }, Lang::Char { value: s, .. }) => {
1764 assert_eq!(d, r#"say "hi""#);
1765 assert_eq!(s, r#"say "hi""#);
1766 }
1767 other => panic!("expected two Lang::Char, got {:?}", other),
1768 }
1769 }
1770
1771 #[test]
1772 fn test_function_with_empty_scope3() {
1773 let res = simple_function("fn(): int { 5 }".into()).unwrap().1;
1774 assert_eq!(res.simple_print(), "Function");
1775 }
1776
1777 #[test]
1778 fn test_variable1() {
1779 let res = variable_exp("hello".into()).unwrap().1 .0;
1780 assert_eq!(res, "hello", "Should return the variable name 'hello'");
1781 }
1782
1783 #[test]
1784 fn test_simple_variable1() {
1785 let res = variable_exp("hello".into()).unwrap().1 .0;
1786 assert_eq!(res, "hello", "Should return the variable name 'hello'");
1787 }
1788
1789 #[test]
1790 fn test_addition1() {
1791 let res = "1 + 2".parse::<Lang>().unwrap();
1792 assert_eq!(res.simple_print(), "Operator", "Should parse 1 + 2");
1793 }
1794
1795 #[test]
1796 fn test_addition2() {
1797 let res = "1 + 2 + 3".parse::<Lang>().unwrap();
1798 assert_eq!(res.simple_print(), "Operator", "Should parse 1 + 2 + 3");
1799 }
1800
1801 #[test]
1802 fn test_multiplication1() {
1803 let res = "1 + 2 * 3".parse::<Lang>().unwrap();
1804 assert_eq!(
1805 res.simple_print(),
1806 "Operator",
1807 "Should put multiplication first 1 + 2 * 3"
1808 );
1809 }
1810
1811 #[test]
1812 fn test_multiplication2() {
1813 let res = "1 * 2 + 3".parse::<Lang>().unwrap();
1814 assert_eq!(
1815 res.simple_print(),
1816 "Operator",
1817 "Should put multiplication first 1 * 2 + 3"
1818 );
1819 }
1820
1821 #[test]
1822 fn test_multiplication3() {
1823 let res = "1 * 2 + 3 * 4".parse::<Lang>().unwrap();
1824 assert_eq!(
1825 res.simple_print(),
1826 "Operator",
1827 "Should put multiplication first 1 * 2 + 3 * 4"
1828 );
1829 }
1830
1831 #[test]
1832 fn test_accessor1() {
1833 let res = "3 + personne$age ".parse::<Lang>().unwrap();
1834 assert_eq!(
1835 res.simple_print(),
1836 "Operator",
1837 "Should put multiplication first 1 * 2 + 3 * 4"
1838 );
1839 }
1840
1841 #[test]
1842 fn test_and1() {
1843 let res = "true & true".parse::<Lang>().unwrap();
1844 assert_eq!(res.simple_print(), "Operator", "Should accept '&&'");
1845 }
1846
1847 #[test]
1848 fn test_array_indexing0() {
1849 let res = array_indexing("name[1, 2, 3]".into()).unwrap().1;
1850 assert_eq!(res.simple_print(), "ArrayIndexing");
1851 }
1852
1853 #[test]
1854 fn test_array_indexing() {
1855 let fp = FluentParser::new().push("name[1, 2, 3]").parse_next();
1856 assert_eq!(fp.get_last_log(), "The logs are empty");
1857 }
1858
1859 #[test]
1860 fn test_quoted_variable() {
1861 let res = quoted_variable("`+`".into()).unwrap().1;
1862 assert_eq!(res.0, "`+`");
1863 }
1864
1865 #[test]
1866 fn test_uniform_function_call() {
1867 let fp = FluentParser::new().push("true.not()").parse_next();
1868 assert_eq!(fp.get_last_log(), "The logs are empty");
1869 }
1870
1871 #[test]
1872 fn test_key_value1() {
1873 let res = key_value("sep = '3'".into()).unwrap().1;
1874 assert_eq!(res.simple_print(), "KeyValue");
1875 }
1876
1877 #[test]
1878 fn test_empty_char0() {
1879 let res = single_element("''".into()).unwrap().1;
1880 assert_eq!(res.simple_print(), "Char");
1881 }
1882
1883 #[test]
1884 fn test_empty_char1() {
1885 let res = primitive("''".into()).unwrap().1;
1886 assert_eq!(res.simple_print(), "Char");
1887 }
1888
1889 #[test]
1890 fn test_empty_char2() {
1891 let res = chars("''".into()).unwrap().1;
1892 assert_eq!(res.simple_print(), "Char");
1893 }
1894
1895 #[test]
1898 fn test_null_value_lowercase() {
1899 let res = null_value("null ".into()).unwrap().1;
1900 assert_eq!(res.simple_print(), "Null");
1901 }
1902
1903 #[test]
1904 fn test_null_value_uppercase() {
1905 let res = null_value("NULL ".into()).unwrap().1;
1906 assert_eq!(res.simple_print(), "Null");
1907 }
1908
1909 #[test]
1910 fn test_null_via_primitive() {
1911 let res = primitive("null ".into()).unwrap().1;
1912 assert_eq!(res.simple_print(), "Null");
1913 }
1914
1915 #[test]
1916 fn test_null_via_single_element() {
1917 let res = single_element("null ".into()).unwrap().1;
1918 assert_eq!(res.simple_print(), "Null");
1919 }
1920
1921 #[test]
1922 fn test_null_parse_lang() {
1923 let res = "null".parse::<Lang>().unwrap();
1924 assert_eq!(res.simple_print(), "Null");
1925 }
1926
1927 #[test]
1928 fn test_null_type_check() {
1929 let fp = FluentParser::new()
1930 .push("let x: null <- null;")
1931 .parse_type_next()
1932 .push("x")
1933 .parse_next();
1934 assert_eq!(fp.get_last_type(), crate::utils::builder::null_type());
1935 }
1936
1937 #[test]
1940 fn test_match_pattern_tag_with_binding() {
1941 let input = "match x { .Some(a) => a, .None => 0 }";
1942 let res = match_exp(input.into()).unwrap().1;
1943 assert_eq!(res.simple_print(), "Match");
1944 }
1945
1946 #[test]
1947 fn test_match_pattern_with_wildcard() {
1948 let input = "match x { .Some(a) => a, _ => 0 }";
1949 let res = match_exp(input.into()).unwrap().1;
1950 assert_eq!(res.simple_print(), "Match");
1951 }
1952
1953 #[test]
1954 fn test_match_pattern_tag_without_binding() {
1955 let input = "match x { .None => 7 }";
1956 let res = match_exp(input.into()).unwrap().1;
1957 assert_eq!(res.simple_print(), "Match");
1958 }
1959
1960 #[test]
1961 fn test_match_pattern_multiple_branches() {
1962 let input = "match value { .Some(a) => a + 1, .None => 0, _ => 9 }";
1963 let res = match_exp(input.into()).unwrap().1;
1964 assert_eq!(res.simple_print(), "Match");
1965 if let Lang::Match { branches, .. } = &res {
1967 assert_eq!(branches.len(), 3, "Should have 3 branches");
1968 } else {
1969 panic!("Expected Match variant");
1970 }
1971 }
1972
1973 #[test]
1974 fn test_match_pattern_via_single_element() {
1975 let input = "match x { .Some(a) => a, .None => 0 } ";
1976 let res = single_element(input.into()).unwrap().1;
1977 assert_eq!(res.simple_print(), "Match");
1978 }
1979
1980 #[test]
1981 fn test_match_pattern_branch_tag_with_var() {
1982 let input = ".Some(a) => a + 1, ";
1983 let res = pattern_branch(input.into()).unwrap().1;
1984 let (pattern, _body) = res;
1985 assert_eq!(pattern.simple_print(), "Tag");
1986 }
1987
1988 #[test]
1989 fn test_match_pattern_branch_wildcard() {
1990 let input = "_ => 42 ";
1991 let res = pattern_branch(input.into()).unwrap().1;
1992 let (pattern, _body) = res;
1993 assert_eq!(pattern.simple_print(), "Variable(_)");
1994 }
1995
1996 #[test]
1997 fn test_match_pattern_branch_tag_no_binding() {
1998 let input = ".None => 7, ";
1999 let res = pattern_branch(input.into()).unwrap().1;
2000 let (pattern, body) = res;
2001 assert_eq!(pattern.simple_print(), "Tag");
2002 assert_eq!(body.simple_print(), "Integer");
2003 }
2004
2005 #[test]
2006 fn test_wildcard_pattern() {
2007 let input = "_ ";
2008 let res = wildcard_pattern(input.into()).unwrap().1;
2009 assert_eq!(res.simple_print(), "Variable(_)");
2010 }
2011
2012 #[test]
2013 fn test_tag_pattern_with_var() {
2014 let input = ".Some(a)";
2015 let res = tag_pattern_with_var(input.into()).unwrap().1;
2016 assert_eq!(res.simple_print(), "Tag");
2017 if let Lang::Tag { name, value: inner, .. } = &res {
2018 assert_eq!(name, "Some");
2019 assert_eq!(inner.simple_print(), "Variable(a)");
2020 } else {
2021 panic!("Expected Tag variant");
2022 }
2023 }
2024
2025 #[test]
2026 fn test_tag_pattern_no_var() {
2027 let input = ".None ";
2028 let res = tag_pattern_no_var(input.into()).unwrap().1;
2029 assert_eq!(res.simple_print(), "Tag");
2030 if let Lang::Tag { name, value: inner, .. } = &res {
2031 assert_eq!(name, "None");
2032 assert_eq!(inner.simple_print(), "Empty");
2033 } else {
2034 panic!("Expected Tag variant");
2035 }
2036 }
2037
2038 #[test]
2039 fn test_match_pattern_multiline() {
2040 let input = "match result {
2041 .Some(value) => value + 1,
2042 .None => 0,
2043 _ => 99
2044 } ";
2045 let res = match_exp(input.into()).unwrap().1;
2046 assert_eq!(res.simple_print(), "Match");
2047 if let Lang::Match { branches, .. } = &res {
2048 assert_eq!(branches.len(), 3);
2049 } else {
2050 panic!("Expected Match variant");
2051 }
2052 }
2053
2054 #[test]
2057 fn test_type_pattern_int() {
2058 let input = "x as int ";
2059 let res = type_pattern(input.into()).unwrap().1;
2060 assert!(
2061 res.simple_print().starts_with("TypePattern"),
2062 "Should parse 'x as int' as TypePattern"
2063 );
2064 if let Lang::TypePattern {
2065 variable_name: name, ..
2066 } = &res
2067 {
2068 assert_eq!(name, "x");
2069 } else {
2070 panic!("Expected TypePattern variant");
2071 }
2072 }
2073
2074 #[test]
2075 fn test_type_pattern_bool() {
2076 let input = "y as bool ";
2077 let res = type_pattern(input.into()).unwrap().1;
2078 if let Lang::TypePattern {
2079 variable_name: name, ..
2080 } = &res
2081 {
2082 assert_eq!(name, "y");
2083 } else {
2084 panic!("Expected TypePattern variant");
2085 }
2086 }
2087
2088 #[test]
2089 fn test_type_pattern_num() {
2090 let input = "val as num ";
2091 let res = type_pattern(input.into()).unwrap().1;
2092 if let Lang::TypePattern {
2093 variable_name: name, ..
2094 } = &res
2095 {
2096 assert_eq!(name, "val");
2097 } else {
2098 panic!("Expected TypePattern variant");
2099 }
2100 }
2101
2102 #[test]
2103 fn test_type_pattern_char() {
2104 let input = "s as char ";
2105 let res = type_pattern(input.into()).unwrap().1;
2106 if let Lang::TypePattern {
2107 variable_name: name, ..
2108 } = &res
2109 {
2110 assert_eq!(name, "s");
2111 } else {
2112 panic!("Expected TypePattern variant");
2113 }
2114 }
2115
2116 #[test]
2117 fn test_match_with_type_patterns() {
2118 let input = "match x { y as int => y + 1, z as bool => 0 } ";
2119 let res = match_exp(input.into()).unwrap().1;
2120 assert_eq!(res.simple_print(), "Match");
2121 if let Lang::Match { branches, .. } = &res {
2122 assert_eq!(branches.len(), 2, "Should have 2 branches");
2123 assert!(
2124 branches[0].0.simple_print().starts_with("TypePattern"),
2125 "First branch should be a TypePattern"
2126 );
2127 assert!(
2128 branches[1].0.simple_print().starts_with("TypePattern"),
2129 "Second branch should be a TypePattern"
2130 );
2131 } else {
2132 panic!("Expected Match variant");
2133 }
2134 }
2135
2136 #[test]
2137 fn test_match_mixed_tag_and_type_patterns() {
2138 let input = "match value {
2139 .Some(a) => a,
2140 x as int => x + 1,
2141 _ => 0
2142 } ";
2143 let res = match_exp(input.into()).unwrap().1;
2144 assert_eq!(res.simple_print(), "Match");
2145 if let Lang::Match { branches, .. } = &res {
2146 assert_eq!(branches.len(), 3, "Should have 3 branches");
2147 assert_eq!(branches[0].0.simple_print(), "Tag");
2148 assert!(branches[1].0.simple_print().starts_with("TypePattern"));
2149 assert_eq!(branches[2].0.simple_print(), "Variable(_)");
2150 } else {
2151 panic!("Expected Match variant");
2152 }
2153 }
2154
2155 #[test]
2156 fn test_type_pattern_in_match_pattern() {
2157 let input = "x as int ";
2158 let res = match_pattern(input.into()).unwrap().1;
2159 assert!(
2160 res.simple_print().starts_with("TypePattern"),
2161 "match_pattern should accept type patterns"
2162 );
2163 }
2164
2165 #[test]
2168 fn test_record_pattern_colon_syntax() {
2169 let input = ":{nom: n, age: a} ";
2170 let res = match_pattern(input.into()).unwrap().1;
2171 assert_eq!(res.simple_print(), "Record", "Should parse record pattern as Record");
2172 if let Lang::List { value: fields, .. } = &res {
2173 assert_eq!(fields.len(), 2);
2174 assert_eq!(fields[0].get_argument(), "nom");
2175 assert_eq!(fields[1].get_argument(), "age");
2176 } else {
2177 panic!("Expected List variant");
2178 }
2179 }
2180
2181 #[test]
2182 fn test_record_pattern_list_syntax() {
2183 let input = "list(nom = n, age = a) ";
2184 let res = match_pattern(input.into()).unwrap().1;
2185 assert_eq!(res.simple_print(), "Record");
2186 if let Lang::List { value: fields, .. } = &res {
2187 assert_eq!(fields.len(), 2);
2188 assert_eq!(fields[0].get_argument(), "nom");
2189 assert_eq!(fields[1].get_argument(), "age");
2190 } else {
2191 panic!("Expected List variant");
2192 }
2193 }
2194
2195 #[test]
2196 fn test_match_with_record_pattern() {
2197 let input = "match x { :{nom: n, age: a} => a, _ => 0 } ";
2198 let res = match_exp(input.into()).unwrap().1;
2199 assert_eq!(res.simple_print(), "Match");
2200 if let Lang::Match { branches, .. } = &res {
2201 assert_eq!(branches.len(), 2, "Should have 2 branches");
2202 assert_eq!(
2203 branches[0].0.simple_print(),
2204 "Record",
2205 "First branch should be a Record pattern"
2206 );
2207 assert_eq!(branches[1].0.simple_print(), "Variable(_)");
2208 } else {
2209 panic!("Expected Match variant");
2210 }
2211 }
2212
2213 #[test]
2214 fn test_match_with_list_pattern() {
2215 let input = "match x { list(nom = n, age = a) => a, _ => 0 } ";
2216 let res = match_exp(input.into()).unwrap().1;
2217 assert_eq!(res.simple_print(), "Match");
2218 if let Lang::Match { branches, .. } = &res {
2219 assert_eq!(branches.len(), 2);
2220 assert_eq!(branches[0].0.simple_print(), "Record");
2221 } else {
2222 panic!("Expected Match variant");
2223 }
2224 }
2225
2226 #[test]
2227 fn test_match_mixed_record_tag_type_patterns() {
2228 let input = "match value {
2229 .Some(a) => a,
2230 :{nom: n, age: a} => a,
2231 x as int => x + 1,
2232 _ => 0
2233 } ";
2234 let res = match_exp(input.into()).unwrap().1;
2235 assert_eq!(res.simple_print(), "Match");
2236 if let Lang::Match { branches, .. } = &res {
2237 assert_eq!(branches.len(), 4);
2238 assert_eq!(branches[0].0.simple_print(), "Tag");
2239 assert_eq!(branches[1].0.simple_print(), "Record");
2240 assert!(branches[2].0.simple_print().starts_with("TypePattern"));
2241 assert_eq!(branches[3].0.simple_print(), "Variable(_)");
2242 } else {
2243 panic!("Expected Match variant");
2244 }
2245 }
2246
2247 #[test]
2248 fn test_record_pattern_single_field() {
2249 let input = ":{nom: n} ";
2250 let res = match_pattern(input.into()).unwrap().1;
2251 assert_eq!(res.simple_print(), "Record");
2252 if let Lang::List { value: fields, .. } = &res {
2253 assert_eq!(fields.len(), 1);
2254 assert_eq!(fields[0].get_argument(), "nom");
2255 } else {
2256 panic!("Expected List variant");
2257 }
2258 }
2259
2260 #[test]
2263 fn test_tuple_pattern_colon_syntax() {
2264 let input = ":{a, b, c} ";
2265 let res = match_pattern(input.into()).unwrap().1;
2266 assert_eq!(res.simple_print(), "Tuple");
2267 if let Lang::Tuple { value: elements, .. } = &res {
2268 assert_eq!(elements.len(), 3);
2269 } else {
2270 panic!("Expected Tuple variant");
2271 }
2272 }
2273
2274 #[test]
2275 fn test_tuple_pattern_list_syntax() {
2276 let input = "list(a, b, c) ";
2277 let res = match_pattern(input.into()).unwrap().1;
2278 assert_eq!(res.simple_print(), "Tuple");
2279 if let Lang::Tuple { value: elements, .. } = &res {
2280 assert_eq!(elements.len(), 3);
2281 } else {
2282 panic!("Expected Tuple variant");
2283 }
2284 }
2285
2286 #[test]
2287 fn test_tuple_pattern_two_elements() {
2288 let input = ":{x, y} ";
2289 let res = match_pattern(input.into()).unwrap().1;
2290 assert_eq!(res.simple_print(), "Tuple");
2291 if let Lang::Tuple { value: elements, .. } = &res {
2292 assert_eq!(elements.len(), 2);
2293 } else {
2294 panic!("Expected Tuple variant");
2295 }
2296 }
2297
2298 #[test]
2299 fn test_match_with_tuple_pattern() {
2300 let input = "match x { :{a, b, c} => a + c, _ => 0 } ";
2301 let res = match_exp(input.into()).unwrap().1;
2302 assert_eq!(res.simple_print(), "Match");
2303 if let Lang::Match { branches, .. } = &res {
2304 assert_eq!(branches.len(), 2);
2305 assert_eq!(branches[0].0.simple_print(), "Tuple");
2306 assert_eq!(branches[1].0.simple_print(), "Variable(_)");
2307 } else {
2308 panic!("Expected Match variant");
2309 }
2310 }
2311
2312 #[test]
2313 fn test_match_with_list_tuple_pattern() {
2314 let input = "match x { list(a, b, c) => a + c, _ => 0 } ";
2315 let res = match_exp(input.into()).unwrap().1;
2316 assert_eq!(res.simple_print(), "Match");
2317 if let Lang::Match { branches, .. } = &res {
2318 assert_eq!(branches.len(), 2);
2319 assert_eq!(branches[0].0.simple_print(), "Tuple");
2320 } else {
2321 panic!("Expected Match variant");
2322 }
2323 }
2324
2325 #[test]
2326 fn test_match_mixed_all_pattern_types() {
2327 let input = "match value {
2328 .Some(a) => a,
2329 :{nom: n, age: a} => a,
2330 :{x, y} => x + y,
2331 z as int => z + 1,
2332 _ => 0
2333 } ";
2334 let res = match_exp(input.into()).unwrap().1;
2335 assert_eq!(res.simple_print(), "Match");
2336 if let Lang::Match { branches, .. } = &res {
2337 assert_eq!(branches.len(), 5);
2338 assert_eq!(branches[0].0.simple_print(), "Tag");
2339 assert_eq!(branches[1].0.simple_print(), "Record");
2340 assert_eq!(branches[2].0.simple_print(), "Tuple");
2341 assert!(branches[3].0.simple_print().starts_with("TypePattern"));
2342 assert_eq!(branches[4].0.simple_print(), "Variable(_)");
2343 } else {
2344 panic!("Expected Match variant");
2345 }
2346 }
2347
2348 #[test]
2349 fn test_character_constructor_fn() {
2350 let input = "fn(name: char, attack: int, health: int): Character {\n :{ name: name, attack: attack, health: health }\n}";
2351 let res = simple_function(input.into());
2352 match &res {
2353 Ok((remaining, _)) => {
2354 println!("SUCCESS, remaining: {:?}", **remaining);
2355 assert!(
2356 remaining.is_empty(),
2357 "Should consume entire input, remaining: {:?}",
2358 **remaining
2359 );
2360 }
2361 Err(e) => panic!("Parse failed: {:?}", e),
2362 }
2363 }
2364
2365 #[test]
2366 fn test_scope_with_record_body() {
2367 let input = "{\n :{ name: name, attack: attack, health: health }\n}";
2368 let res = scope(input.into());
2369 match &res {
2370 Ok((remaining, _)) => {
2371 println!("scope SUCCESS, remaining: {:?}", **remaining);
2372 }
2373 Err(e) => println!("scope FAILED: {:?}", e),
2374 }
2375 assert!(res.is_ok(), "scope should succeed");
2376 }
2377
2378 #[test]
2379 fn test_record_parse_directly() {
2380 use crate::processes::parsing::base_parse;
2381 let input = ":{ name: name, attack: attack, health: health }";
2382 let res = base_parse(input.into());
2383 println!(
2384 "base_parse result: {:?}",
2385 res.as_ref().map(|(r, v): &(_, Vec<_>)| (*r.fragment(), v.len()))
2386 );
2387 assert!(res.is_ok());
2388 let (remaining, elems) = res.unwrap();
2389 println!(" remaining: {:?}", *remaining.fragment());
2390 println!(" elements count: {}", elems.len());
2391 for (i, el) in elems.iter().enumerate() {
2392 println!(" elem[{}]: {}", i, el.simple_print());
2393 }
2394 }
2395
2396 #[test]
2397 fn test_parse_elements_record() {
2398 let input = ":{ name: name, attack: attack, health: health }";
2399 let res = parse_elements(input.into());
2400 match &res {
2401 Ok((remaining, lang)) => println!(
2402 "parse_elements OK: {}, remaining: {:?}",
2403 lang.simple_print(),
2404 **remaining
2405 ),
2406 Err(e) => println!("parse_elements FAILED: {:?}", e),
2407 }
2408 assert!(res.is_ok(), "parse_elements should succeed on record");
2409 }
2410
2411 #[test]
2412 fn test_single_element_record() {
2413 let input = ":{ name: name, attack: attack, health: health }";
2414 let res = single_element(input.into());
2415 match &res {
2416 Ok((remaining, lang)) => println!(
2417 "single_element OK: {}, remaining: {:?}",
2418 lang.simple_print(),
2419 **remaining
2420 ),
2421 Err(e) => println!("single_element FAILED: {:?}", e),
2422 }
2423 assert!(res.is_ok(), "single_element should succeed on record");
2424 }
2425
2426 #[test]
2427 fn test_record_logic_inline() {
2428 let input = ":{ name: name, attack: attack, health: health }";
2429 let res = record(input.into());
2430 match &res {
2431 Ok((remaining, lang)) => println!("record OK: {}, remaining: {:?}", lang.simple_print(), **remaining),
2432 Err(e) => println!("record FAILED: {:?}", e),
2433 }
2434 assert!(res.is_ok(), "record should succeed");
2435 }
2436
2437 #[test]
2438 fn test_module_constructor_parsing() {
2439 let (_, lang) = constructor_call("person$Person:{ age = 12, name = \"Bob\" }".into())
2440 .expect("Should parse module constructor call");
2441 match lang {
2442 Lang::ConstructorCall {
2443 module_path, type_name, ..
2444 } => {
2445 assert_eq!(module_path, vec!["person".to_string()]);
2446 assert_eq!(type_name, "Person");
2447 }
2448 other => panic!("Expected ConstructorCall, got: {}", other.simple_print()),
2449 }
2450
2451 let fp = FluentParser::new()
2452 .push("module person { @pub type Person <- list { age: int, name: char }; };")
2453 .run()
2454 .push("let p <- person$Person:{ age = 12, name = \"Bob\" };")
2455 .run();
2456 assert_eq!(fp.get_last_log(), "The logs are empty");
2457 }
2458
2459 #[test]
2460 fn test_constructor_call_spread_parsing() {
2461 let (_, lang) = constructor_call("Person:{ name = \"Alice\", ..bob }".into())
2462 .expect("Should parse constructor call with spread");
2463 match lang {
2464 Lang::ConstructorCall {
2465 type_name,
2466 fields,
2467 spread,
2468 ..
2469 } => {
2470 assert_eq!(type_name, "Person");
2471 assert_eq!(fields.len(), 1);
2472 assert_eq!(fields[0].get_argument(), "name");
2473 let (path, name, _) = spread.expect("Should have a spread");
2474 assert!(path.is_empty());
2475 assert_eq!(name, "bob");
2476 }
2477 other => panic!("Expected ConstructorCall, got: {}", other.simple_print()),
2478 }
2479 }
2480
2481 #[test]
2482 fn test_constructor_call_runtime_spread_parsing() {
2483 let (_, lang) = constructor_call("Person:{ name = \"Alice\", ...bob }".into())
2484 .expect("Should parse constructor call with runtime spread");
2485 match lang {
2486 Lang::ConstructorCall {
2487 type_name,
2488 fields,
2489 spread,
2490 spreads,
2491 ..
2492 } => {
2493 assert_eq!(type_name, "Person");
2494 assert_eq!(fields.len(), 1);
2495 assert_eq!(fields[0].get_argument(), "name");
2496 assert!(spread.is_none());
2497 assert_eq!(spreads.len(), 1);
2498 }
2499 other => panic!("Expected ConstructorCall, got: {}", other.simple_print()),
2500 }
2501 }
2502
2503 #[test]
2504 fn test_record_literal_spread_parsing() {
2505 let (_, lang) = record(":{ ...x, a = 1 }".into()).expect("Should parse record literal with spread");
2506 match lang {
2507 Lang::List { value, spreads, .. } => {
2508 assert_eq!(value.len(), 1);
2509 assert_eq!(value[0].get_argument(), "a");
2510 assert_eq!(spreads.len(), 1);
2511 assert!(matches!(&spreads[0], Lang::Variable { name, .. } if name == "x"));
2512 }
2513 other => panic!("Expected Lang::List, got: {}", other.simple_print()),
2514 }
2515 }
2516
2517 #[test]
2518 fn test_record_literal_multiple_spreads_parsing() {
2519 let (_, lang) =
2520 record(":{ ...x, ...y, a = 1 }".into()).expect("Should parse record literal with multiple spreads");
2521 match lang {
2522 Lang::List { value, spreads, .. } => {
2523 assert_eq!(value.len(), 1);
2524 assert_eq!(spreads.len(), 2);
2525 }
2526 other => panic!("Expected Lang::List, got: {}", other.simple_print()),
2527 }
2528 }
2529
2530 #[test]
2531 fn test_record_literal_bare_spread_parsing() {
2532 let (_, lang) = record(":{ ...x }".into()).expect("Should parse record literal with bare spread");
2533 match lang {
2534 Lang::List { value, spreads, .. } => {
2535 assert!(value.is_empty());
2536 assert_eq!(spreads.len(), 1);
2537 }
2538 other => panic!("Expected Lang::List, got: {}", other.simple_print()),
2539 }
2540 }
2541}