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