1use crate::ast::*;
2use harn_lexer::{Span, TokenKind};
3
4use super::error::ParserError;
5use super::state::Parser;
6
7impl Parser {
8 pub fn parse_single_expression(&mut self) -> Result<SNode, ParserError> {
10 self.skip_newlines();
11 self.parse_expression()
12 }
13
14 pub(super) fn parse_expression(&mut self) -> Result<SNode, ParserError> {
15 self.skip_newlines();
16 self.parse_pipe()
17 }
18
19 pub(super) fn parse_pipe(&mut self) -> Result<SNode, ParserError> {
20 let mut left = self.parse_range()?;
21 while self.check_skip_newlines(&TokenKind::Pipe) {
22 let start = left.span;
23 self.advance();
24 let right = self.parse_range()?;
25 left = spanned(
26 Node::BinaryOp {
27 op: "|>".into(),
28 left: Box::new(left),
29 right: Box::new(right),
30 },
31 Span::merge(start, self.prev_span()),
32 );
33 }
34 Ok(left)
35 }
36
37 pub(super) fn parse_range(&mut self) -> Result<SNode, ParserError> {
38 let left = self.parse_ternary()?;
39 if self.check(&TokenKind::To) {
40 let start = left.span;
41 self.advance();
42 let right = self.parse_ternary()?;
43 let inclusive = if self.check(&TokenKind::Exclusive) {
44 self.advance();
45 false
46 } else {
47 true
48 };
49 return Ok(spanned(
50 Node::RangeExpr {
51 start: Box::new(left),
52 end: Box::new(right),
53 inclusive,
54 },
55 Span::merge(start, self.prev_span()),
56 ));
57 }
58 Ok(left)
59 }
60
61 pub(super) fn parse_ternary(&mut self) -> Result<SNode, ParserError> {
62 let condition = self.parse_logical_or()?;
63 if !self.check(&TokenKind::Question) {
64 return Ok(condition);
65 }
66 let start = condition.span;
67 self.advance(); let true_val = self.parse_logical_or()?;
69 self.consume(&TokenKind::Colon, ":")?;
70 let false_val = self.parse_logical_or()?;
71 Ok(spanned(
72 Node::Ternary {
73 condition: Box::new(condition),
74 true_expr: Box::new(true_val),
75 false_expr: Box::new(false_val),
76 },
77 Span::merge(start, self.prev_span()),
78 ))
79 }
80
81 pub(super) fn parse_nil_coalescing(&mut self) -> Result<SNode, ParserError> {
84 let mut left = self.parse_multiplicative()?;
85 while self.check(&TokenKind::NilCoal) {
86 let start = left.span;
87 self.advance();
88 let right = self.parse_multiplicative()?;
89 left = spanned(
90 Node::BinaryOp {
91 op: "??".into(),
92 left: Box::new(left),
93 right: Box::new(right),
94 },
95 Span::merge(start, self.prev_span()),
96 );
97 }
98 Ok(left)
99 }
100
101 pub(super) fn parse_logical_or(&mut self) -> Result<SNode, ParserError> {
102 let mut left = self.parse_logical_and()?;
103 while self.check_skip_newlines(&TokenKind::Or) {
104 let start = left.span;
105 self.advance();
106 let right = self.parse_logical_and()?;
107 left = spanned(
108 Node::BinaryOp {
109 op: "||".into(),
110 left: Box::new(left),
111 right: Box::new(right),
112 },
113 Span::merge(start, self.prev_span()),
114 );
115 }
116 Ok(left)
117 }
118
119 pub(super) fn parse_logical_and(&mut self) -> Result<SNode, ParserError> {
120 let mut left = self.parse_equality()?;
121 while self.check_skip_newlines(&TokenKind::And) {
122 let start = left.span;
123 self.advance();
124 let right = self.parse_equality()?;
125 left = spanned(
126 Node::BinaryOp {
127 op: "&&".into(),
128 left: Box::new(left),
129 right: Box::new(right),
130 },
131 Span::merge(start, self.prev_span()),
132 );
133 }
134 Ok(left)
135 }
136
137 pub(super) fn parse_equality(&mut self) -> Result<SNode, ParserError> {
138 let mut left = self.parse_comparison()?;
139 while self.check(&TokenKind::Eq) || self.check(&TokenKind::Neq) {
140 let start = left.span;
141 let op = if self.check(&TokenKind::Eq) {
142 "=="
143 } else {
144 "!="
145 };
146 self.advance();
147 let right = self.parse_comparison()?;
148 left = spanned(
149 Node::BinaryOp {
150 op: op.into(),
151 left: Box::new(left),
152 right: Box::new(right),
153 },
154 Span::merge(start, self.prev_span()),
155 );
156 }
157 Ok(left)
158 }
159
160 pub(super) fn parse_comparison(&mut self) -> Result<SNode, ParserError> {
161 let mut left = self.parse_additive()?;
162 loop {
163 if self.check(&TokenKind::Lt)
164 || self.check(&TokenKind::Gt)
165 || self.check(&TokenKind::Lte)
166 || self.check(&TokenKind::Gte)
167 {
168 let start = left.span;
169 let op = match self.current().map(|t| &t.kind) {
170 Some(TokenKind::Lt) => "<",
171 Some(TokenKind::Gt) => ">",
172 Some(TokenKind::Lte) => "<=",
173 Some(TokenKind::Gte) => ">=",
174 _ => "<",
175 };
176 self.advance();
177 let right = self.parse_additive()?;
178 left = spanned(
179 Node::BinaryOp {
180 op: op.into(),
181 left: Box::new(left),
182 right: Box::new(right),
183 },
184 Span::merge(start, self.prev_span()),
185 );
186 } else if self.check(&TokenKind::In) {
187 let start = left.span;
188 self.advance();
189 let right = self.parse_additive()?;
190 left = spanned(
191 Node::BinaryOp {
192 op: "in".into(),
193 left: Box::new(left),
194 right: Box::new(right),
195 },
196 Span::merge(start, self.prev_span()),
197 );
198 } else if self.check_identifier("not") {
199 let saved = self.pos;
200 self.advance();
201 if self.check(&TokenKind::In) {
202 let start = left.span;
203 self.advance();
204 let right = self.parse_additive()?;
205 left = spanned(
206 Node::BinaryOp {
207 op: "not_in".into(),
208 left: Box::new(left),
209 right: Box::new(right),
210 },
211 Span::merge(start, self.prev_span()),
212 );
213 } else {
214 self.pos = saved;
215 break;
216 }
217 } else {
218 break;
219 }
220 }
221 Ok(left)
222 }
223
224 pub(super) fn parse_additive(&mut self) -> Result<SNode, ParserError> {
225 let mut left = self.parse_nil_coalescing()?;
226 while self.check_skip_newlines(&TokenKind::Plus) || self.check(&TokenKind::Minus) {
227 let start = left.span;
228 let op = if self.check(&TokenKind::Plus) {
229 "+"
230 } else {
231 "-"
232 };
233 self.advance();
234 let right = self.parse_nil_coalescing()?;
235 left = spanned(
236 Node::BinaryOp {
237 op: op.into(),
238 left: Box::new(left),
239 right: Box::new(right),
240 },
241 Span::merge(start, self.prev_span()),
242 );
243 }
244 Ok(left)
245 }
246
247 pub(super) fn parse_multiplicative(&mut self) -> Result<SNode, ParserError> {
248 let mut left = self.parse_exponent()?;
249 while self.check_skip_newlines(&TokenKind::Star)
250 || self.check_skip_newlines(&TokenKind::Slash)
251 || self.check_skip_newlines(&TokenKind::Percent)
252 {
253 let start = left.span;
254 let op = if self.check(&TokenKind::Star) {
255 "*"
256 } else if self.check(&TokenKind::Slash) {
257 "/"
258 } else {
259 "%"
260 };
261 self.advance();
262 let right = self.parse_exponent()?;
263 left = spanned(
264 Node::BinaryOp {
265 op: op.into(),
266 left: Box::new(left),
267 right: Box::new(right),
268 },
269 Span::merge(start, self.prev_span()),
270 );
271 }
272 Ok(left)
273 }
274
275 pub(super) fn parse_exponent(&mut self) -> Result<SNode, ParserError> {
276 let left = self.parse_unary()?;
277 if !self.check_skip_newlines(&TokenKind::Pow) {
278 return Ok(left);
279 }
280
281 let start = left.span;
282 self.advance();
283 let right = self.parse_exponent()?;
284 Ok(spanned(
285 Node::BinaryOp {
286 op: "**".into(),
287 left: Box::new(left),
288 right: Box::new(right),
289 },
290 Span::merge(start, self.prev_span()),
291 ))
292 }
293
294 pub(super) fn parse_unary(&mut self) -> Result<SNode, ParserError> {
295 if self.check(&TokenKind::Not) {
296 let start = self.current_span();
297 self.advance();
298 let operand = self.parse_unary()?;
299 return Ok(spanned(
300 Node::UnaryOp {
301 op: "!".into(),
302 operand: Box::new(operand),
303 },
304 Span::merge(start, self.prev_span()),
305 ));
306 }
307 if self.check(&TokenKind::Minus) {
308 let start = self.current_span();
309 self.advance();
310 let operand = self.parse_unary()?;
311 return Ok(spanned(
312 Node::UnaryOp {
313 op: "-".into(),
314 operand: Box::new(operand),
315 },
316 Span::merge(start, self.prev_span()),
317 ));
318 }
319 self.parse_postfix()
320 }
321
322 pub(super) fn parse_postfix(&mut self) -> Result<SNode, ParserError> {
323 let mut expr = self.parse_primary()?;
324
325 loop {
326 if self.check_skip_newlines(&TokenKind::Dot)
327 || self.check_skip_newlines(&TokenKind::QuestionDot)
328 {
329 let optional = self.check(&TokenKind::QuestionDot);
330 let start = expr.span;
331 self.advance();
332 let member = self.consume_identifier_or_keyword("member name")?;
333 if self.check(&TokenKind::LParen) {
334 self.advance();
335 let args = self.parse_arg_list()?;
336 self.consume(&TokenKind::RParen, ")")?;
337 if optional {
338 expr = spanned(
339 Node::OptionalMethodCall {
340 object: Box::new(expr),
341 method: member,
342 args,
343 },
344 Span::merge(start, self.prev_span()),
345 );
346 } else {
347 expr = spanned(
348 Node::MethodCall {
349 object: Box::new(expr),
350 method: member,
351 args,
352 },
353 Span::merge(start, self.prev_span()),
354 );
355 }
356 } else if optional {
357 expr = spanned(
358 Node::OptionalPropertyAccess {
359 object: Box::new(expr),
360 property: member,
361 },
362 Span::merge(start, self.prev_span()),
363 );
364 } else {
365 expr = spanned(
366 Node::PropertyAccess {
367 object: Box::new(expr),
368 property: member,
369 },
370 Span::merge(start, self.prev_span()),
371 );
372 }
373 } else if self.check(&TokenKind::LBracket) {
374 let start = expr.span;
375 self.advance();
376
377 if self.check(&TokenKind::Colon) {
380 self.advance();
381 let end_expr = if self.check(&TokenKind::RBracket) {
382 None
383 } else {
384 Some(Box::new(self.parse_expression()?))
385 };
386 self.consume(&TokenKind::RBracket, "]")?;
387 expr = spanned(
388 Node::SliceAccess {
389 object: Box::new(expr),
390 start: None,
391 end: end_expr,
392 },
393 Span::merge(start, self.prev_span()),
394 );
395 } else {
396 let index = self.parse_expression()?;
397 if self.check(&TokenKind::Colon) {
398 self.advance();
399 let end_expr = if self.check(&TokenKind::RBracket) {
400 None
401 } else {
402 Some(Box::new(self.parse_expression()?))
403 };
404 self.consume(&TokenKind::RBracket, "]")?;
405 expr = spanned(
406 Node::SliceAccess {
407 object: Box::new(expr),
408 start: Some(Box::new(index)),
409 end: end_expr,
410 },
411 Span::merge(start, self.prev_span()),
412 );
413 } else {
414 self.consume(&TokenKind::RBracket, "]")?;
415 expr = spanned(
416 Node::SubscriptAccess {
417 object: Box::new(expr),
418 index: Box::new(index),
419 },
420 Span::merge(start, self.prev_span()),
421 );
422 }
423 }
424 } else if self.check(&TokenKind::LBrace)
425 && matches!(&expr.node, Node::Identifier(name) if self.struct_names.contains(name))
426 {
427 let start = expr.span;
428 let struct_name = match expr.node {
429 Node::Identifier(name) => name,
430 _ => unreachable!("checked above"),
431 };
432 self.advance();
433 let dict = self.parse_dict_literal(start)?;
434 let fields = match dict.node {
435 Node::DictLiteral(fields) => fields,
436 _ => unreachable!("dict parser must return a dict literal"),
437 };
438 expr = spanned(
439 Node::StructConstruct {
440 struct_name,
441 fields,
442 },
443 dict.span,
444 );
445 } else if self.check(&TokenKind::LParen) && matches!(expr.node, Node::Identifier(_)) {
446 let start = expr.span;
447 self.advance();
448 let args = self.parse_arg_list()?;
449 self.consume(&TokenKind::RParen, ")")?;
450 if let Node::Identifier(name) = expr.node {
451 expr = spanned(
452 Node::FunctionCall { name, args },
453 Span::merge(start, self.prev_span()),
454 );
455 }
456 } else if self.check(&TokenKind::Question) {
457 let next_pos = self.pos + 1;
460 let is_ternary = self.tokens.get(next_pos).is_some_and(|t| {
461 matches!(
462 t.kind,
463 TokenKind::Identifier(_)
464 | TokenKind::IntLiteral(_)
465 | TokenKind::FloatLiteral(_)
466 | TokenKind::StringLiteral(_)
467 | TokenKind::InterpolatedString(_)
468 | TokenKind::True
469 | TokenKind::False
470 | TokenKind::Nil
471 | TokenKind::LParen
472 | TokenKind::LBracket
473 | TokenKind::LBrace
474 | TokenKind::Not
475 | TokenKind::Minus
476 | TokenKind::Fn
477 )
478 });
479 if is_ternary {
480 break;
481 }
482 let start = expr.span;
483 self.advance();
484 expr = spanned(
485 Node::TryOperator {
486 operand: Box::new(expr),
487 },
488 Span::merge(start, self.prev_span()),
489 );
490 } else {
491 break;
492 }
493 }
494
495 Ok(expr)
496 }
497
498 pub(super) fn parse_primary(&mut self) -> Result<SNode, ParserError> {
499 let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
500 expected: "expression".into(),
501 span: self.prev_span(),
502 })?;
503 let start = self.current_span();
504
505 match &tok.kind {
506 TokenKind::StringLiteral(s) => {
507 let s = s.clone();
508 self.advance();
509 Ok(spanned(
510 Node::StringLiteral(s),
511 Span::merge(start, self.prev_span()),
512 ))
513 }
514 TokenKind::RawStringLiteral(s) => {
515 let s = s.clone();
516 self.advance();
517 Ok(spanned(
518 Node::RawStringLiteral(s),
519 Span::merge(start, self.prev_span()),
520 ))
521 }
522 TokenKind::InterpolatedString(segments) => {
523 let segments = segments.clone();
524 self.advance();
525 Ok(spanned(
526 Node::InterpolatedString(segments),
527 Span::merge(start, self.prev_span()),
528 ))
529 }
530 TokenKind::IntLiteral(n) => {
531 let n = *n;
532 self.advance();
533 Ok(spanned(
534 Node::IntLiteral(n),
535 Span::merge(start, self.prev_span()),
536 ))
537 }
538 TokenKind::FloatLiteral(n) => {
539 let n = *n;
540 self.advance();
541 Ok(spanned(
542 Node::FloatLiteral(n),
543 Span::merge(start, self.prev_span()),
544 ))
545 }
546 TokenKind::True => {
547 self.advance();
548 Ok(spanned(
549 Node::BoolLiteral(true),
550 Span::merge(start, self.prev_span()),
551 ))
552 }
553 TokenKind::False => {
554 self.advance();
555 Ok(spanned(
556 Node::BoolLiteral(false),
557 Span::merge(start, self.prev_span()),
558 ))
559 }
560 TokenKind::Nil => {
561 self.advance();
562 Ok(spanned(
563 Node::NilLiteral,
564 Span::merge(start, self.prev_span()),
565 ))
566 }
567 TokenKind::Identifier(name) => {
568 let name = name.clone();
569 self.advance();
570 Ok(spanned(
571 Node::Identifier(name),
572 Span::merge(start, self.prev_span()),
573 ))
574 }
575 TokenKind::LParen => {
576 self.advance();
577 let expr = self.parse_expression()?;
578 self.consume(&TokenKind::RParen, ")")?;
579 Ok(expr)
580 }
581 TokenKind::LBracket => self.parse_list_literal(),
582 TokenKind::LBrace => self.parse_dict_or_closure(),
583 TokenKind::Parallel => self.parse_parallel(),
584 TokenKind::Retry => self.parse_retry(),
585 TokenKind::If => self.parse_if_else(),
586 TokenKind::Spawn => self.parse_spawn_expr(),
587 TokenKind::DurationLiteral(ms) => {
588 let ms = *ms;
589 self.advance();
590 Ok(spanned(
591 Node::DurationLiteral(ms),
592 Span::merge(start, self.prev_span()),
593 ))
594 }
595 TokenKind::Deadline => self.parse_deadline(),
596 TokenKind::Try => self.parse_try_catch(),
597 TokenKind::Match => self.parse_match(),
598 TokenKind::Fn => self.parse_fn_expr(),
599 TokenKind::Lt
602 if matches!(self.peek_kind(), Some(&TokenKind::Lt))
603 && matches!(self.peek_kind_at(2), Some(TokenKind::Identifier(_))) =>
604 {
605 Err(ParserError::Unexpected {
606 got: "`<<` heredoc-like syntax".to_string(),
607 expected: "an expression — heredocs are only valid \
608 inside LLM tool-call argument JSON; \
609 for multiline strings in source code use \
610 triple-quoted `\"\"\"...\"\"\"`"
611 .to_string(),
612 span: start,
613 })
614 }
615 _ => Err(self.error("expression")),
616 }
617 }
618
619 pub(super) fn parse_fn_expr(&mut self) -> Result<SNode, ParserError> {
622 let start = self.current_span();
623 self.consume(&TokenKind::Fn, "fn")?;
624 self.consume(&TokenKind::LParen, "(")?;
625 let params = self.parse_typed_param_list()?;
626 self.consume(&TokenKind::RParen, ")")?;
627 self.consume(&TokenKind::LBrace, "{")?;
628 let body = self.parse_block()?;
629 self.consume(&TokenKind::RBrace, "}")?;
630 Ok(spanned(
631 Node::Closure {
632 params,
633 body,
634 fn_syntax: true,
635 },
636 Span::merge(start, self.prev_span()),
637 ))
638 }
639
640 pub(super) fn parse_spawn_expr(&mut self) -> Result<SNode, ParserError> {
641 let start = self.current_span();
642 self.consume(&TokenKind::Spawn, "spawn")?;
643 self.consume(&TokenKind::LBrace, "{")?;
644 let body = self.parse_block()?;
645 self.consume(&TokenKind::RBrace, "}")?;
646 Ok(spanned(
647 Node::SpawnExpr { body },
648 Span::merge(start, self.prev_span()),
649 ))
650 }
651
652 pub(super) fn parse_list_literal(&mut self) -> Result<SNode, ParserError> {
653 let start = self.current_span();
654 self.consume(&TokenKind::LBracket, "[")?;
655 let mut elements = Vec::new();
656 self.skip_newlines();
657
658 while !self.is_at_end() && !self.check(&TokenKind::RBracket) {
659 if self.check(&TokenKind::Dot) {
660 let saved_pos = self.pos;
661 self.advance();
662 if self.check(&TokenKind::Dot) {
663 self.advance();
664 self.consume(&TokenKind::Dot, ".")?;
665 let spread_start = self.tokens[saved_pos].span;
666 let expr = self.parse_expression()?;
667 elements.push(spanned(
668 Node::Spread(Box::new(expr)),
669 Span::merge(spread_start, self.prev_span()),
670 ));
671 } else {
672 self.pos = saved_pos;
673 elements.push(self.parse_expression()?);
674 }
675 } else {
676 elements.push(self.parse_expression()?);
677 }
678 self.skip_newlines();
679 if self.check(&TokenKind::Comma) {
680 self.advance();
681 self.skip_newlines();
682 }
683 }
684
685 self.consume(&TokenKind::RBracket, "]")?;
686 Ok(spanned(
687 Node::ListLiteral(elements),
688 Span::merge(start, self.prev_span()),
689 ))
690 }
691
692 pub(super) fn parse_dict_or_closure(&mut self) -> Result<SNode, ParserError> {
693 let start = self.current_span();
694 self.consume(&TokenKind::LBrace, "{")?;
695 self.skip_newlines();
696
697 if self.check(&TokenKind::RBrace) {
698 self.advance();
699 return Ok(spanned(
700 Node::DictLiteral(Vec::new()),
701 Span::merge(start, self.prev_span()),
702 ));
703 }
704
705 let saved = self.pos;
707 if self.is_closure_lookahead() {
708 self.pos = saved;
709 return self.parse_closure_body(start);
710 }
711 self.pos = saved;
712 self.parse_dict_literal(start)
713 }
714
715 pub(super) fn is_closure_lookahead(&mut self) -> bool {
717 let mut depth = 0;
718 while !self.is_at_end() {
719 if let Some(tok) = self.current() {
720 match &tok.kind {
721 TokenKind::Arrow if depth == 0 => return true,
722 TokenKind::LBrace | TokenKind::LParen | TokenKind::LBracket => depth += 1,
723 TokenKind::RBrace if depth == 0 => return false,
724 TokenKind::RBrace => depth -= 1,
725 TokenKind::RParen | TokenKind::RBracket if depth > 0 => depth -= 1,
726 _ => {}
727 }
728 self.advance();
729 } else {
730 return false;
731 }
732 }
733 false
734 }
735
736 pub(super) fn parse_closure_body(&mut self, start: Span) -> Result<SNode, ParserError> {
738 let params = self.parse_typed_param_list_until_arrow()?;
739 self.consume(&TokenKind::Arrow, "->")?;
740 let body = self.parse_block()?;
741 self.consume(&TokenKind::RBrace, "}")?;
742 Ok(spanned(
743 Node::Closure {
744 params,
745 body,
746 fn_syntax: false,
747 },
748 Span::merge(start, self.prev_span()),
749 ))
750 }
751
752 pub(super) fn parse_typed_param_list_until_arrow(
754 &mut self,
755 ) -> Result<Vec<TypedParam>, ParserError> {
756 self.parse_typed_params_until(|tok| tok == &TokenKind::Arrow)
757 }
758
759 pub(super) fn parse_dict_literal(&mut self, start: Span) -> Result<SNode, ParserError> {
760 let entries = self.parse_dict_entries()?;
761 Ok(spanned(
762 Node::DictLiteral(entries),
763 Span::merge(start, self.prev_span()),
764 ))
765 }
766
767 pub(super) fn parse_dict_entries(&mut self) -> Result<Vec<DictEntry>, ParserError> {
768 let mut entries = Vec::new();
769 self.skip_newlines();
770
771 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
772 if self.check(&TokenKind::Dot) {
773 let saved_pos = self.pos;
774 self.advance();
775 if self.check(&TokenKind::Dot) {
776 self.advance();
777 if self.check(&TokenKind::Dot) {
778 self.advance();
779 let spread_start = self.tokens[saved_pos].span;
780 let expr = self.parse_expression()?;
781 entries.push(DictEntry {
782 key: spanned(Node::NilLiteral, spread_start),
783 value: spanned(
784 Node::Spread(Box::new(expr)),
785 Span::merge(spread_start, self.prev_span()),
786 ),
787 });
788 self.skip_newlines();
789 if self.check(&TokenKind::Comma) {
790 self.advance();
791 self.skip_newlines();
792 }
793 continue;
794 }
795 self.pos = saved_pos;
796 } else {
797 self.pos = saved_pos;
798 }
799 }
800 let key = if self.check(&TokenKind::LBracket) {
801 self.advance();
802 let k = self.parse_expression()?;
803 self.consume(&TokenKind::RBracket, "]")?;
804 k
805 } else if matches!(
806 self.current().map(|t| &t.kind),
807 Some(TokenKind::StringLiteral(_))
808 ) {
809 let key_span = self.current_span();
810 let name =
811 if let Some(TokenKind::StringLiteral(s)) = self.current().map(|t| &t.kind) {
812 s.clone()
813 } else {
814 unreachable!()
815 };
816 self.advance();
817 spanned(Node::StringLiteral(name), key_span)
818 } else {
819 let key_span = self.current_span();
820 let name = self.consume_identifier_or_keyword("dict key")?;
821 spanned(Node::StringLiteral(name), key_span)
822 };
823 self.consume(&TokenKind::Colon, ":")?;
824 let value = self.parse_expression()?;
825 entries.push(DictEntry { key, value });
826 self.skip_newlines();
827 if self.check(&TokenKind::Comma) {
828 self.advance();
829 self.skip_newlines();
830 }
831 }
832
833 self.consume(&TokenKind::RBrace, "}")?;
834 Ok(entries)
835 }
836
837 pub(super) fn parse_param_list(&mut self) -> Result<Vec<String>, ParserError> {
839 let mut params = Vec::new();
840 self.skip_newlines();
841
842 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
843 params.push(self.consume_identifier("parameter name")?);
844 if self.check(&TokenKind::Comma) {
845 self.advance();
846 self.skip_newlines();
847 }
848 }
849 Ok(params)
850 }
851
852 pub(super) fn parse_typed_param_list(&mut self) -> Result<Vec<TypedParam>, ParserError> {
854 self.parse_typed_params_until(|tok| tok == &TokenKind::RParen)
855 }
856
857 pub(super) fn parse_typed_params_until(
860 &mut self,
861 is_terminator: impl Fn(&TokenKind) -> bool,
862 ) -> Result<Vec<TypedParam>, ParserError> {
863 let mut params = Vec::new();
864 let mut seen_default = false;
865 self.skip_newlines();
866
867 while !self.is_at_end() {
868 if let Some(tok) = self.current() {
869 if is_terminator(&tok.kind) {
870 break;
871 }
872 } else {
873 break;
874 }
875 let is_rest = if self.check(&TokenKind::Dot) {
876 let p1 = self.pos + 1;
877 let p2 = self.pos + 2;
878 let is_ellipsis = p1 < self.tokens.len()
879 && p2 < self.tokens.len()
880 && self.tokens[p1].kind == TokenKind::Dot
881 && self.tokens[p2].kind == TokenKind::Dot;
882 if is_ellipsis {
883 self.advance();
884 self.advance();
885 self.advance();
886 true
887 } else {
888 false
889 }
890 } else {
891 false
892 };
893 let name = self.consume_identifier("parameter name")?;
894 let type_expr = self.try_parse_type_annotation()?;
895 let default_value = if self.check(&TokenKind::Assign) {
896 self.advance();
897 seen_default = true;
898 Some(Box::new(self.parse_expression()?))
899 } else {
900 if seen_default && !is_rest {
901 return Err(self.error(
902 "Required parameter cannot follow a parameter with a default value",
903 ));
904 }
905 None
906 };
907 if is_rest
908 && !is_terminator(
909 &self
910 .current()
911 .map(|t| t.kind.clone())
912 .unwrap_or(TokenKind::Eof),
913 )
914 {
915 return Err(self.error("Rest parameter must be the last parameter"));
916 }
917 params.push(TypedParam {
918 name,
919 type_expr,
920 default_value,
921 rest: is_rest,
922 });
923 if self.check(&TokenKind::Comma) {
924 self.advance();
925 self.skip_newlines();
926 }
927 }
928 Ok(params)
929 }
930
931 pub(super) fn parse_arg_list(&mut self) -> Result<Vec<SNode>, ParserError> {
932 let mut args = Vec::new();
933 self.skip_newlines();
934
935 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
936 if self.check(&TokenKind::Dot) {
937 let saved_pos = self.pos;
938 self.advance();
939 if self.check(&TokenKind::Dot) {
940 self.advance();
941 self.consume(&TokenKind::Dot, ".")?;
942 let spread_start = self.tokens[saved_pos].span;
943 let expr = self.parse_expression()?;
944 args.push(spanned(
945 Node::Spread(Box::new(expr)),
946 Span::merge(spread_start, self.prev_span()),
947 ));
948 } else {
949 self.pos = saved_pos;
950 args.push(self.parse_expression()?);
951 }
952 } else {
953 args.push(self.parse_expression()?);
954 }
955 self.skip_newlines();
956 if self.check(&TokenKind::Comma) {
957 self.advance();
958 self.skip_newlines();
959 }
960 }
961 Ok(args)
962 }
963}