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 let struct_name = match &expr.node {
426 Node::Identifier(name) if self.is_struct_construct_lookahead(name) => {
427 Some(name.clone())
428 }
429 _ => None,
430 };
431 let Some(struct_name) = struct_name else {
432 break;
433 };
434 let start = expr.span;
435 self.advance();
436 let dict = self.parse_dict_literal(start)?;
437 let fields = match dict.node {
438 Node::DictLiteral(fields) => fields,
439 _ => unreachable!("dict parser must return a dict literal"),
440 };
441 expr = spanned(
442 Node::StructConstruct {
443 struct_name,
444 fields,
445 },
446 dict.span,
447 );
448 } else if self.check(&TokenKind::LParen) && matches!(expr.node, Node::Identifier(_)) {
449 let start = expr.span;
450 self.advance();
451 let args = self.parse_arg_list()?;
452 self.consume(&TokenKind::RParen, ")")?;
453 if let Node::Identifier(name) = expr.node {
454 expr = spanned(
455 Node::FunctionCall { name, args },
456 Span::merge(start, self.prev_span()),
457 );
458 }
459 } else if self.check(&TokenKind::Question) {
460 let next_pos = self.pos + 1;
463 let is_ternary = self.tokens.get(next_pos).is_some_and(|t| {
464 matches!(
465 t.kind,
466 TokenKind::Identifier(_)
467 | TokenKind::IntLiteral(_)
468 | TokenKind::FloatLiteral(_)
469 | TokenKind::StringLiteral(_)
470 | TokenKind::InterpolatedString(_)
471 | TokenKind::True
472 | TokenKind::False
473 | TokenKind::Nil
474 | TokenKind::LParen
475 | TokenKind::LBracket
476 | TokenKind::LBrace
477 | TokenKind::Not
478 | TokenKind::Minus
479 | TokenKind::Fn
480 )
481 });
482 if is_ternary {
483 break;
484 }
485 let start = expr.span;
486 self.advance();
487 expr = spanned(
488 Node::TryOperator {
489 operand: Box::new(expr),
490 },
491 Span::merge(start, self.prev_span()),
492 );
493 } else {
494 break;
495 }
496 }
497
498 Ok(expr)
499 }
500
501 pub(super) fn parse_primary(&mut self) -> Result<SNode, ParserError> {
502 let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
503 expected: "expression".into(),
504 span: self.prev_span(),
505 })?;
506 let start = self.current_span();
507
508 match &tok.kind {
509 TokenKind::StringLiteral(s) => {
510 let s = s.clone();
511 self.advance();
512 Ok(spanned(
513 Node::StringLiteral(s),
514 Span::merge(start, self.prev_span()),
515 ))
516 }
517 TokenKind::RawStringLiteral(s) => {
518 let s = s.clone();
519 self.advance();
520 Ok(spanned(
521 Node::RawStringLiteral(s),
522 Span::merge(start, self.prev_span()),
523 ))
524 }
525 TokenKind::InterpolatedString(segments) => {
526 let segments = segments.clone();
527 self.advance();
528 Ok(spanned(
529 Node::InterpolatedString(segments),
530 Span::merge(start, self.prev_span()),
531 ))
532 }
533 TokenKind::IntLiteral(n) => {
534 let n = *n;
535 self.advance();
536 Ok(spanned(
537 Node::IntLiteral(n),
538 Span::merge(start, self.prev_span()),
539 ))
540 }
541 TokenKind::FloatLiteral(n) => {
542 let n = *n;
543 self.advance();
544 Ok(spanned(
545 Node::FloatLiteral(n),
546 Span::merge(start, self.prev_span()),
547 ))
548 }
549 TokenKind::True => {
550 self.advance();
551 Ok(spanned(
552 Node::BoolLiteral(true),
553 Span::merge(start, self.prev_span()),
554 ))
555 }
556 TokenKind::False => {
557 self.advance();
558 Ok(spanned(
559 Node::BoolLiteral(false),
560 Span::merge(start, self.prev_span()),
561 ))
562 }
563 TokenKind::Nil => {
564 self.advance();
565 Ok(spanned(
566 Node::NilLiteral,
567 Span::merge(start, self.prev_span()),
568 ))
569 }
570 TokenKind::Identifier(name) => {
571 let name = name.clone();
572 self.advance();
573 Ok(spanned(
574 Node::Identifier(name),
575 Span::merge(start, self.prev_span()),
576 ))
577 }
578 TokenKind::LParen => {
579 self.advance();
580 let expr = self.parse_expression()?;
581 self.consume(&TokenKind::RParen, ")")?;
582 Ok(expr)
583 }
584 TokenKind::LBracket => self.parse_list_literal(),
585 TokenKind::LBrace => self.parse_dict_or_closure(),
586 TokenKind::Parallel => self.parse_parallel(),
587 TokenKind::Retry => self.parse_retry(),
588 TokenKind::If => self.parse_if_else(),
589 TokenKind::Spawn => self.parse_spawn_expr(),
590 TokenKind::DurationLiteral(ms) => {
591 let ms = *ms;
592 self.advance();
593 Ok(spanned(
594 Node::DurationLiteral(ms),
595 Span::merge(start, self.prev_span()),
596 ))
597 }
598 TokenKind::Deadline => self.parse_deadline(),
599 TokenKind::Try => self.parse_try_catch(),
600 TokenKind::Match => self.parse_match(),
601 TokenKind::Fn => self.parse_fn_expr(),
602 TokenKind::Lt
605 if matches!(self.peek_kind(), Some(&TokenKind::Lt))
606 && matches!(self.peek_kind_at(2), Some(TokenKind::Identifier(_))) =>
607 {
608 Err(ParserError::Unexpected {
609 got: "`<<` heredoc-like syntax".to_string(),
610 expected: "an expression — heredocs are only valid \
611 inside LLM tool-call argument JSON; \
612 for multiline strings in source code use \
613 triple-quoted `\"\"\"...\"\"\"`"
614 .to_string(),
615 span: start,
616 })
617 }
618 _ => Err(self.error("expression")),
619 }
620 }
621
622 pub(super) fn parse_fn_expr(&mut self) -> Result<SNode, ParserError> {
625 let start = self.current_span();
626 self.consume(&TokenKind::Fn, "fn")?;
627 self.consume(&TokenKind::LParen, "(")?;
628 let params = self.parse_typed_param_list()?;
629 self.consume(&TokenKind::RParen, ")")?;
630 self.consume(&TokenKind::LBrace, "{")?;
631 let body = self.parse_block()?;
632 self.consume(&TokenKind::RBrace, "}")?;
633 Ok(spanned(
634 Node::Closure {
635 params,
636 body,
637 fn_syntax: true,
638 },
639 Span::merge(start, self.prev_span()),
640 ))
641 }
642
643 pub(super) fn parse_spawn_expr(&mut self) -> Result<SNode, ParserError> {
644 let start = self.current_span();
645 self.consume(&TokenKind::Spawn, "spawn")?;
646 self.consume(&TokenKind::LBrace, "{")?;
647 let body = self.parse_block()?;
648 self.consume(&TokenKind::RBrace, "}")?;
649 Ok(spanned(
650 Node::SpawnExpr { body },
651 Span::merge(start, self.prev_span()),
652 ))
653 }
654
655 pub(super) fn parse_list_literal(&mut self) -> Result<SNode, ParserError> {
656 let start = self.current_span();
657 self.consume(&TokenKind::LBracket, "[")?;
658 let mut elements = Vec::new();
659 self.skip_newlines();
660
661 while !self.is_at_end() && !self.check(&TokenKind::RBracket) {
662 if self.check(&TokenKind::Dot) {
663 let saved_pos = self.pos;
664 self.advance();
665 if self.check(&TokenKind::Dot) {
666 self.advance();
667 self.consume(&TokenKind::Dot, ".")?;
668 let spread_start = self.tokens[saved_pos].span;
669 let expr = self.parse_expression()?;
670 elements.push(spanned(
671 Node::Spread(Box::new(expr)),
672 Span::merge(spread_start, self.prev_span()),
673 ));
674 } else {
675 self.pos = saved_pos;
676 elements.push(self.parse_expression()?);
677 }
678 } else {
679 elements.push(self.parse_expression()?);
680 }
681 self.skip_newlines();
682 if self.check(&TokenKind::Comma) {
683 self.advance();
684 self.skip_newlines();
685 }
686 }
687
688 self.consume(&TokenKind::RBracket, "]")?;
689 Ok(spanned(
690 Node::ListLiteral(elements),
691 Span::merge(start, self.prev_span()),
692 ))
693 }
694
695 pub(super) fn parse_dict_or_closure(&mut self) -> Result<SNode, ParserError> {
696 let start = self.current_span();
697 self.consume(&TokenKind::LBrace, "{")?;
698 self.skip_newlines();
699
700 if self.check(&TokenKind::RBrace) {
701 self.advance();
702 return Ok(spanned(
703 Node::DictLiteral(Vec::new()),
704 Span::merge(start, self.prev_span()),
705 ));
706 }
707
708 let saved = self.pos;
710 if self.is_closure_lookahead() {
711 self.pos = saved;
712 return self.parse_closure_body(start);
713 }
714 self.pos = saved;
715 self.parse_dict_literal(start)
716 }
717
718 pub(super) fn is_struct_construct_lookahead(&self, struct_name: &str) -> bool {
722 if !struct_name
723 .chars()
724 .next()
725 .is_some_and(|ch| ch.is_uppercase())
726 {
727 return false;
728 }
729
730 let mut offset = 1;
731 while matches!(self.peek_kind_at(offset), Some(TokenKind::Newline)) {
732 offset += 1;
733 }
734
735 match self.peek_kind_at(offset) {
736 Some(TokenKind::RBrace) => true,
737 Some(TokenKind::Identifier(_)) | Some(TokenKind::StringLiteral(_)) => {
738 offset += 1;
739 while matches!(self.peek_kind_at(offset), Some(TokenKind::Newline)) {
740 offset += 1;
741 }
742 matches!(self.peek_kind_at(offset), Some(TokenKind::Colon))
743 }
744 _ => false,
745 }
746 }
747
748 pub(super) fn is_closure_lookahead(&mut self) -> bool {
750 let mut depth = 0;
751 while !self.is_at_end() {
752 if let Some(tok) = self.current() {
753 match &tok.kind {
754 TokenKind::Arrow if depth == 0 => return true,
755 TokenKind::LBrace | TokenKind::LParen | TokenKind::LBracket => depth += 1,
756 TokenKind::RBrace if depth == 0 => return false,
757 TokenKind::RBrace => depth -= 1,
758 TokenKind::RParen | TokenKind::RBracket if depth > 0 => depth -= 1,
759 _ => {}
760 }
761 self.advance();
762 } else {
763 return false;
764 }
765 }
766 false
767 }
768
769 pub(super) fn parse_closure_body(&mut self, start: Span) -> Result<SNode, ParserError> {
771 let params = self.parse_typed_param_list_until_arrow()?;
772 self.consume(&TokenKind::Arrow, "->")?;
773 let body = self.parse_block()?;
774 self.consume(&TokenKind::RBrace, "}")?;
775 Ok(spanned(
776 Node::Closure {
777 params,
778 body,
779 fn_syntax: false,
780 },
781 Span::merge(start, self.prev_span()),
782 ))
783 }
784
785 pub(super) fn parse_typed_param_list_until_arrow(
787 &mut self,
788 ) -> Result<Vec<TypedParam>, ParserError> {
789 self.parse_typed_params_until(|tok| tok == &TokenKind::Arrow)
790 }
791
792 pub(super) fn parse_dict_literal(&mut self, start: Span) -> Result<SNode, ParserError> {
793 let entries = self.parse_dict_entries()?;
794 Ok(spanned(
795 Node::DictLiteral(entries),
796 Span::merge(start, self.prev_span()),
797 ))
798 }
799
800 pub(super) fn parse_dict_entries(&mut self) -> Result<Vec<DictEntry>, ParserError> {
801 let mut entries = Vec::new();
802 self.skip_newlines();
803
804 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
805 if self.check(&TokenKind::Dot) {
806 let saved_pos = self.pos;
807 self.advance();
808 if self.check(&TokenKind::Dot) {
809 self.advance();
810 if self.check(&TokenKind::Dot) {
811 self.advance();
812 let spread_start = self.tokens[saved_pos].span;
813 let expr = self.parse_expression()?;
814 entries.push(DictEntry {
815 key: spanned(Node::NilLiteral, spread_start),
816 value: spanned(
817 Node::Spread(Box::new(expr)),
818 Span::merge(spread_start, self.prev_span()),
819 ),
820 });
821 self.skip_newlines();
822 if self.check(&TokenKind::Comma) {
823 self.advance();
824 self.skip_newlines();
825 }
826 continue;
827 }
828 self.pos = saved_pos;
829 } else {
830 self.pos = saved_pos;
831 }
832 }
833 let key = if self.check(&TokenKind::LBracket) {
834 self.advance();
835 let k = self.parse_expression()?;
836 self.consume(&TokenKind::RBracket, "]")?;
837 k
838 } else if matches!(
839 self.current().map(|t| &t.kind),
840 Some(TokenKind::StringLiteral(_))
841 ) {
842 let key_span = self.current_span();
843 let name =
844 if let Some(TokenKind::StringLiteral(s)) = self.current().map(|t| &t.kind) {
845 s.clone()
846 } else {
847 unreachable!()
848 };
849 self.advance();
850 spanned(Node::StringLiteral(name), key_span)
851 } else {
852 let key_span = self.current_span();
853 let name = self.consume_identifier_or_keyword("dict key")?;
854 spanned(Node::StringLiteral(name), key_span)
855 };
856 self.consume(&TokenKind::Colon, ":")?;
857 let value = self.parse_expression()?;
858 entries.push(DictEntry { key, value });
859 self.skip_newlines();
860 if self.check(&TokenKind::Comma) {
861 self.advance();
862 self.skip_newlines();
863 }
864 }
865
866 self.consume(&TokenKind::RBrace, "}")?;
867 Ok(entries)
868 }
869
870 pub(super) fn parse_param_list(&mut self) -> Result<Vec<String>, ParserError> {
872 let mut params = Vec::new();
873 self.skip_newlines();
874
875 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
876 params.push(self.consume_identifier("parameter name")?);
877 if self.check(&TokenKind::Comma) {
878 self.advance();
879 self.skip_newlines();
880 }
881 }
882 Ok(params)
883 }
884
885 pub(super) fn parse_typed_param_list(&mut self) -> Result<Vec<TypedParam>, ParserError> {
887 self.parse_typed_params_until(|tok| tok == &TokenKind::RParen)
888 }
889
890 pub(super) fn parse_typed_params_until(
893 &mut self,
894 is_terminator: impl Fn(&TokenKind) -> bool,
895 ) -> Result<Vec<TypedParam>, ParserError> {
896 let mut params = Vec::new();
897 let mut seen_default = false;
898 self.skip_newlines();
899
900 while !self.is_at_end() {
901 if let Some(tok) = self.current() {
902 if is_terminator(&tok.kind) {
903 break;
904 }
905 } else {
906 break;
907 }
908 let is_rest = if self.check(&TokenKind::Dot) {
909 let p1 = self.pos + 1;
910 let p2 = self.pos + 2;
911 let is_ellipsis = p1 < self.tokens.len()
912 && p2 < self.tokens.len()
913 && self.tokens[p1].kind == TokenKind::Dot
914 && self.tokens[p2].kind == TokenKind::Dot;
915 if is_ellipsis {
916 self.advance();
917 self.advance();
918 self.advance();
919 true
920 } else {
921 false
922 }
923 } else {
924 false
925 };
926 let name = self.consume_identifier("parameter name")?;
927 let type_expr = self.try_parse_type_annotation()?;
928 let default_value = if self.check(&TokenKind::Assign) {
929 self.advance();
930 seen_default = true;
931 Some(Box::new(self.parse_expression()?))
932 } else {
933 if seen_default && !is_rest {
934 return Err(self.error(
935 "Required parameter cannot follow a parameter with a default value",
936 ));
937 }
938 None
939 };
940 if is_rest
941 && !is_terminator(
942 &self
943 .current()
944 .map(|t| t.kind.clone())
945 .unwrap_or(TokenKind::Eof),
946 )
947 {
948 return Err(self.error("Rest parameter must be the last parameter"));
949 }
950 params.push(TypedParam {
951 name,
952 type_expr,
953 default_value,
954 rest: is_rest,
955 });
956 if self.check(&TokenKind::Comma) {
957 self.advance();
958 self.skip_newlines();
959 }
960 }
961 Ok(params)
962 }
963
964 pub(super) fn parse_arg_list(&mut self) -> Result<Vec<SNode>, ParserError> {
965 let mut args = Vec::new();
966 self.skip_newlines();
967
968 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
969 if self.check(&TokenKind::Dot) {
970 let saved_pos = self.pos;
971 self.advance();
972 if self.check(&TokenKind::Dot) {
973 self.advance();
974 self.consume(&TokenKind::Dot, ".")?;
975 let spread_start = self.tokens[saved_pos].span;
976 let expr = self.parse_expression()?;
977 args.push(spanned(
978 Node::Spread(Box::new(expr)),
979 Span::merge(spread_start, self.prev_span()),
980 ));
981 } else {
982 self.pos = saved_pos;
983 args.push(self.parse_expression()?);
984 }
985 } else {
986 args.push(self.parse_expression()?);
987 }
988 self.skip_newlines();
989 if self.check(&TokenKind::Comma) {
990 self.advance();
991 self.skip_newlines();
992 }
993 }
994 Ok(args)
995 }
996}