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