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