1use pest::iterators::Pair;
4
5use super::ast::*;
6use super::literals::{parse_complex, parse_number, parse_raw_string, parse_string};
7use super::Rule;
8
9fn unescape_backtick_ident(s: &str) -> String {
12 s.replace("\\`", "`")
13}
14
15pub(super) fn parse_ident_str(pair: Pair<Rule>) -> String {
16 let s = pair.as_str();
17 if s.starts_with('`') && s.ends_with('`') {
18 unescape_backtick_ident(&s[1..s.len() - 1])
19 } else {
20 s.to_string()
21 }
22}
23
24pub(super) fn parse_ident_or_string(pair: Pair<Rule>) -> String {
25 let s = pair.as_str();
26 if s.starts_with('`') && s.ends_with('`') {
27 unescape_backtick_ident(&s[1..s.len() - 1])
28 } else if (s.starts_with('"') && s.ends_with('"')) || (s.starts_with('\'') && s.ends_with('\''))
29 {
30 super::literals::unescape_string(&s[1..s.len() - 1])
31 } else {
32 s.to_string()
33 }
34}
35
36pub(super) fn build_program(pair: Pair<Rule>) -> Expr {
41 let mut exprs = Vec::new();
42 for p in pair.into_inner() {
43 match p.as_rule() {
44 Rule::expr_seq => {
45 for child in p.into_inner() {
46 if child.as_rule() == Rule::expr {
47 exprs.push(build_expr(child));
48 }
49 }
50 }
51 Rule::EOI => {}
52 _ => {}
53 }
54 }
55 if exprs.len() == 1 {
56 exprs
57 .into_iter()
58 .next()
59 .expect("parser: single-expr program should have one element")
60 } else {
61 Expr::Program(exprs)
62 }
63}
64
65pub(super) fn build_expr(pair: Pair<Rule>) -> Expr {
66 match pair.as_rule() {
67 Rule::expr => build_expr(
68 pair.into_inner()
69 .next()
70 .expect("parser: expr should have inner expression"),
71 ),
72 Rule::help_expr => build_help(pair),
73 Rule::assign_eq_expr => build_assign_eq(pair),
74 Rule::walrus_expr => build_walrus(pair),
75 Rule::assign_left_expr => build_assign_left(pair),
76 Rule::assign_right_expr => build_assign_right(pair),
77 Rule::formula_expr => build_formula(pair),
78 Rule::or_expr => build_binary_left(pair, |op| match op.as_str() {
79 "||" => BinaryOp::OrScalar,
80 "|" => BinaryOp::Or,
81 _ => unreachable!(),
82 }),
83 Rule::and_expr => build_binary_left(pair, |op| match op.as_str() {
84 "&&" => BinaryOp::AndScalar,
85 "&" => BinaryOp::And,
86 _ => unreachable!(),
87 }),
88 Rule::not_expr => build_not(pair),
89 Rule::compare_expr => build_binary_left(pair, |op| match op.as_str() {
90 "==" => BinaryOp::Eq,
91 "!=" => BinaryOp::Ne,
92 "<" => BinaryOp::Lt,
93 ">" => BinaryOp::Gt,
94 "<=" => BinaryOp::Le,
95 ">=" => BinaryOp::Ge,
96 _ => unreachable!(),
97 }),
98 Rule::add_expr => build_binary_left(pair, |op| match op.as_str() {
99 "+" => BinaryOp::Add,
100 "-" => BinaryOp::Sub,
101 _ => unreachable!(),
102 }),
103 Rule::mul_expr => build_binary_left(pair, |op| match op.as_str() {
104 "*" => BinaryOp::Mul,
105 "/" => BinaryOp::Div,
106 _ => unreachable!(),
107 }),
108 Rule::special_pipe_expr => build_special_pipe(pair),
109 Rule::colon_expr => build_colon(pair),
110 Rule::unary_expr => build_unary(pair),
111 Rule::power_expr => build_power(pair),
112 Rule::postfix_expr => build_postfix_expr(pair),
113 Rule::namespace_expr => build_namespace_expr(pair),
114 Rule::primary_expr => build_primary(pair),
115 Rule::keyword_constant => build_primary(pair),
116 _ => build_primary(pair),
117 }
118}
119
120fn build_help(pair: Pair<Rule>) -> Expr {
125 let mut inner = pair.into_inner();
126 let first = inner
127 .next()
128 .expect("parser: help_expr should have at least one child");
129 if first.as_rule() == Rule::help_expr {
130 let topic = extract_help_topic(&first);
132 Expr::Call {
134 func: Box::new(Expr::Symbol("invisible".to_string())),
135 args: vec![Arg {
136 name: None,
137 value: Some(Expr::Call {
138 func: Box::new(Expr::Symbol("help".to_string())),
139 args: vec![Arg {
140 name: None,
141 value: Some(Expr::String(topic)),
142 }],
143 span: None,
144 }),
145 }],
146 span: None,
147 }
148 } else {
149 let pkg_text = first.as_str().trim().to_string();
152 match inner.next() {
153 Some(rhs) => {
154 let topic = extract_help_topic(&rhs);
155 Expr::Call {
156 func: Box::new(Expr::Symbol("invisible".to_string())),
157 args: vec![Arg {
158 name: None,
159 value: Some(Expr::Call {
160 func: Box::new(Expr::Symbol("help".to_string())),
161 args: vec![
162 Arg {
163 name: None,
164 value: Some(Expr::String(topic)),
165 },
166 Arg {
167 name: Some("package".to_string()),
168 value: Some(Expr::String(pkg_text)),
169 },
170 ],
171 span: None,
172 }),
173 }],
174 span: None,
175 }
176 }
177 None => build_expr(first),
178 }
179 }
180}
181
182fn extract_help_topic(pair: &Pair<Rule>) -> String {
186 let text = pair.as_str().trim();
187 let text = text.strip_prefix('?').unwrap_or(text).trim();
189 if let Some(paren_pos) = text.find('(') {
191 let name = text[..paren_pos].trim();
192 if !name.is_empty()
193 && name
194 .chars()
195 .all(|c| c.is_alphanumeric() || c == '.' || c == '_')
196 {
197 return name.to_string();
198 }
199 }
200 text.to_string()
201}
202
203fn build_assign_eq(pair: Pair<Rule>) -> Expr {
208 let mut inner = pair.into_inner();
209 let lhs = build_expr(
210 inner
211 .next()
212 .expect("parser: assign_eq_expr should have LHS"),
213 );
214 match inner.next() {
215 None => lhs,
216 Some(op_pair) => {
217 assert!(op_pair.as_rule() == Rule::eq_assign_op);
218 let rhs = build_expr(
219 inner
220 .next()
221 .expect("parser: assign_eq_expr should have RHS after '='"),
222 );
223 Expr::Assign {
224 op: AssignOp::Equals,
225 target: Box::new(lhs),
226 value: Box::new(rhs),
227 }
228 }
229 }
230}
231
232fn build_walrus(pair: Pair<Rule>) -> Expr {
233 let mut inner = pair.into_inner();
234 let lhs = build_expr(inner.next().expect("parser: walrus_expr should have LHS"));
235 match inner.next() {
236 None => lhs,
237 Some(op_pair) => {
238 assert!(op_pair.as_rule() == Rule::walrus_assign_op);
239 let rhs = build_expr(
240 inner
241 .next()
242 .expect("parser: walrus_expr should have RHS after ':='"),
243 );
244 Expr::BinaryOp {
245 op: BinaryOp::Special(SpecialOp::Walrus),
246 lhs: Box::new(lhs),
247 rhs: Box::new(rhs),
248 }
249 }
250 }
251}
252
253fn build_assign_left(pair: Pair<Rule>) -> Expr {
254 let mut inner = pair.into_inner();
255 let lhs = build_expr(
256 inner
257 .next()
258 .expect("parser: assign_left_expr should have LHS"),
259 );
260 match inner.next() {
261 None => lhs,
262 Some(op_pair) => {
263 let op = match op_pair.as_str() {
264 "<-" => AssignOp::LeftAssign,
265 "<<-" => AssignOp::SuperAssign,
266 _ => unreachable!(),
267 };
268 let rhs = build_expr(
269 inner
270 .next()
271 .expect("parser: assign_left_expr should have RHS after '<-'/'<<-'"),
272 );
273 Expr::Assign {
274 op,
275 target: Box::new(lhs),
276 value: Box::new(rhs),
277 }
278 }
279 }
280}
281
282fn build_assign_right(pair: Pair<Rule>) -> Expr {
283 let mut inner = pair.into_inner();
284 let mut result = build_expr(
285 inner
286 .next()
287 .expect("parser: assign_right_expr should have LHS"),
288 );
289 while let Some(op_pair) = inner.next() {
290 let op = match op_pair.as_str() {
291 "->" => AssignOp::RightAssign,
292 "->>" => AssignOp::RightSuperAssign,
293 _ => unreachable!(),
294 };
295 let target = build_expr(
296 inner
297 .next()
298 .expect("parser: assign_right_expr should have target after '->'/'->>'"),
299 );
300 result = Expr::Assign {
301 op,
302 target: Box::new(target),
303 value: Box::new(result),
304 };
305 }
306 result
307}
308
309fn build_formula(pair: Pair<Rule>) -> Expr {
314 let mut inner = pair.into_inner();
315 let first = inner
316 .next()
317 .expect("parser: formula_expr should have at least one child");
318
319 if first.as_rule() == Rule::formula_expr {
320 let rhs = build_expr(first);
322 Expr::Formula {
323 lhs: None,
324 rhs: Some(Box::new(rhs)),
325 }
326 } else {
327 let lhs = build_expr(first);
328 match inner.next() {
329 None => lhs,
330 Some(op_pair) => {
331 let rhs = build_expr(
332 inner
333 .next()
334 .expect("parser: formula_expr should have RHS after tilde op"),
335 );
336 let remaining: Vec<_> = inner.collect();
337
338 if op_pair.as_rule() == Rule::tilde_op
339 && op_pair.as_str() == "~"
340 && remaining.is_empty()
341 {
342 return Expr::Formula {
343 lhs: Some(Box::new(lhs)),
344 rhs: Some(Box::new(rhs)),
345 };
346 }
347
348 let mut expr = Expr::BinaryOp {
349 op: map_tilde_op(&op_pair),
350 lhs: Box::new(lhs),
351 rhs: Box::new(rhs),
352 };
353
354 let mut remaining = remaining.into_iter();
355 while let Some(next_op) = remaining.next() {
356 let next_rhs = build_expr(
357 remaining
358 .next()
359 .expect("parser: chained tilde should have RHS after operator"),
360 );
361 expr = Expr::BinaryOp {
362 op: map_tilde_op(&next_op),
363 lhs: Box::new(expr),
364 rhs: Box::new(next_rhs),
365 };
366 }
367
368 expr
369 }
370 }
371 }
372}
373
374fn map_tilde_op(pair: &Pair<Rule>) -> BinaryOp {
375 match pair.as_str() {
376 "~" => BinaryOp::Tilde,
377 "~~" => BinaryOp::DoubleTilde,
378 _ => unreachable!(),
379 }
380}
381
382fn build_binary_left(pair: Pair<Rule>, map_op: impl Fn(&Pair<Rule>) -> BinaryOp) -> Expr {
387 let mut inner = pair.into_inner();
388 let mut lhs = build_expr(
389 inner
390 .next()
391 .expect("parser: binary expression should have LHS"),
392 );
393 while let Some(op_pair) = inner.next() {
394 let op = map_op(&op_pair);
395 let rhs = build_expr(
396 inner
397 .next()
398 .expect("parser: binary expression should have RHS after operator"),
399 );
400 lhs = Expr::BinaryOp {
401 op,
402 lhs: Box::new(lhs),
403 rhs: Box::new(rhs),
404 };
405 }
406 lhs
407}
408
409fn build_not(pair: Pair<Rule>) -> Expr {
410 let mut inner = pair.into_inner();
411 let first = inner.next().expect("parser: not_expr should have operand");
412 if first.as_rule() == Rule::compare_expr {
413 build_expr(first)
414 } else {
415 let operand = build_expr(first);
417 Expr::UnaryOp {
418 op: UnaryOp::Not,
419 operand: Box::new(operand),
420 }
421 }
422}
423
424fn build_special_pipe(pair: Pair<Rule>) -> Expr {
425 let mut inner = pair.into_inner();
426 let mut lhs = build_expr(
427 inner
428 .next()
429 .expect("parser: special_pipe_expr should have LHS"),
430 );
431 while let Some(op_pair) = inner.next() {
432 let op = match op_pair.as_rule() {
433 Rule::pipe_op => BinaryOp::Pipe,
434 Rule::special_op => match op_pair.as_str() {
435 "%in%" => BinaryOp::Special(SpecialOp::In),
436 "%*%" => BinaryOp::Special(SpecialOp::MatMul),
437 "%x%" => BinaryOp::Special(SpecialOp::Kronecker),
438 "%%" => BinaryOp::Mod,
439 "%/%" => BinaryOp::IntDiv,
440 "%>%" => BinaryOp::Pipe,
442 "%<>%" => BinaryOp::AssignPipe,
443 "%T>%" => BinaryOp::TeePipe,
444 "%$%" => BinaryOp::ExpoPipe,
445 other => BinaryOp::Special(SpecialOp::Other(other.to_string())),
446 },
447 _ => unreachable!(),
448 };
449 let rhs = build_expr(
450 inner
451 .next()
452 .expect("parser: special/pipe expression should have RHS after operator"),
453 );
454 lhs = Expr::BinaryOp {
455 op,
456 lhs: Box::new(lhs),
457 rhs: Box::new(rhs),
458 };
459 }
460 lhs
461}
462
463fn build_colon(pair: Pair<Rule>) -> Expr {
464 let mut inner = pair.into_inner();
465 let mut lhs = build_expr(inner.next().expect("parser: colon_expr should have LHS"));
466 for rhs_pair in inner {
467 lhs = Expr::BinaryOp {
468 op: BinaryOp::Range,
469 lhs: Box::new(lhs),
470 rhs: Box::new(build_expr(rhs_pair)),
471 };
472 }
473 lhs
474}
475
476fn build_unary(pair: Pair<Rule>) -> Expr {
477 let mut inner = pair.into_inner();
478 let first = inner
479 .next()
480 .expect("parser: unary_expr should have operator or operand");
481 match first.as_rule() {
482 Rule::unary_op => {
483 let op = match first.as_str() {
484 "-" => UnaryOp::Neg,
485 "+" => UnaryOp::Pos,
486 _ => unreachable!(),
487 };
488 let operand = build_expr(
489 inner
490 .next()
491 .expect("parser: unary_expr should have operand after unary operator"),
492 );
493 Expr::UnaryOp {
494 op,
495 operand: Box::new(operand),
496 }
497 }
498 Rule::unary_expr => {
500 let operand = build_expr(first);
501 Expr::UnaryOp {
502 op: UnaryOp::Not,
503 operand: Box::new(operand),
504 }
505 }
506 _ => build_expr(first),
507 }
508}
509
510fn build_power(pair: Pair<Rule>) -> Expr {
511 let mut inner = pair.into_inner();
512 let base = build_expr(
513 inner
514 .next()
515 .expect("parser: power_expr should have base expression"),
516 );
517 match inner.next() {
519 None => base,
520 Some(next) => {
521 let rhs_pair = if next.as_rule() == Rule::power_op {
522 inner
523 .next()
524 .expect("parser: power_expr should have exponent after '^'/'**'")
525 } else {
526 next
527 };
528 Expr::BinaryOp {
529 op: BinaryOp::Pow,
530 lhs: Box::new(base),
531 rhs: Box::new(build_expr(rhs_pair)),
532 }
533 }
534 }
535}
536
537fn build_postfix_expr(pair: Pair<Rule>) -> Expr {
542 let mut inner = pair.into_inner();
543 let mut expr = build_expr(
544 inner
545 .next()
546 .expect("parser: postfix_expr should have base expression"),
547 );
548 for suffix in inner {
549 expr = build_postfix_suffix(expr, suffix);
550 }
551 expr
552}
553
554fn build_postfix_suffix(object: Expr, pair: Pair<Rule>) -> Expr {
555 let outer_span = pair.as_span();
557 let pair = if pair.as_rule() == Rule::postfix_suffix {
558 pair.into_inner()
559 .next()
560 .expect("parser: postfix_suffix should have inner suffix kind")
561 } else {
562 pair
563 };
564 match pair.as_rule() {
565 Rule::call_suffix => {
566 let args = pair
567 .into_inner()
568 .filter(|p| p.as_rule() == Rule::arg_list)
569 .flat_map(build_arg_list)
570 .collect();
571 Expr::Call {
572 func: Box::new(object),
573 args,
574 span: Some(crate::parser::ast::Span {
575 start: u32::try_from(outer_span.start()).unwrap_or(0),
576 end: u32::try_from(outer_span.end()).unwrap_or(0),
577 }),
578 }
579 }
580 Rule::index1_suffix => {
581 let indices = pair
582 .into_inner()
583 .filter(|p| p.as_rule() == Rule::sub_list)
584 .flat_map(build_sub_list)
585 .collect();
586 Expr::Index {
587 object: Box::new(object),
588 indices,
589 }
590 }
591 Rule::index2_suffix => {
592 let indices = pair
593 .into_inner()
594 .filter(|p| p.as_rule() == Rule::sub_list)
595 .flat_map(build_sub_list)
596 .collect();
597 Expr::IndexDouble {
598 object: Box::new(object),
599 indices,
600 }
601 }
602 Rule::dollar_suffix => {
603 let inner = pair
604 .into_inner()
605 .next()
606 .expect("parser: dollar_suffix should have member name");
607 let name = match inner.as_rule() {
608 Rule::dots => "...".to_string(),
609 _ => parse_ident_or_string(inner),
610 };
611 Expr::Dollar {
612 object: Box::new(object),
613 member: name,
614 }
615 }
616 Rule::slot_suffix => {
617 let inner = pair
618 .into_inner()
619 .next()
620 .expect("parser: slot_suffix should have slot name");
621 let name = parse_ident_str(inner);
622 Expr::Slot {
623 object: Box::new(object),
624 member: name,
625 }
626 }
627 _ => unreachable!("unexpected postfix: {:?}", pair.as_rule()),
628 }
629}
630
631fn build_namespace_expr(pair: Pair<Rule>) -> Expr {
632 let mut inner = pair.into_inner();
633 let mut expr = build_expr(
634 inner
635 .next()
636 .expect("parser: namespace_expr should have base expression"),
637 );
638 for suffix in inner {
639 if suffix.as_rule() == Rule::namespace_suffix {
640 let mut ns_inner = suffix.into_inner();
641 let op_pair = ns_inner
642 .next()
643 .expect("parser: namespace_suffix should have '::' or ':::'");
644 let op_str = op_pair.as_str();
645 let name_pair = ns_inner
646 .next()
647 .expect("parser: namespace_suffix should have name after '::'/':::'");
648 let name = parse_ident_or_string(name_pair);
649 expr = if op_str == ":::" {
650 Expr::NsGetInt {
651 namespace: Box::new(expr),
652 name,
653 }
654 } else {
655 Expr::NsGet {
656 namespace: Box::new(expr),
657 name,
658 }
659 };
660 }
661 }
662 expr
663}
664
665fn build_primary(pair: Pair<Rule>) -> Expr {
670 let pair = match pair.as_rule() {
671 Rule::primary_expr | Rule::keyword_constant => pair
672 .into_inner()
673 .next()
674 .expect("parser: primary_expr/keyword_constant should have inner content"),
675 _ => pair,
676 };
677
678 match pair.as_rule() {
679 Rule::null_lit => Expr::Null,
680 Rule::na_lit => {
681 let s = pair.as_str();
682 let na_type = if s.starts_with("NA_complex") {
683 NaType::Complex
684 } else if s.starts_with("NA_character") {
685 NaType::Character
686 } else if s.starts_with("NA_real") {
687 NaType::Real
688 } else if s.starts_with("NA_integer") {
689 NaType::Integer
690 } else {
691 NaType::Logical
692 };
693 Expr::Na(na_type)
694 }
695 Rule::inf_lit => Expr::Inf,
696 Rule::nan_lit => Expr::NaN,
697 Rule::bool_lit => {
698 let val = pair.as_str().starts_with('T');
699 Expr::Bool(val)
700 }
701 Rule::complex_number => parse_complex(pair),
702 Rule::number => parse_number(pair),
703 Rule::raw_string => parse_raw_string(pair),
704 Rule::string => parse_string(pair),
705 Rule::dots => Expr::Dots,
706 Rule::dotdot => {
707 let s = pair.as_str();
708 let n: u32 = s[2..].parse().unwrap_or(1);
709 Expr::DotDot(n)
710 }
711 Rule::formula_literal => {
712 let rhs = pair
713 .into_inner()
714 .next()
715 .map(build_expr)
716 .unwrap_or(Expr::Null);
717 Expr::Formula {
718 lhs: None,
719 rhs: Some(Box::new(rhs)),
720 }
721 }
722 Rule::ident => {
723 let name = parse_ident_str(pair);
724 Expr::Symbol(name)
725 }
726 Rule::if_expr => build_if(pair),
727 Rule::for_expr => build_for(pair),
728 Rule::while_expr => build_while(pair),
729 Rule::repeat_expr => {
730 let body = pair
731 .into_inner()
732 .find(|p| p.as_rule() == Rule::expr)
733 .map(build_expr)
734 .unwrap_or(Expr::Null);
735 Expr::Repeat {
736 body: Box::new(body),
737 }
738 }
739 Rule::break_expr => Expr::Break,
740 Rule::next_expr => Expr::Next,
741 Rule::return_expr => {
742 let val = pair
743 .into_inner()
744 .find(|p| p.as_rule() == Rule::expr)
745 .map(|p| Box::new(build_expr(p)));
746 Expr::Return(val)
747 }
748 Rule::function_def | Rule::lambda_def => build_function(pair),
749 Rule::block => build_block(pair),
750 Rule::paren_expr => {
751 let inner = pair
752 .into_inner()
753 .find(|p| p.as_rule() == Rule::expr)
754 .expect("parser: paren_expr should contain an expression");
755 build_expr(inner)
756 }
757 _ => build_expr(pair),
758 }
759}
760
761fn build_if(pair: Pair<Rule>) -> Expr {
766 let mut exprs: Vec<Expr> = pair
767 .into_inner()
768 .filter(|p| p.as_rule() == Rule::expr)
769 .map(build_expr)
770 .collect();
771 let condition = exprs.remove(0);
772 let then_body = exprs.remove(0);
773 let else_body = if !exprs.is_empty() {
774 Some(Box::new(exprs.remove(0)))
775 } else {
776 None
777 };
778 Expr::If {
779 condition: Box::new(condition),
780 then_body: Box::new(then_body),
781 else_body,
782 }
783}
784
785fn build_for(pair: Pair<Rule>) -> Expr {
786 let inner = pair.into_inner();
787 let mut var = String::new();
788 let mut exprs = Vec::new();
789 for p in inner {
790 match p.as_rule() {
791 Rule::ident => var = parse_ident_str(p),
792 Rule::expr => exprs.push(build_expr(p)),
793 _ => {}
794 }
795 }
796 let iter = exprs.remove(0);
797 let body = exprs.remove(0);
798 Expr::For {
799 var,
800 iter: Box::new(iter),
801 body: Box::new(body),
802 }
803}
804
805fn build_while(pair: Pair<Rule>) -> Expr {
806 let exprs: Vec<Expr> = pair
807 .into_inner()
808 .filter(|p| p.as_rule() == Rule::expr)
809 .map(build_expr)
810 .collect();
811 Expr::While {
812 condition: Box::new(exprs[0].clone()),
813 body: Box::new(exprs[1].clone()),
814 }
815}
816
817fn build_function(pair: Pair<Rule>) -> Expr {
818 let inner = pair.into_inner();
819 let mut params = Vec::new();
820 let mut body = None;
821
822 for p in inner {
823 match p.as_rule() {
824 Rule::param_list => {
825 params = build_param_list(p);
826 }
827 Rule::expr => {
828 body = Some(build_expr(p));
829 }
830 _ => {}
831 }
832 }
833
834 Expr::Function {
835 params,
836 body: Box::new(body.unwrap_or(Expr::Null)),
837 }
838}
839
840fn build_param_list(pair: Pair<Rule>) -> Vec<Param> {
841 pair.into_inner()
842 .filter(|p| p.as_rule() == Rule::param)
843 .map(|p| {
844 let mut inner = p.into_inner();
845 let first = inner
846 .next()
847 .expect("parser: param should have name or dots");
848 if first.as_rule() == Rule::dots {
849 Param {
850 name: "...".to_string(),
851 default: None,
852 is_dots: true,
853 }
854 } else {
855 let name = parse_ident_str(first);
856 let default = inner.find(|p| p.as_rule() == Rule::expr).map(build_expr);
858 Param {
859 name,
860 default,
861 is_dots: false,
862 }
863 }
864 })
865 .collect()
866}
867
868fn build_block(pair: Pair<Rule>) -> Expr {
869 let mut exprs = Vec::new();
870 for p in pair.into_inner() {
871 match p.as_rule() {
872 Rule::expr_seq => {
873 for child in p.into_inner() {
874 if child.as_rule() == Rule::expr {
875 exprs.push(build_expr(child));
876 }
877 }
878 }
879 Rule::expr => exprs.push(build_expr(p)),
880 _ => {}
881 }
882 }
883 if exprs.is_empty() {
884 Expr::Null
885 } else {
886 Expr::Block(exprs)
887 }
888}
889
890fn build_arg_list(pair: Pair<Rule>) -> Vec<Arg> {
895 pair.into_inner()
896 .filter(|p| p.as_rule() == Rule::arg_slot)
897 .map(|slot| {
898 match slot.into_inner().next() {
899 None => Arg {
900 name: None,
901 value: None,
902 }, Some(arg_pair) => build_arg_or_sub(arg_pair),
904 }
905 })
906 .collect()
907}
908
909fn build_sub_list(pair: Pair<Rule>) -> Vec<Arg> {
910 pair.into_inner()
911 .filter(|p| p.as_rule() == Rule::sub_slot)
912 .map(|slot| {
913 match slot.into_inner().next() {
914 None => Arg {
915 name: None,
916 value: None,
917 }, Some(sub_pair) => build_arg_or_sub(sub_pair),
919 }
920 })
921 .collect()
922}
923
924fn build_arg_or_sub(pair: Pair<Rule>) -> Arg {
926 let inner_pair = pair
927 .into_inner()
928 .next()
929 .expect("parser: arg/sub should have content");
930 match inner_pair.as_rule() {
931 Rule::named_arg | Rule::named_sub_arg => build_named_arg(inner_pair),
932 _ => Arg {
933 name: None,
934 value: Some(build_expr(inner_pair)),
935 },
936 }
937}
938
939fn build_named_arg(pair: Pair<Rule>) -> Arg {
940 let mut inner = pair.into_inner();
941 let name_pair = inner
942 .next()
943 .expect("parser: named_arg should have arg name");
944 let name = match name_pair.as_rule() {
945 Rule::arg_name => {
946 let inner_name = name_pair
947 .into_inner()
948 .next()
949 .expect("parser: arg_name should have identifier, string, or dots");
950 match inner_name.as_rule() {
951 Rule::dots => "...".to_string(),
952 Rule::dotdot => inner_name.as_str().to_string(),
953 Rule::string => super::literals::parse_string_value(inner_name),
954 _ => parse_ident_str(inner_name),
955 }
956 }
957 _ => parse_ident_str(name_pair),
958 };
959 let value = inner.find(|p| p.as_rule() == Rule::expr).map(build_expr);
961 Arg {
962 name: Some(name),
963 value,
964 }
965}
966
967