1use crate::ast::*;
2use harn_lexer::{Span, Token, TokenKind};
3use std::collections::HashSet;
4use std::fmt;
5
6#[derive(Debug, Clone, PartialEq)]
8pub enum ParserError {
9 Unexpected {
10 got: String,
11 expected: String,
12 span: Span,
13 },
14 UnexpectedEof {
15 expected: String,
16 span: Span,
17 },
18}
19
20impl fmt::Display for ParserError {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 match self {
23 ParserError::Unexpected {
24 got,
25 expected,
26 span,
27 } => write!(
28 f,
29 "Expected {expected}, got {got} at {}:{}",
30 span.line, span.column
31 ),
32 ParserError::UnexpectedEof { expected, .. } => {
33 write!(f, "Unexpected end of file, expected {expected}")
34 }
35 }
36 }
37}
38
39impl std::error::Error for ParserError {}
40
41pub struct Parser {
43 tokens: Vec<Token>,
44 pos: usize,
45 errors: Vec<ParserError>,
46 struct_names: HashSet<String>,
47}
48
49impl Parser {
50 pub fn new(tokens: Vec<Token>) -> Self {
51 Self {
52 tokens,
53 pos: 0,
54 errors: Vec::new(),
55 struct_names: HashSet::new(),
56 }
57 }
58
59 fn current_span(&self) -> Span {
60 self.tokens
61 .get(self.pos)
62 .map(|t| t.span)
63 .unwrap_or(Span::dummy())
64 }
65
66 fn current_kind(&self) -> Option<&TokenKind> {
67 self.tokens.get(self.pos).map(|t| &t.kind)
68 }
69
70 fn prev_span(&self) -> Span {
71 if self.pos > 0 {
72 self.tokens[self.pos - 1].span
73 } else {
74 Span::dummy()
75 }
76 }
77
78 pub fn parse(&mut self) -> Result<Vec<SNode>, ParserError> {
80 let mut nodes = Vec::new();
81 self.skip_newlines();
82
83 while !self.is_at_end() {
84 if self.check(&TokenKind::RBrace) {
86 self.advance();
87 self.skip_newlines();
88 continue;
89 }
90
91 let result = if self.check(&TokenKind::Import) {
92 self.parse_import()
93 } else if self.check(&TokenKind::Pipeline) {
94 self.parse_pipeline()
95 } else {
96 self.parse_statement()
97 };
98
99 match result {
100 Ok(node) => nodes.push(node),
101 Err(err) => {
102 self.errors.push(err);
103 self.synchronize();
104 }
105 }
106 self.skip_newlines();
107 }
108
109 if let Some(first) = self.errors.first() {
110 return Err(first.clone());
111 }
112 Ok(nodes)
113 }
114
115 pub fn all_errors(&self) -> &[ParserError] {
117 &self.errors
118 }
119
120 fn is_statement_start(&self) -> bool {
122 matches!(
123 self.current_kind(),
124 Some(
125 TokenKind::Let
126 | TokenKind::Var
127 | TokenKind::If
128 | TokenKind::For
129 | TokenKind::While
130 | TokenKind::Match
131 | TokenKind::Retry
132 | TokenKind::Return
133 | TokenKind::Throw
134 | TokenKind::Fn
135 | TokenKind::Pub
136 | TokenKind::Try
137 | TokenKind::Select
138 | TokenKind::Pipeline
139 | TokenKind::Import
140 | TokenKind::Parallel
141 | TokenKind::Enum
142 | TokenKind::Struct
143 | TokenKind::Interface
144 | TokenKind::Guard
145 | TokenKind::Require
146 | TokenKind::Deadline
147 | TokenKind::Yield
148 | TokenKind::Mutex
149 | TokenKind::Tool
150 )
151 )
152 }
153
154 fn synchronize(&mut self) {
156 while !self.is_at_end() {
157 if self.check(&TokenKind::Newline) {
158 self.advance();
159 if self.is_at_end() || self.is_statement_start() {
160 return;
161 }
162 continue;
163 }
164 if self.check(&TokenKind::RBrace) {
165 return;
166 }
167 self.advance();
168 }
169 }
170
171 pub fn parse_single_expression(&mut self) -> Result<SNode, ParserError> {
173 self.skip_newlines();
174 self.parse_expression()
175 }
176
177 fn parse_pipeline_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
178 let start = self.current_span();
179 self.consume(&TokenKind::Pipeline, "pipeline")?;
180 let name = self.consume_identifier("pipeline name")?;
181
182 self.consume(&TokenKind::LParen, "(")?;
183 let params = self.parse_param_list()?;
184 self.consume(&TokenKind::RParen, ")")?;
185
186 let extends = if self.check(&TokenKind::Extends) {
187 self.advance();
188 Some(self.consume_identifier("parent pipeline name")?)
189 } else {
190 None
191 };
192
193 self.consume(&TokenKind::LBrace, "{")?;
194 let body = self.parse_block()?;
195 self.consume(&TokenKind::RBrace, "}")?;
196
197 Ok(spanned(
198 Node::Pipeline {
199 name,
200 params,
201 body,
202 extends,
203 is_pub,
204 },
205 Span::merge(start, self.prev_span()),
206 ))
207 }
208
209 fn parse_pipeline(&mut self) -> Result<SNode, ParserError> {
210 self.parse_pipeline_with_pub(false)
211 }
212
213 fn parse_import(&mut self) -> Result<SNode, ParserError> {
214 let start = self.current_span();
215 self.consume(&TokenKind::Import, "import")?;
216
217 if self.check(&TokenKind::LBrace) {
219 self.advance();
220 self.skip_newlines();
221 let mut names = Vec::new();
222 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
223 let name = self.consume_identifier("import name")?;
224 names.push(name);
225 self.skip_newlines();
226 if self.check(&TokenKind::Comma) {
227 self.advance();
228 self.skip_newlines();
229 }
230 }
231 self.consume(&TokenKind::RBrace, "}")?;
232 self.consume(&TokenKind::From, "from")?;
233 if let Some(tok) = self.current() {
234 if let TokenKind::StringLiteral(path) = &tok.kind {
235 let path = path.clone();
236 self.advance();
237 return Ok(spanned(
238 Node::SelectiveImport { names, path },
239 Span::merge(start, self.prev_span()),
240 ));
241 }
242 }
243 return Err(self.error("import path string"));
244 }
245
246 if let Some(tok) = self.current() {
247 if let TokenKind::StringLiteral(path) = &tok.kind {
248 let path = path.clone();
249 self.advance();
250 return Ok(spanned(
251 Node::ImportDecl { path },
252 Span::merge(start, self.prev_span()),
253 ));
254 }
255 }
256 Err(self.error("import path string"))
257 }
258
259 fn parse_block(&mut self) -> Result<Vec<SNode>, ParserError> {
260 let mut stmts = Vec::new();
261 self.skip_newlines();
262
263 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
264 stmts.push(self.parse_statement()?);
265 self.skip_newlines();
266 }
267 Ok(stmts)
268 }
269
270 fn parse_statement(&mut self) -> Result<SNode, ParserError> {
271 self.skip_newlines();
272
273 let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
274 expected: "statement".into(),
275 span: self.prev_span(),
276 })?;
277
278 match &tok.kind {
279 TokenKind::Let => self.parse_let_binding(),
280 TokenKind::Var => self.parse_var_binding(),
281 TokenKind::If => self.parse_if_else(),
282 TokenKind::For => self.parse_for_in(),
283 TokenKind::Match => self.parse_match(),
284 TokenKind::Retry => self.parse_retry(),
285 TokenKind::While => self.parse_while_loop(),
286 TokenKind::Parallel => self.parse_parallel(),
287 TokenKind::Return => self.parse_return(),
288 TokenKind::Throw => self.parse_throw(),
289 TokenKind::Override => self.parse_override(),
290 TokenKind::Try => self.parse_try_catch(),
291 TokenKind::Select => self.parse_select(),
292 TokenKind::Fn => self.parse_fn_decl_with_pub(false),
293 TokenKind::Tool => self.parse_tool_decl(false),
294 TokenKind::Pub => {
295 self.advance(); let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
297 expected: "fn, struct, enum, or pipeline after pub".into(),
298 span: self.prev_span(),
299 })?;
300 match &tok.kind {
301 TokenKind::Fn => self.parse_fn_decl_with_pub(true),
302 TokenKind::Tool => self.parse_tool_decl(true),
303 TokenKind::Pipeline => self.parse_pipeline_with_pub(true),
304 TokenKind::Enum => self.parse_enum_decl_with_pub(true),
305 TokenKind::Struct => self.parse_struct_decl_with_pub(true),
306 _ => Err(self.error("fn, tool, struct, enum, or pipeline after pub")),
307 }
308 }
309 TokenKind::TypeKw => self.parse_type_decl(),
310 TokenKind::Enum => self.parse_enum_decl(),
311 TokenKind::Struct => self.parse_struct_decl(),
312 TokenKind::Interface => self.parse_interface_decl(),
313 TokenKind::Impl => self.parse_impl_block(),
314 TokenKind::Guard => self.parse_guard(),
315 TokenKind::Require => self.parse_require(),
316 TokenKind::Deadline => self.parse_deadline(),
317 TokenKind::Yield => self.parse_yield(),
318 TokenKind::Mutex => self.parse_mutex(),
319 TokenKind::Defer => self.parse_defer(),
320 TokenKind::Break => {
321 let span = self.current_span();
322 self.advance();
323 Ok(spanned(Node::BreakStmt, span))
324 }
325 TokenKind::Continue => {
326 let span = self.current_span();
327 self.advance();
328 Ok(spanned(Node::ContinueStmt, span))
329 }
330 _ => self.parse_expression_statement(),
331 }
332 }
333
334 fn parse_let_binding(&mut self) -> Result<SNode, ParserError> {
335 let start = self.current_span();
336 self.consume(&TokenKind::Let, "let")?;
337 let pattern = self.parse_binding_pattern()?;
338 let type_ann = if matches!(pattern, BindingPattern::Identifier(_)) {
339 self.try_parse_type_annotation()?
340 } else {
341 None
342 };
343 self.consume(&TokenKind::Assign, "=")?;
344 let value = self.parse_expression()?;
345 Ok(spanned(
346 Node::LetBinding {
347 pattern,
348 type_ann,
349 value: Box::new(value),
350 },
351 Span::merge(start, self.prev_span()),
352 ))
353 }
354
355 fn parse_var_binding(&mut self) -> Result<SNode, ParserError> {
356 let start = self.current_span();
357 self.consume(&TokenKind::Var, "var")?;
358 let pattern = self.parse_binding_pattern()?;
359 let type_ann = if matches!(pattern, BindingPattern::Identifier(_)) {
360 self.try_parse_type_annotation()?
361 } else {
362 None
363 };
364 self.consume(&TokenKind::Assign, "=")?;
365 let value = self.parse_expression()?;
366 Ok(spanned(
367 Node::VarBinding {
368 pattern,
369 type_ann,
370 value: Box::new(value),
371 },
372 Span::merge(start, self.prev_span()),
373 ))
374 }
375
376 fn parse_if_else(&mut self) -> Result<SNode, ParserError> {
377 let start = self.current_span();
378 self.consume(&TokenKind::If, "if")?;
379 let condition = self.parse_expression()?;
380 self.consume(&TokenKind::LBrace, "{")?;
381 let then_body = self.parse_block()?;
382 self.consume(&TokenKind::RBrace, "}")?;
383 self.skip_newlines();
384
385 let else_body = if self.check(&TokenKind::Else) {
386 self.advance();
387 if self.check(&TokenKind::If) {
388 Some(vec![self.parse_if_else()?])
389 } else {
390 self.consume(&TokenKind::LBrace, "{")?;
391 let body = self.parse_block()?;
392 self.consume(&TokenKind::RBrace, "}")?;
393 Some(body)
394 }
395 } else {
396 None
397 };
398
399 Ok(spanned(
400 Node::IfElse {
401 condition: Box::new(condition),
402 then_body,
403 else_body,
404 },
405 Span::merge(start, self.prev_span()),
406 ))
407 }
408
409 fn parse_for_in(&mut self) -> Result<SNode, ParserError> {
410 let start = self.current_span();
411 self.consume(&TokenKind::For, "for")?;
412 let pattern = if self.check(&TokenKind::LParen) {
413 self.advance();
415 let first = self.consume_identifier("pair pattern element")?;
416 self.consume(&TokenKind::Comma, ",")?;
417 let second = self.consume_identifier("pair pattern element")?;
418 self.consume(&TokenKind::RParen, ")")?;
419 BindingPattern::Pair(first, second)
420 } else {
421 self.parse_binding_pattern()?
422 };
423 self.consume(&TokenKind::In, "in")?;
424 let iterable = self.parse_expression()?;
425 self.consume(&TokenKind::LBrace, "{")?;
426 let body = self.parse_block()?;
427 self.consume(&TokenKind::RBrace, "}")?;
428 Ok(spanned(
429 Node::ForIn {
430 pattern,
431 iterable: Box::new(iterable),
432 body,
433 },
434 Span::merge(start, self.prev_span()),
435 ))
436 }
437
438 fn parse_binding_pattern(&mut self) -> Result<BindingPattern, ParserError> {
441 self.skip_newlines();
442 if self.check(&TokenKind::LBrace) {
443 self.advance();
444 let mut fields = Vec::new();
445 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
446 if self.check(&TokenKind::Dot) {
447 self.advance();
448 self.consume(&TokenKind::Dot, ".")?;
449 self.consume(&TokenKind::Dot, ".")?;
450 let name = self.consume_identifier("rest variable name")?;
451 fields.push(DictPatternField {
452 key: name,
453 alias: None,
454 is_rest: true,
455 default_value: None,
456 });
457 break;
459 }
460 let key = self.consume_identifier("field name")?;
461 let alias = if self.check(&TokenKind::Colon) {
462 self.advance();
463 Some(self.consume_identifier("alias name")?)
464 } else {
465 None
466 };
467 let default_value = if self.check(&TokenKind::Assign) {
468 self.advance();
469 Some(Box::new(self.parse_expression()?))
470 } else {
471 None
472 };
473 fields.push(DictPatternField {
474 key,
475 alias,
476 is_rest: false,
477 default_value,
478 });
479 if self.check(&TokenKind::Comma) {
480 self.advance();
481 }
482 }
483 self.consume(&TokenKind::RBrace, "}")?;
484 Ok(BindingPattern::Dict(fields))
485 } else if self.check(&TokenKind::LBracket) {
486 self.advance();
487 let mut elements = Vec::new();
488 while !self.is_at_end() && !self.check(&TokenKind::RBracket) {
489 if self.check(&TokenKind::Dot) {
490 self.advance();
491 self.consume(&TokenKind::Dot, ".")?;
492 self.consume(&TokenKind::Dot, ".")?;
493 let name = self.consume_identifier("rest variable name")?;
494 elements.push(ListPatternElement {
495 name,
496 is_rest: true,
497 default_value: None,
498 });
499 break;
500 }
501 let name = self.consume_identifier("element name")?;
502 let default_value = if self.check(&TokenKind::Assign) {
503 self.advance();
504 Some(Box::new(self.parse_expression()?))
505 } else {
506 None
507 };
508 elements.push(ListPatternElement {
509 name,
510 is_rest: false,
511 default_value,
512 });
513 if self.check(&TokenKind::Comma) {
514 self.advance();
515 }
516 }
517 self.consume(&TokenKind::RBracket, "]")?;
518 Ok(BindingPattern::List(elements))
519 } else {
520 let name = self.consume_identifier("variable name or destructuring pattern")?;
521 Ok(BindingPattern::Identifier(name))
522 }
523 }
524
525 fn parse_match(&mut self) -> Result<SNode, ParserError> {
526 let start = self.current_span();
527 self.consume(&TokenKind::Match, "match")?;
528 let value = self.parse_expression()?;
529 self.consume(&TokenKind::LBrace, "{")?;
530 self.skip_newlines();
531
532 let mut arms = Vec::new();
533 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
534 let pattern = self.parse_expression()?;
535 let guard = if self.check(&TokenKind::If) {
536 self.advance();
537 Some(Box::new(self.parse_expression()?))
538 } else {
539 None
540 };
541 self.consume(&TokenKind::Arrow, "->")?;
542 self.consume(&TokenKind::LBrace, "{")?;
543 let body = self.parse_block()?;
544 self.consume(&TokenKind::RBrace, "}")?;
545 arms.push(MatchArm {
546 pattern,
547 guard,
548 body,
549 });
550 self.skip_newlines();
551 }
552
553 self.consume(&TokenKind::RBrace, "}")?;
554 Ok(spanned(
555 Node::MatchExpr {
556 value: Box::new(value),
557 arms,
558 },
559 Span::merge(start, self.prev_span()),
560 ))
561 }
562
563 fn parse_while_loop(&mut self) -> Result<SNode, ParserError> {
564 let start = self.current_span();
565 self.consume(&TokenKind::While, "while")?;
566 let condition = if self.check(&TokenKind::LParen) {
567 self.advance();
568 let c = self.parse_expression()?;
569 self.consume(&TokenKind::RParen, ")")?;
570 c
571 } else {
572 self.parse_expression()?
573 };
574 self.consume(&TokenKind::LBrace, "{")?;
575 let body = self.parse_block()?;
576 self.consume(&TokenKind::RBrace, "}")?;
577 Ok(spanned(
578 Node::WhileLoop {
579 condition: Box::new(condition),
580 body,
581 },
582 Span::merge(start, self.prev_span()),
583 ))
584 }
585
586 fn parse_retry(&mut self) -> Result<SNode, ParserError> {
587 let start = self.current_span();
588 self.consume(&TokenKind::Retry, "retry")?;
589 let count = if self.check(&TokenKind::LParen) {
590 self.advance();
591 let c = self.parse_expression()?;
592 self.consume(&TokenKind::RParen, ")")?;
593 c
594 } else {
595 self.parse_primary()?
596 };
597 self.consume(&TokenKind::LBrace, "{")?;
598 let body = self.parse_block()?;
599 self.consume(&TokenKind::RBrace, "}")?;
600 Ok(spanned(
601 Node::Retry {
602 count: Box::new(count),
603 body,
604 },
605 Span::merge(start, self.prev_span()),
606 ))
607 }
608
609 fn parse_parallel(&mut self) -> Result<SNode, ParserError> {
610 let start = self.current_span();
611 self.consume(&TokenKind::Parallel, "parallel")?;
612
613 let mode = if self.check_identifier("each") {
614 self.advance();
615 ParallelMode::Each
616 } else if self.check_identifier("settle") {
617 self.advance();
618 ParallelMode::Settle
619 } else {
620 ParallelMode::Count
621 };
622
623 let expr = self.parse_expression()?;
624
625 let options = if self.check_identifier("with") {
628 self.advance();
629 self.consume(&TokenKind::LBrace, "{")?;
630 let mut options = Vec::new();
631 loop {
632 self.skip_newlines();
633 if matches!(
634 self.current().map(|t| &t.kind),
635 Some(&TokenKind::RBrace) | None
636 ) {
637 break;
638 }
639 let key_span = self.current_span();
640 let key = match self.current().map(|t| &t.kind) {
641 Some(TokenKind::Identifier(name)) => name.clone(),
642 _ => {
643 return Err(ParserError::Unexpected {
644 got: self
645 .current()
646 .map(|t| format!("{:?}", t.kind))
647 .unwrap_or_else(|| "end of input".to_string()),
648 expected: "option name in `parallel ... with { ... }` block"
649 .to_string(),
650 span: key_span,
651 });
652 }
653 };
654 self.advance();
655 if key != "max_concurrent" {
656 return Err(ParserError::Unexpected {
657 got: key.clone(),
658 expected: format!(
659 "known option (only `max_concurrent` is supported in \
660 `parallel ... with {{ ... }}`; got `{key}`)"
661 ),
662 span: key_span,
663 });
664 }
665 self.consume(&TokenKind::Colon, ":")?;
666 let value = self.parse_expression()?;
667 options.push((key, value));
668 self.skip_newlines();
669 if matches!(self.current().map(|t| &t.kind), Some(&TokenKind::Comma)) {
670 self.advance();
671 self.skip_newlines();
672 }
673 }
674 self.consume(&TokenKind::RBrace, "}")?;
675 options
676 } else {
677 Vec::new()
678 };
679
680 self.consume(&TokenKind::LBrace, "{")?;
681
682 let mut variable = None;
683 self.skip_newlines();
684 if let Some(tok) = self.current() {
685 if let TokenKind::Identifier(name) = &tok.kind {
686 if self.peek_kind() == Some(&TokenKind::Arrow) {
687 let name = name.clone();
688 self.advance();
689 self.advance();
690 variable = Some(name);
691 }
692 }
693 }
694
695 let body = self.parse_block()?;
696 self.consume(&TokenKind::RBrace, "}")?;
697 Ok(spanned(
698 Node::Parallel {
699 mode,
700 expr: Box::new(expr),
701 variable,
702 body,
703 options,
704 },
705 Span::merge(start, self.prev_span()),
706 ))
707 }
708
709 fn parse_return(&mut self) -> Result<SNode, ParserError> {
710 let start = self.current_span();
711 self.consume(&TokenKind::Return, "return")?;
712 if self.is_at_end() || self.check(&TokenKind::Newline) || self.check(&TokenKind::RBrace) {
713 return Ok(spanned(
714 Node::ReturnStmt { value: None },
715 Span::merge(start, self.prev_span()),
716 ));
717 }
718 let value = self.parse_expression()?;
719 Ok(spanned(
720 Node::ReturnStmt {
721 value: Some(Box::new(value)),
722 },
723 Span::merge(start, self.prev_span()),
724 ))
725 }
726
727 fn parse_throw(&mut self) -> Result<SNode, ParserError> {
728 let start = self.current_span();
729 self.consume(&TokenKind::Throw, "throw")?;
730 let value = self.parse_expression()?;
731 Ok(spanned(
732 Node::ThrowStmt {
733 value: Box::new(value),
734 },
735 Span::merge(start, self.prev_span()),
736 ))
737 }
738
739 fn parse_override(&mut self) -> Result<SNode, ParserError> {
740 let start = self.current_span();
741 self.consume(&TokenKind::Override, "override")?;
742 let name = self.consume_identifier("override name")?;
743 self.consume(&TokenKind::LParen, "(")?;
744 let params = self.parse_param_list()?;
745 self.consume(&TokenKind::RParen, ")")?;
746 self.consume(&TokenKind::LBrace, "{")?;
747 let body = self.parse_block()?;
748 self.consume(&TokenKind::RBrace, "}")?;
749 Ok(spanned(
750 Node::OverrideDecl { name, params, body },
751 Span::merge(start, self.prev_span()),
752 ))
753 }
754
755 fn parse_try_catch(&mut self) -> Result<SNode, ParserError> {
756 let start = self.current_span();
757 self.consume(&TokenKind::Try, "try")?;
758 if self.check(&TokenKind::Star) {
759 self.advance();
760 let operand = self.parse_unary()?;
761 return Ok(spanned(
762 Node::TryStar {
763 operand: Box::new(operand),
764 },
765 Span::merge(start, self.prev_span()),
766 ));
767 }
768 self.consume(&TokenKind::LBrace, "{")?;
769 let body = self.parse_block()?;
770 self.consume(&TokenKind::RBrace, "}")?;
771 self.skip_newlines();
772
773 let has_catch = self.check(&TokenKind::Catch);
774 let (error_var, error_type, catch_body) = if has_catch {
775 self.advance();
776 let (ev, et) = if self.check(&TokenKind::LParen) {
777 self.advance();
778 let name = self.consume_identifier("error variable")?;
779 let ty = self.try_parse_type_annotation()?;
780 self.consume(&TokenKind::RParen, ")")?;
781 (Some(name), ty)
782 } else if matches!(
783 self.current().map(|t| &t.kind),
784 Some(TokenKind::Identifier(_))
785 ) {
786 let name = self.consume_identifier("error variable")?;
787 (Some(name), None)
788 } else {
789 (None, None)
790 };
791 self.consume(&TokenKind::LBrace, "{")?;
792 let cb = self.parse_block()?;
793 self.consume(&TokenKind::RBrace, "}")?;
794 (ev, et, cb)
795 } else {
796 (None, None, Vec::new())
797 };
798
799 self.skip_newlines();
800
801 let finally_body = if self.check(&TokenKind::Finally) {
802 self.advance();
803 self.consume(&TokenKind::LBrace, "{")?;
804 let fb = self.parse_block()?;
805 self.consume(&TokenKind::RBrace, "}")?;
806 Some(fb)
807 } else {
808 None
809 };
810
811 if !has_catch && finally_body.is_none() {
813 return Ok(spanned(
814 Node::TryExpr { body },
815 Span::merge(start, self.prev_span()),
816 ));
817 }
818
819 Ok(spanned(
820 Node::TryCatch {
821 body,
822 error_var,
823 error_type,
824 catch_body,
825 finally_body,
826 },
827 Span::merge(start, self.prev_span()),
828 ))
829 }
830
831 fn parse_select(&mut self) -> Result<SNode, ParserError> {
832 let start = self.current_span();
833 self.consume(&TokenKind::Select, "select")?;
834 self.consume(&TokenKind::LBrace, "{")?;
835 self.skip_newlines();
836
837 let mut cases = Vec::new();
838 let mut timeout = None;
839 let mut default_body = None;
840
841 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
842 self.skip_newlines();
843 if let Some(tok) = self.current() {
845 if let TokenKind::Identifier(ref id) = tok.kind {
846 if id == "timeout" {
847 self.advance();
848 let duration = self.parse_expression()?;
849 self.consume(&TokenKind::LBrace, "{")?;
850 let body = self.parse_block()?;
851 self.consume(&TokenKind::RBrace, "}")?;
852 timeout = Some((Box::new(duration), body));
853 self.skip_newlines();
854 continue;
855 }
856 if id == "default" {
857 self.advance();
858 self.consume(&TokenKind::LBrace, "{")?;
859 let body = self.parse_block()?;
860 self.consume(&TokenKind::RBrace, "}")?;
861 default_body = Some(body);
862 self.skip_newlines();
863 continue;
864 }
865 }
866 }
867 let variable = self.consume_identifier("select case variable")?;
868 self.consume(&TokenKind::From, "from")?;
869 let channel = self.parse_expression()?;
870 self.consume(&TokenKind::LBrace, "{")?;
871 let body = self.parse_block()?;
872 self.consume(&TokenKind::RBrace, "}")?;
873 cases.push(SelectCase {
874 variable,
875 channel: Box::new(channel),
876 body,
877 });
878 self.skip_newlines();
879 }
880
881 self.consume(&TokenKind::RBrace, "}")?;
882
883 if cases.is_empty() && timeout.is_none() && default_body.is_none() {
884 return Err(self.error("at least one select case"));
885 }
886 if timeout.is_some() && default_body.is_some() {
887 return Err(self.error("select cannot have both timeout and default"));
888 }
889
890 Ok(spanned(
891 Node::SelectExpr {
892 cases,
893 timeout,
894 default_body,
895 },
896 Span::merge(start, self.prev_span()),
897 ))
898 }
899
900 fn parse_fn_decl_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
901 let start = self.current_span();
902 self.consume(&TokenKind::Fn, "fn")?;
903 let name = self.consume_identifier("function name")?;
904
905 let type_params = if self.check(&TokenKind::Lt) {
906 self.advance();
907 self.parse_type_param_list()?
908 } else {
909 Vec::new()
910 };
911
912 self.consume(&TokenKind::LParen, "(")?;
913 let params = self.parse_typed_param_list()?;
914 self.consume(&TokenKind::RParen, ")")?;
915 let return_type = if self.check(&TokenKind::Arrow) {
916 self.advance();
917 Some(self.parse_type_expr()?)
918 } else {
919 None
920 };
921
922 let where_clauses = self.parse_where_clauses()?;
923
924 self.consume(&TokenKind::LBrace, "{")?;
925 let body = self.parse_block()?;
926 self.consume(&TokenKind::RBrace, "}")?;
927 Ok(spanned(
928 Node::FnDecl {
929 name,
930 type_params,
931 params,
932 return_type,
933 where_clauses,
934 body,
935 is_pub,
936 },
937 Span::merge(start, self.prev_span()),
938 ))
939 }
940
941 fn parse_tool_decl(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
942 let start = self.current_span();
943 self.consume(&TokenKind::Tool, "tool")?;
944 let name = self.consume_identifier("tool name")?;
945
946 self.consume(&TokenKind::LParen, "(")?;
947 let params = self.parse_typed_param_list()?;
948 self.consume(&TokenKind::RParen, ")")?;
949
950 let return_type = if self.check(&TokenKind::Arrow) {
951 self.advance();
952 Some(self.parse_type_expr()?)
953 } else {
954 None
955 };
956
957 self.consume(&TokenKind::LBrace, "{")?;
958
959 self.skip_newlines();
961 let mut description = None;
962 if let Some(TokenKind::Identifier(id)) = self.current_kind().cloned() {
963 if id == "description" {
964 let saved_pos = self.pos;
965 self.advance();
966 self.skip_newlines();
967 if let Some(TokenKind::StringLiteral(s)) = self.current_kind().cloned() {
968 description = Some(s);
969 self.advance();
970 } else {
971 self.pos = saved_pos;
972 }
973 }
974 }
975
976 let body = self.parse_block()?;
977 self.consume(&TokenKind::RBrace, "}")?;
978
979 Ok(spanned(
980 Node::ToolDecl {
981 name,
982 description,
983 params,
984 return_type,
985 body,
986 is_pub,
987 },
988 Span::merge(start, self.prev_span()),
989 ))
990 }
991
992 fn parse_type_decl(&mut self) -> Result<SNode, ParserError> {
993 let start = self.current_span();
994 self.consume(&TokenKind::TypeKw, "type")?;
995 let name = self.consume_identifier("type name")?;
996 let type_params = if self.check(&TokenKind::Lt) {
997 self.advance();
998 self.parse_type_param_list()?
999 } else {
1000 Vec::new()
1001 };
1002 self.consume(&TokenKind::Assign, "=")?;
1003 let type_expr = self.parse_type_expr()?;
1004 Ok(spanned(
1005 Node::TypeDecl {
1006 name,
1007 type_params,
1008 type_expr,
1009 },
1010 Span::merge(start, self.prev_span()),
1011 ))
1012 }
1013
1014 fn parse_enum_decl_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
1015 let start = self.current_span();
1016 self.consume(&TokenKind::Enum, "enum")?;
1017 let name = self.consume_identifier("enum name")?;
1018 let type_params = if self.check(&TokenKind::Lt) {
1019 self.advance();
1020 self.parse_type_param_list()?
1021 } else {
1022 Vec::new()
1023 };
1024 self.consume(&TokenKind::LBrace, "{")?;
1025 self.skip_newlines();
1026
1027 let mut variants = Vec::new();
1028 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1029 let variant_name = self.consume_identifier("variant name")?;
1030 let fields = if self.check(&TokenKind::LParen) {
1031 self.advance();
1032 let params = self.parse_typed_param_list()?;
1033 self.consume(&TokenKind::RParen, ")")?;
1034 params
1035 } else {
1036 Vec::new()
1037 };
1038 variants.push(EnumVariant {
1039 name: variant_name,
1040 fields,
1041 });
1042 self.skip_newlines();
1043 if self.check(&TokenKind::Comma) {
1044 self.advance();
1045 self.skip_newlines();
1046 }
1047 }
1048
1049 self.consume(&TokenKind::RBrace, "}")?;
1050 Ok(spanned(
1051 Node::EnumDecl {
1052 name,
1053 type_params,
1054 variants,
1055 is_pub,
1056 },
1057 Span::merge(start, self.prev_span()),
1058 ))
1059 }
1060
1061 fn parse_enum_decl(&mut self) -> Result<SNode, ParserError> {
1062 self.parse_enum_decl_with_pub(false)
1063 }
1064
1065 fn parse_struct_decl_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
1066 let start = self.current_span();
1067 self.consume(&TokenKind::Struct, "struct")?;
1068 let name = self.consume_identifier("struct name")?;
1069 self.struct_names.insert(name.clone());
1070 let type_params = if self.check(&TokenKind::Lt) {
1071 self.advance();
1072 self.parse_type_param_list()?
1073 } else {
1074 Vec::new()
1075 };
1076 self.consume(&TokenKind::LBrace, "{")?;
1077 self.skip_newlines();
1078
1079 let mut fields = Vec::new();
1080 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1081 let field_name = self.consume_identifier("field name")?;
1082 let optional = if self.check(&TokenKind::Question) {
1083 self.advance();
1084 true
1085 } else {
1086 false
1087 };
1088 let type_expr = self.try_parse_type_annotation()?;
1089 fields.push(StructField {
1090 name: field_name,
1091 type_expr,
1092 optional,
1093 });
1094 self.skip_newlines();
1095 if self.check(&TokenKind::Comma) {
1096 self.advance();
1097 self.skip_newlines();
1098 }
1099 }
1100
1101 self.consume(&TokenKind::RBrace, "}")?;
1102 Ok(spanned(
1103 Node::StructDecl {
1104 name,
1105 type_params,
1106 fields,
1107 is_pub,
1108 },
1109 Span::merge(start, self.prev_span()),
1110 ))
1111 }
1112
1113 fn parse_struct_decl(&mut self) -> Result<SNode, ParserError> {
1114 self.parse_struct_decl_with_pub(false)
1115 }
1116
1117 fn parse_interface_decl(&mut self) -> Result<SNode, ParserError> {
1118 let start = self.current_span();
1119 self.consume(&TokenKind::Interface, "interface")?;
1120 let name = self.consume_identifier("interface name")?;
1121 let type_params = if self.check(&TokenKind::Lt) {
1122 self.advance();
1123 self.parse_type_param_list()?
1124 } else {
1125 Vec::new()
1126 };
1127 self.consume(&TokenKind::LBrace, "{")?;
1128 self.skip_newlines();
1129
1130 let mut associated_types = Vec::new();
1131 let mut methods = Vec::new();
1132 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1133 if self.check(&TokenKind::TypeKw) {
1134 self.advance();
1135 let assoc_name = self.consume_identifier("associated type name")?;
1136 let assoc_type = if self.check(&TokenKind::Assign) {
1137 self.advance();
1138 Some(self.parse_type_expr()?)
1139 } else {
1140 None
1141 };
1142 associated_types.push((assoc_name, assoc_type));
1143 } else {
1144 self.consume(&TokenKind::Fn, "fn")?;
1145 let method_name = self.consume_identifier("method name")?;
1146 let method_type_params = if self.check(&TokenKind::Lt) {
1147 self.advance();
1148 self.parse_type_param_list()?
1149 } else {
1150 Vec::new()
1151 };
1152 self.consume(&TokenKind::LParen, "(")?;
1153 let params = self.parse_typed_param_list()?;
1154 self.consume(&TokenKind::RParen, ")")?;
1155 let return_type = if self.check(&TokenKind::Arrow) {
1156 self.advance();
1157 Some(self.parse_type_expr()?)
1158 } else {
1159 None
1160 };
1161 methods.push(InterfaceMethod {
1162 name: method_name,
1163 type_params: method_type_params,
1164 params,
1165 return_type,
1166 });
1167 }
1168 self.skip_newlines();
1169 }
1170
1171 self.consume(&TokenKind::RBrace, "}")?;
1172 Ok(spanned(
1173 Node::InterfaceDecl {
1174 name,
1175 type_params,
1176 associated_types,
1177 methods,
1178 },
1179 Span::merge(start, self.prev_span()),
1180 ))
1181 }
1182
1183 fn parse_impl_block(&mut self) -> Result<SNode, ParserError> {
1184 let start = self.current_span();
1185 self.consume(&TokenKind::Impl, "impl")?;
1186 let type_name = self.consume_identifier("type name")?;
1187 self.consume(&TokenKind::LBrace, "{")?;
1188 self.skip_newlines();
1189
1190 let mut methods = Vec::new();
1191 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1192 let is_pub = self.check(&TokenKind::Pub);
1193 if is_pub {
1194 self.advance();
1195 }
1196 let method = self.parse_fn_decl_with_pub(is_pub)?;
1197 methods.push(method);
1198 self.skip_newlines();
1199 }
1200
1201 self.consume(&TokenKind::RBrace, "}")?;
1202 Ok(spanned(
1203 Node::ImplBlock { type_name, methods },
1204 Span::merge(start, self.prev_span()),
1205 ))
1206 }
1207
1208 fn parse_guard(&mut self) -> Result<SNode, ParserError> {
1209 let start = self.current_span();
1210 self.consume(&TokenKind::Guard, "guard")?;
1211 let condition = self.parse_expression()?;
1212 self.consume(&TokenKind::Else, "else")?;
1213 self.consume(&TokenKind::LBrace, "{")?;
1214 let else_body = self.parse_block()?;
1215 self.consume(&TokenKind::RBrace, "}")?;
1216 Ok(spanned(
1217 Node::GuardStmt {
1218 condition: Box::new(condition),
1219 else_body,
1220 },
1221 Span::merge(start, self.prev_span()),
1222 ))
1223 }
1224
1225 fn parse_require(&mut self) -> Result<SNode, ParserError> {
1226 let start = self.current_span();
1227 self.consume(&TokenKind::Require, "require")?;
1228 let condition = self.parse_expression()?;
1229 let message = if self.check(&TokenKind::Comma) {
1230 self.advance();
1231 Some(Box::new(self.parse_expression()?))
1232 } else {
1233 None
1234 };
1235 Ok(spanned(
1236 Node::RequireStmt {
1237 condition: Box::new(condition),
1238 message,
1239 },
1240 Span::merge(start, self.prev_span()),
1241 ))
1242 }
1243
1244 fn parse_deadline(&mut self) -> Result<SNode, ParserError> {
1245 let start = self.current_span();
1246 self.consume(&TokenKind::Deadline, "deadline")?;
1247 let duration = self.parse_primary()?;
1248 self.consume(&TokenKind::LBrace, "{")?;
1249 let body = self.parse_block()?;
1250 self.consume(&TokenKind::RBrace, "}")?;
1251 Ok(spanned(
1252 Node::DeadlineBlock {
1253 duration: Box::new(duration),
1254 body,
1255 },
1256 Span::merge(start, self.prev_span()),
1257 ))
1258 }
1259
1260 fn parse_yield(&mut self) -> Result<SNode, ParserError> {
1261 let start = self.current_span();
1262 self.consume(&TokenKind::Yield, "yield")?;
1263 if self.is_at_end() || self.check(&TokenKind::Newline) || self.check(&TokenKind::RBrace) {
1264 return Ok(spanned(
1265 Node::YieldExpr { value: None },
1266 Span::merge(start, self.prev_span()),
1267 ));
1268 }
1269 let value = self.parse_expression()?;
1270 Ok(spanned(
1271 Node::YieldExpr {
1272 value: Some(Box::new(value)),
1273 },
1274 Span::merge(start, self.prev_span()),
1275 ))
1276 }
1277
1278 fn parse_mutex(&mut self) -> Result<SNode, ParserError> {
1279 let start = self.current_span();
1280 self.consume(&TokenKind::Mutex, "mutex")?;
1281 self.consume(&TokenKind::LBrace, "{")?;
1282 let body = self.parse_block()?;
1283 self.consume(&TokenKind::RBrace, "}")?;
1284 Ok(spanned(
1285 Node::MutexBlock { body },
1286 Span::merge(start, self.prev_span()),
1287 ))
1288 }
1289
1290 fn parse_defer(&mut self) -> Result<SNode, ParserError> {
1291 let start = self.current_span();
1292 self.consume(&TokenKind::Defer, "defer")?;
1293 self.consume(&TokenKind::LBrace, "{")?;
1294 let body = self.parse_block()?;
1295 self.consume(&TokenKind::RBrace, "}")?;
1296 Ok(spanned(
1297 Node::DeferStmt { body },
1298 Span::merge(start, self.prev_span()),
1299 ))
1300 }
1301
1302 fn parse_expression_statement(&mut self) -> Result<SNode, ParserError> {
1303 let start = self.current_span();
1304 let expr = self.parse_expression()?;
1305
1306 let is_assignable = matches!(
1309 expr.node,
1310 Node::Identifier(_) | Node::PropertyAccess { .. } | Node::SubscriptAccess { .. }
1311 );
1312 if is_assignable {
1313 if self.check(&TokenKind::Assign) {
1314 self.advance();
1315 let value = self.parse_expression()?;
1316 return Ok(spanned(
1317 Node::Assignment {
1318 target: Box::new(expr),
1319 value: Box::new(value),
1320 op: None,
1321 },
1322 Span::merge(start, self.prev_span()),
1323 ));
1324 }
1325 let compound_op = if self.check(&TokenKind::PlusAssign) {
1326 Some("+")
1327 } else if self.check(&TokenKind::MinusAssign) {
1328 Some("-")
1329 } else if self.check(&TokenKind::StarAssign) {
1330 Some("*")
1331 } else if self.check(&TokenKind::SlashAssign) {
1332 Some("/")
1333 } else if self.check(&TokenKind::PercentAssign) {
1334 Some("%")
1335 } else {
1336 None
1337 };
1338 if let Some(op) = compound_op {
1339 self.advance();
1340 let value = self.parse_expression()?;
1341 return Ok(spanned(
1342 Node::Assignment {
1343 target: Box::new(expr),
1344 value: Box::new(value),
1345 op: Some(op.into()),
1346 },
1347 Span::merge(start, self.prev_span()),
1348 ));
1349 }
1350 }
1351
1352 Ok(expr)
1353 }
1354
1355 fn parse_expression(&mut self) -> Result<SNode, ParserError> {
1356 self.skip_newlines();
1357 self.parse_pipe()
1358 }
1359
1360 fn parse_pipe(&mut self) -> Result<SNode, ParserError> {
1361 let mut left = self.parse_range()?;
1362 while self.check_skip_newlines(&TokenKind::Pipe) {
1363 let start = left.span;
1364 self.advance();
1365 let right = self.parse_range()?;
1366 left = spanned(
1367 Node::BinaryOp {
1368 op: "|>".into(),
1369 left: Box::new(left),
1370 right: Box::new(right),
1371 },
1372 Span::merge(start, self.prev_span()),
1373 );
1374 }
1375 Ok(left)
1376 }
1377
1378 fn parse_range(&mut self) -> Result<SNode, ParserError> {
1379 let left = self.parse_ternary()?;
1380 if self.check(&TokenKind::To) {
1381 let start = left.span;
1382 self.advance();
1383 let right = self.parse_ternary()?;
1384 let inclusive = if self.check(&TokenKind::Exclusive) {
1385 self.advance();
1386 false
1387 } else {
1388 true
1389 };
1390 return Ok(spanned(
1391 Node::RangeExpr {
1392 start: Box::new(left),
1393 end: Box::new(right),
1394 inclusive,
1395 },
1396 Span::merge(start, self.prev_span()),
1397 ));
1398 }
1399 Ok(left)
1400 }
1401
1402 fn parse_ternary(&mut self) -> Result<SNode, ParserError> {
1403 let condition = self.parse_logical_or()?;
1404 if !self.check(&TokenKind::Question) {
1405 return Ok(condition);
1406 }
1407 let start = condition.span;
1408 self.advance(); let true_val = self.parse_logical_or()?;
1410 self.consume(&TokenKind::Colon, ":")?;
1411 let false_val = self.parse_logical_or()?;
1412 Ok(spanned(
1413 Node::Ternary {
1414 condition: Box::new(condition),
1415 true_expr: Box::new(true_val),
1416 false_expr: Box::new(false_val),
1417 },
1418 Span::merge(start, self.prev_span()),
1419 ))
1420 }
1421
1422 fn parse_nil_coalescing(&mut self) -> Result<SNode, ParserError> {
1425 let mut left = self.parse_multiplicative()?;
1426 while self.check(&TokenKind::NilCoal) {
1427 let start = left.span;
1428 self.advance();
1429 let right = self.parse_multiplicative()?;
1430 left = spanned(
1431 Node::BinaryOp {
1432 op: "??".into(),
1433 left: Box::new(left),
1434 right: Box::new(right),
1435 },
1436 Span::merge(start, self.prev_span()),
1437 );
1438 }
1439 Ok(left)
1440 }
1441
1442 fn parse_logical_or(&mut self) -> Result<SNode, ParserError> {
1443 let mut left = self.parse_logical_and()?;
1444 while self.check_skip_newlines(&TokenKind::Or) {
1445 let start = left.span;
1446 self.advance();
1447 let right = self.parse_logical_and()?;
1448 left = spanned(
1449 Node::BinaryOp {
1450 op: "||".into(),
1451 left: Box::new(left),
1452 right: Box::new(right),
1453 },
1454 Span::merge(start, self.prev_span()),
1455 );
1456 }
1457 Ok(left)
1458 }
1459
1460 fn parse_logical_and(&mut self) -> Result<SNode, ParserError> {
1461 let mut left = self.parse_equality()?;
1462 while self.check_skip_newlines(&TokenKind::And) {
1463 let start = left.span;
1464 self.advance();
1465 let right = self.parse_equality()?;
1466 left = spanned(
1467 Node::BinaryOp {
1468 op: "&&".into(),
1469 left: Box::new(left),
1470 right: Box::new(right),
1471 },
1472 Span::merge(start, self.prev_span()),
1473 );
1474 }
1475 Ok(left)
1476 }
1477
1478 fn parse_equality(&mut self) -> Result<SNode, ParserError> {
1479 let mut left = self.parse_comparison()?;
1480 while self.check(&TokenKind::Eq) || self.check(&TokenKind::Neq) {
1481 let start = left.span;
1482 let op = if self.check(&TokenKind::Eq) {
1483 "=="
1484 } else {
1485 "!="
1486 };
1487 self.advance();
1488 let right = self.parse_comparison()?;
1489 left = spanned(
1490 Node::BinaryOp {
1491 op: op.into(),
1492 left: Box::new(left),
1493 right: Box::new(right),
1494 },
1495 Span::merge(start, self.prev_span()),
1496 );
1497 }
1498 Ok(left)
1499 }
1500
1501 fn parse_comparison(&mut self) -> Result<SNode, ParserError> {
1502 let mut left = self.parse_additive()?;
1503 loop {
1504 if self.check(&TokenKind::Lt)
1505 || self.check(&TokenKind::Gt)
1506 || self.check(&TokenKind::Lte)
1507 || self.check(&TokenKind::Gte)
1508 {
1509 let start = left.span;
1510 let op = match self.current().map(|t| &t.kind) {
1511 Some(TokenKind::Lt) => "<",
1512 Some(TokenKind::Gt) => ">",
1513 Some(TokenKind::Lte) => "<=",
1514 Some(TokenKind::Gte) => ">=",
1515 _ => "<",
1516 };
1517 self.advance();
1518 let right = self.parse_additive()?;
1519 left = spanned(
1520 Node::BinaryOp {
1521 op: op.into(),
1522 left: Box::new(left),
1523 right: Box::new(right),
1524 },
1525 Span::merge(start, self.prev_span()),
1526 );
1527 } else if self.check(&TokenKind::In) {
1528 let start = left.span;
1529 self.advance();
1530 let right = self.parse_additive()?;
1531 left = spanned(
1532 Node::BinaryOp {
1533 op: "in".into(),
1534 left: Box::new(left),
1535 right: Box::new(right),
1536 },
1537 Span::merge(start, self.prev_span()),
1538 );
1539 } else if self.check_identifier("not") {
1540 let saved = self.pos;
1541 self.advance();
1542 if self.check(&TokenKind::In) {
1543 let start = left.span;
1544 self.advance();
1545 let right = self.parse_additive()?;
1546 left = spanned(
1547 Node::BinaryOp {
1548 op: "not_in".into(),
1549 left: Box::new(left),
1550 right: Box::new(right),
1551 },
1552 Span::merge(start, self.prev_span()),
1553 );
1554 } else {
1555 self.pos = saved;
1556 break;
1557 }
1558 } else {
1559 break;
1560 }
1561 }
1562 Ok(left)
1563 }
1564
1565 fn parse_additive(&mut self) -> Result<SNode, ParserError> {
1566 let mut left = self.parse_nil_coalescing()?;
1567 while self.check_skip_newlines(&TokenKind::Plus) || self.check(&TokenKind::Minus) {
1568 let start = left.span;
1569 let op = if self.check(&TokenKind::Plus) {
1570 "+"
1571 } else {
1572 "-"
1573 };
1574 self.advance();
1575 let right = self.parse_nil_coalescing()?;
1576 left = spanned(
1577 Node::BinaryOp {
1578 op: op.into(),
1579 left: Box::new(left),
1580 right: Box::new(right),
1581 },
1582 Span::merge(start, self.prev_span()),
1583 );
1584 }
1585 Ok(left)
1586 }
1587
1588 fn parse_multiplicative(&mut self) -> Result<SNode, ParserError> {
1589 let mut left = self.parse_exponent()?;
1590 while self.check_skip_newlines(&TokenKind::Star)
1591 || self.check_skip_newlines(&TokenKind::Slash)
1592 || self.check_skip_newlines(&TokenKind::Percent)
1593 {
1594 let start = left.span;
1595 let op = if self.check(&TokenKind::Star) {
1596 "*"
1597 } else if self.check(&TokenKind::Slash) {
1598 "/"
1599 } else {
1600 "%"
1601 };
1602 self.advance();
1603 let right = self.parse_exponent()?;
1604 left = spanned(
1605 Node::BinaryOp {
1606 op: op.into(),
1607 left: Box::new(left),
1608 right: Box::new(right),
1609 },
1610 Span::merge(start, self.prev_span()),
1611 );
1612 }
1613 Ok(left)
1614 }
1615
1616 fn parse_exponent(&mut self) -> Result<SNode, ParserError> {
1617 let left = self.parse_unary()?;
1618 if !self.check_skip_newlines(&TokenKind::Pow) {
1619 return Ok(left);
1620 }
1621
1622 let start = left.span;
1623 self.advance();
1624 let right = self.parse_exponent()?;
1625 Ok(spanned(
1626 Node::BinaryOp {
1627 op: "**".into(),
1628 left: Box::new(left),
1629 right: Box::new(right),
1630 },
1631 Span::merge(start, self.prev_span()),
1632 ))
1633 }
1634
1635 fn parse_unary(&mut self) -> Result<SNode, ParserError> {
1636 if self.check(&TokenKind::Not) {
1637 let start = self.current_span();
1638 self.advance();
1639 let operand = self.parse_unary()?;
1640 return Ok(spanned(
1641 Node::UnaryOp {
1642 op: "!".into(),
1643 operand: Box::new(operand),
1644 },
1645 Span::merge(start, self.prev_span()),
1646 ));
1647 }
1648 if self.check(&TokenKind::Minus) {
1649 let start = self.current_span();
1650 self.advance();
1651 let operand = self.parse_unary()?;
1652 return Ok(spanned(
1653 Node::UnaryOp {
1654 op: "-".into(),
1655 operand: Box::new(operand),
1656 },
1657 Span::merge(start, self.prev_span()),
1658 ));
1659 }
1660 self.parse_postfix()
1661 }
1662
1663 fn parse_postfix(&mut self) -> Result<SNode, ParserError> {
1664 let mut expr = self.parse_primary()?;
1665
1666 loop {
1667 if self.check_skip_newlines(&TokenKind::Dot)
1668 || self.check_skip_newlines(&TokenKind::QuestionDot)
1669 {
1670 let optional = self.check(&TokenKind::QuestionDot);
1671 let start = expr.span;
1672 self.advance();
1673 let member = self.consume_identifier_or_keyword("member name")?;
1674 if self.check(&TokenKind::LParen) {
1675 self.advance();
1676 let args = self.parse_arg_list()?;
1677 self.consume(&TokenKind::RParen, ")")?;
1678 if optional {
1679 expr = spanned(
1680 Node::OptionalMethodCall {
1681 object: Box::new(expr),
1682 method: member,
1683 args,
1684 },
1685 Span::merge(start, self.prev_span()),
1686 );
1687 } else {
1688 expr = spanned(
1689 Node::MethodCall {
1690 object: Box::new(expr),
1691 method: member,
1692 args,
1693 },
1694 Span::merge(start, self.prev_span()),
1695 );
1696 }
1697 } else if optional {
1698 expr = spanned(
1699 Node::OptionalPropertyAccess {
1700 object: Box::new(expr),
1701 property: member,
1702 },
1703 Span::merge(start, self.prev_span()),
1704 );
1705 } else {
1706 expr = spanned(
1707 Node::PropertyAccess {
1708 object: Box::new(expr),
1709 property: member,
1710 },
1711 Span::merge(start, self.prev_span()),
1712 );
1713 }
1714 } else if self.check(&TokenKind::LBracket) {
1715 let start = expr.span;
1716 self.advance();
1717
1718 if self.check(&TokenKind::Colon) {
1721 self.advance();
1722 let end_expr = if self.check(&TokenKind::RBracket) {
1723 None
1724 } else {
1725 Some(Box::new(self.parse_expression()?))
1726 };
1727 self.consume(&TokenKind::RBracket, "]")?;
1728 expr = spanned(
1729 Node::SliceAccess {
1730 object: Box::new(expr),
1731 start: None,
1732 end: end_expr,
1733 },
1734 Span::merge(start, self.prev_span()),
1735 );
1736 } else {
1737 let index = self.parse_expression()?;
1738 if self.check(&TokenKind::Colon) {
1739 self.advance();
1740 let end_expr = if self.check(&TokenKind::RBracket) {
1741 None
1742 } else {
1743 Some(Box::new(self.parse_expression()?))
1744 };
1745 self.consume(&TokenKind::RBracket, "]")?;
1746 expr = spanned(
1747 Node::SliceAccess {
1748 object: Box::new(expr),
1749 start: Some(Box::new(index)),
1750 end: end_expr,
1751 },
1752 Span::merge(start, self.prev_span()),
1753 );
1754 } else {
1755 self.consume(&TokenKind::RBracket, "]")?;
1756 expr = spanned(
1757 Node::SubscriptAccess {
1758 object: Box::new(expr),
1759 index: Box::new(index),
1760 },
1761 Span::merge(start, self.prev_span()),
1762 );
1763 }
1764 }
1765 } else if self.check(&TokenKind::LBrace)
1766 && matches!(&expr.node, Node::Identifier(name) if self.struct_names.contains(name))
1767 {
1768 let start = expr.span;
1769 let struct_name = match expr.node {
1770 Node::Identifier(name) => name,
1771 _ => unreachable!("checked above"),
1772 };
1773 self.advance();
1774 let dict = self.parse_dict_literal(start)?;
1775 let fields = match dict.node {
1776 Node::DictLiteral(fields) => fields,
1777 _ => unreachable!("dict parser must return a dict literal"),
1778 };
1779 expr = spanned(
1780 Node::StructConstruct {
1781 struct_name,
1782 fields,
1783 },
1784 dict.span,
1785 );
1786 } else if self.check(&TokenKind::LParen) && matches!(expr.node, Node::Identifier(_)) {
1787 let start = expr.span;
1788 self.advance();
1789 let args = self.parse_arg_list()?;
1790 self.consume(&TokenKind::RParen, ")")?;
1791 if let Node::Identifier(name) = expr.node {
1792 expr = spanned(
1793 Node::FunctionCall { name, args },
1794 Span::merge(start, self.prev_span()),
1795 );
1796 }
1797 } else if self.check(&TokenKind::Question) {
1798 let next_pos = self.pos + 1;
1801 let is_ternary = self.tokens.get(next_pos).is_some_and(|t| {
1802 matches!(
1803 t.kind,
1804 TokenKind::Identifier(_)
1805 | TokenKind::IntLiteral(_)
1806 | TokenKind::FloatLiteral(_)
1807 | TokenKind::StringLiteral(_)
1808 | TokenKind::InterpolatedString(_)
1809 | TokenKind::True
1810 | TokenKind::False
1811 | TokenKind::Nil
1812 | TokenKind::LParen
1813 | TokenKind::LBracket
1814 | TokenKind::LBrace
1815 | TokenKind::Not
1816 | TokenKind::Minus
1817 | TokenKind::Fn
1818 )
1819 });
1820 if is_ternary {
1821 break;
1822 }
1823 let start = expr.span;
1824 self.advance();
1825 expr = spanned(
1826 Node::TryOperator {
1827 operand: Box::new(expr),
1828 },
1829 Span::merge(start, self.prev_span()),
1830 );
1831 } else {
1832 break;
1833 }
1834 }
1835
1836 Ok(expr)
1837 }
1838
1839 fn parse_primary(&mut self) -> Result<SNode, ParserError> {
1840 let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
1841 expected: "expression".into(),
1842 span: self.prev_span(),
1843 })?;
1844 let start = self.current_span();
1845
1846 match &tok.kind {
1847 TokenKind::StringLiteral(s) => {
1848 let s = s.clone();
1849 self.advance();
1850 Ok(spanned(
1851 Node::StringLiteral(s),
1852 Span::merge(start, self.prev_span()),
1853 ))
1854 }
1855 TokenKind::RawStringLiteral(s) => {
1856 let s = s.clone();
1857 self.advance();
1858 Ok(spanned(
1859 Node::RawStringLiteral(s),
1860 Span::merge(start, self.prev_span()),
1861 ))
1862 }
1863 TokenKind::InterpolatedString(segments) => {
1864 let segments = segments.clone();
1865 self.advance();
1866 Ok(spanned(
1867 Node::InterpolatedString(segments),
1868 Span::merge(start, self.prev_span()),
1869 ))
1870 }
1871 TokenKind::IntLiteral(n) => {
1872 let n = *n;
1873 self.advance();
1874 Ok(spanned(
1875 Node::IntLiteral(n),
1876 Span::merge(start, self.prev_span()),
1877 ))
1878 }
1879 TokenKind::FloatLiteral(n) => {
1880 let n = *n;
1881 self.advance();
1882 Ok(spanned(
1883 Node::FloatLiteral(n),
1884 Span::merge(start, self.prev_span()),
1885 ))
1886 }
1887 TokenKind::True => {
1888 self.advance();
1889 Ok(spanned(
1890 Node::BoolLiteral(true),
1891 Span::merge(start, self.prev_span()),
1892 ))
1893 }
1894 TokenKind::False => {
1895 self.advance();
1896 Ok(spanned(
1897 Node::BoolLiteral(false),
1898 Span::merge(start, self.prev_span()),
1899 ))
1900 }
1901 TokenKind::Nil => {
1902 self.advance();
1903 Ok(spanned(
1904 Node::NilLiteral,
1905 Span::merge(start, self.prev_span()),
1906 ))
1907 }
1908 TokenKind::Identifier(name) => {
1909 let name = name.clone();
1910 self.advance();
1911 Ok(spanned(
1912 Node::Identifier(name),
1913 Span::merge(start, self.prev_span()),
1914 ))
1915 }
1916 TokenKind::LParen => {
1917 self.advance();
1918 let expr = self.parse_expression()?;
1919 self.consume(&TokenKind::RParen, ")")?;
1920 Ok(expr)
1921 }
1922 TokenKind::LBracket => self.parse_list_literal(),
1923 TokenKind::LBrace => self.parse_dict_or_closure(),
1924 TokenKind::Parallel => self.parse_parallel(),
1925 TokenKind::Retry => self.parse_retry(),
1926 TokenKind::If => self.parse_if_else(),
1927 TokenKind::Spawn => self.parse_spawn_expr(),
1928 TokenKind::DurationLiteral(ms) => {
1929 let ms = *ms;
1930 self.advance();
1931 Ok(spanned(
1932 Node::DurationLiteral(ms),
1933 Span::merge(start, self.prev_span()),
1934 ))
1935 }
1936 TokenKind::Deadline => self.parse_deadline(),
1937 TokenKind::Try => self.parse_try_catch(),
1938 TokenKind::Match => self.parse_match(),
1939 TokenKind::Fn => self.parse_fn_expr(),
1940 TokenKind::Lt
1943 if matches!(self.peek_kind(), Some(&TokenKind::Lt))
1944 && matches!(self.peek_kind_at(2), Some(TokenKind::Identifier(_))) =>
1945 {
1946 Err(ParserError::Unexpected {
1947 got: "`<<` heredoc-like syntax".to_string(),
1948 expected: "an expression — heredocs are only valid \
1949 inside LLM tool-call argument JSON; \
1950 for multiline strings in source code use \
1951 triple-quoted `\"\"\"...\"\"\"`"
1952 .to_string(),
1953 span: start,
1954 })
1955 }
1956 _ => Err(self.error("expression")),
1957 }
1958 }
1959
1960 fn parse_fn_expr(&mut self) -> Result<SNode, ParserError> {
1963 let start = self.current_span();
1964 self.consume(&TokenKind::Fn, "fn")?;
1965 self.consume(&TokenKind::LParen, "(")?;
1966 let params = self.parse_typed_param_list()?;
1967 self.consume(&TokenKind::RParen, ")")?;
1968 self.consume(&TokenKind::LBrace, "{")?;
1969 let body = self.parse_block()?;
1970 self.consume(&TokenKind::RBrace, "}")?;
1971 Ok(spanned(
1972 Node::Closure {
1973 params,
1974 body,
1975 fn_syntax: true,
1976 },
1977 Span::merge(start, self.prev_span()),
1978 ))
1979 }
1980
1981 fn parse_spawn_expr(&mut self) -> Result<SNode, ParserError> {
1982 let start = self.current_span();
1983 self.consume(&TokenKind::Spawn, "spawn")?;
1984 self.consume(&TokenKind::LBrace, "{")?;
1985 let body = self.parse_block()?;
1986 self.consume(&TokenKind::RBrace, "}")?;
1987 Ok(spanned(
1988 Node::SpawnExpr { body },
1989 Span::merge(start, self.prev_span()),
1990 ))
1991 }
1992
1993 fn parse_list_literal(&mut self) -> Result<SNode, ParserError> {
1994 let start = self.current_span();
1995 self.consume(&TokenKind::LBracket, "[")?;
1996 let mut elements = Vec::new();
1997 self.skip_newlines();
1998
1999 while !self.is_at_end() && !self.check(&TokenKind::RBracket) {
2000 if self.check(&TokenKind::Dot) {
2001 let saved_pos = self.pos;
2002 self.advance();
2003 if self.check(&TokenKind::Dot) {
2004 self.advance();
2005 self.consume(&TokenKind::Dot, ".")?;
2006 let spread_start = self.tokens[saved_pos].span;
2007 let expr = self.parse_expression()?;
2008 elements.push(spanned(
2009 Node::Spread(Box::new(expr)),
2010 Span::merge(spread_start, self.prev_span()),
2011 ));
2012 } else {
2013 self.pos = saved_pos;
2014 elements.push(self.parse_expression()?);
2015 }
2016 } else {
2017 elements.push(self.parse_expression()?);
2018 }
2019 self.skip_newlines();
2020 if self.check(&TokenKind::Comma) {
2021 self.advance();
2022 self.skip_newlines();
2023 }
2024 }
2025
2026 self.consume(&TokenKind::RBracket, "]")?;
2027 Ok(spanned(
2028 Node::ListLiteral(elements),
2029 Span::merge(start, self.prev_span()),
2030 ))
2031 }
2032
2033 fn parse_dict_or_closure(&mut self) -> Result<SNode, ParserError> {
2034 let start = self.current_span();
2035 self.consume(&TokenKind::LBrace, "{")?;
2036 self.skip_newlines();
2037
2038 if self.check(&TokenKind::RBrace) {
2039 self.advance();
2040 return Ok(spanned(
2041 Node::DictLiteral(Vec::new()),
2042 Span::merge(start, self.prev_span()),
2043 ));
2044 }
2045
2046 let saved = self.pos;
2048 if self.is_closure_lookahead() {
2049 self.pos = saved;
2050 return self.parse_closure_body(start);
2051 }
2052 self.pos = saved;
2053 self.parse_dict_literal(start)
2054 }
2055
2056 fn is_closure_lookahead(&mut self) -> bool {
2058 let mut depth = 0;
2059 while !self.is_at_end() {
2060 if let Some(tok) = self.current() {
2061 match &tok.kind {
2062 TokenKind::Arrow if depth == 0 => return true,
2063 TokenKind::LBrace | TokenKind::LParen | TokenKind::LBracket => depth += 1,
2064 TokenKind::RBrace if depth == 0 => return false,
2065 TokenKind::RBrace => depth -= 1,
2066 TokenKind::RParen | TokenKind::RBracket => {
2067 if depth > 0 {
2068 depth -= 1;
2069 }
2070 }
2071 _ => {}
2072 }
2073 self.advance();
2074 } else {
2075 return false;
2076 }
2077 }
2078 false
2079 }
2080
2081 fn parse_closure_body(&mut self, start: Span) -> Result<SNode, ParserError> {
2083 let params = self.parse_typed_param_list_until_arrow()?;
2084 self.consume(&TokenKind::Arrow, "->")?;
2085 let body = self.parse_block()?;
2086 self.consume(&TokenKind::RBrace, "}")?;
2087 Ok(spanned(
2088 Node::Closure {
2089 params,
2090 body,
2091 fn_syntax: false,
2092 },
2093 Span::merge(start, self.prev_span()),
2094 ))
2095 }
2096
2097 fn parse_typed_param_list_until_arrow(&mut self) -> Result<Vec<TypedParam>, ParserError> {
2099 self.parse_typed_params_until(|tok| tok == &TokenKind::Arrow)
2100 }
2101
2102 fn parse_dict_literal(&mut self, start: Span) -> Result<SNode, ParserError> {
2103 let entries = self.parse_dict_entries()?;
2104 Ok(spanned(
2105 Node::DictLiteral(entries),
2106 Span::merge(start, self.prev_span()),
2107 ))
2108 }
2109
2110 fn parse_dict_entries(&mut self) -> Result<Vec<DictEntry>, ParserError> {
2111 let mut entries = Vec::new();
2112 self.skip_newlines();
2113
2114 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
2115 if self.check(&TokenKind::Dot) {
2116 let saved_pos = self.pos;
2117 self.advance();
2118 if self.check(&TokenKind::Dot) {
2119 self.advance();
2120 if self.check(&TokenKind::Dot) {
2121 self.advance();
2122 let spread_start = self.tokens[saved_pos].span;
2123 let expr = self.parse_expression()?;
2124 entries.push(DictEntry {
2125 key: spanned(Node::NilLiteral, spread_start),
2126 value: spanned(
2127 Node::Spread(Box::new(expr)),
2128 Span::merge(spread_start, self.prev_span()),
2129 ),
2130 });
2131 self.skip_newlines();
2132 if self.check(&TokenKind::Comma) {
2133 self.advance();
2134 self.skip_newlines();
2135 }
2136 continue;
2137 }
2138 self.pos = saved_pos;
2139 } else {
2140 self.pos = saved_pos;
2141 }
2142 }
2143 let key = if self.check(&TokenKind::LBracket) {
2144 self.advance();
2145 let k = self.parse_expression()?;
2146 self.consume(&TokenKind::RBracket, "]")?;
2147 k
2148 } else if matches!(
2149 self.current().map(|t| &t.kind),
2150 Some(TokenKind::StringLiteral(_))
2151 ) {
2152 let key_span = self.current_span();
2153 let name =
2154 if let Some(TokenKind::StringLiteral(s)) = self.current().map(|t| &t.kind) {
2155 s.clone()
2156 } else {
2157 unreachable!()
2158 };
2159 self.advance();
2160 spanned(Node::StringLiteral(name), key_span)
2161 } else {
2162 let key_span = self.current_span();
2163 let name = self.consume_identifier_or_keyword("dict key")?;
2164 spanned(Node::StringLiteral(name), key_span)
2165 };
2166 self.consume(&TokenKind::Colon, ":")?;
2167 let value = self.parse_expression()?;
2168 entries.push(DictEntry { key, value });
2169 self.skip_newlines();
2170 if self.check(&TokenKind::Comma) {
2171 self.advance();
2172 self.skip_newlines();
2173 }
2174 }
2175
2176 self.consume(&TokenKind::RBrace, "}")?;
2177 Ok(entries)
2178 }
2179
2180 fn parse_param_list(&mut self) -> Result<Vec<String>, ParserError> {
2182 let mut params = Vec::new();
2183 self.skip_newlines();
2184
2185 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2186 params.push(self.consume_identifier("parameter name")?);
2187 if self.check(&TokenKind::Comma) {
2188 self.advance();
2189 self.skip_newlines();
2190 }
2191 }
2192 Ok(params)
2193 }
2194
2195 fn parse_typed_param_list(&mut self) -> Result<Vec<TypedParam>, ParserError> {
2197 self.parse_typed_params_until(|tok| tok == &TokenKind::RParen)
2198 }
2199
2200 fn parse_typed_params_until(
2203 &mut self,
2204 is_terminator: impl Fn(&TokenKind) -> bool,
2205 ) -> Result<Vec<TypedParam>, ParserError> {
2206 let mut params = Vec::new();
2207 let mut seen_default = false;
2208 self.skip_newlines();
2209
2210 while !self.is_at_end() {
2211 if let Some(tok) = self.current() {
2212 if is_terminator(&tok.kind) {
2213 break;
2214 }
2215 } else {
2216 break;
2217 }
2218 let is_rest = if self.check(&TokenKind::Dot) {
2219 let p1 = self.pos + 1;
2220 let p2 = self.pos + 2;
2221 let is_ellipsis = p1 < self.tokens.len()
2222 && p2 < self.tokens.len()
2223 && self.tokens[p1].kind == TokenKind::Dot
2224 && self.tokens[p2].kind == TokenKind::Dot;
2225 if is_ellipsis {
2226 self.advance();
2227 self.advance();
2228 self.advance();
2229 true
2230 } else {
2231 false
2232 }
2233 } else {
2234 false
2235 };
2236 let name = self.consume_identifier("parameter name")?;
2237 let type_expr = self.try_parse_type_annotation()?;
2238 let default_value = if self.check(&TokenKind::Assign) {
2239 self.advance();
2240 seen_default = true;
2241 Some(Box::new(self.parse_expression()?))
2242 } else {
2243 if seen_default && !is_rest {
2244 return Err(self.error(
2245 "Required parameter cannot follow a parameter with a default value",
2246 ));
2247 }
2248 None
2249 };
2250 if is_rest
2251 && !is_terminator(
2252 &self
2253 .current()
2254 .map(|t| t.kind.clone())
2255 .unwrap_or(TokenKind::Eof),
2256 )
2257 {
2258 return Err(self.error("Rest parameter must be the last parameter"));
2259 }
2260 params.push(TypedParam {
2261 name,
2262 type_expr,
2263 default_value,
2264 rest: is_rest,
2265 });
2266 if self.check(&TokenKind::Comma) {
2267 self.advance();
2268 self.skip_newlines();
2269 }
2270 }
2271 Ok(params)
2272 }
2273
2274 fn parse_type_param_list(&mut self) -> Result<Vec<TypeParam>, ParserError> {
2280 let mut params = Vec::new();
2281 self.skip_newlines();
2282 while !self.is_at_end() && !self.check(&TokenKind::Gt) {
2283 let variance = self.parse_optional_variance_marker();
2284 let name = self.consume_identifier("type parameter name")?;
2285 params.push(TypeParam { name, variance });
2286 if self.check(&TokenKind::Comma) {
2287 self.advance();
2288 self.skip_newlines();
2289 }
2290 }
2291 self.consume(&TokenKind::Gt, ">")?;
2292 Ok(params)
2293 }
2294
2295 fn parse_optional_variance_marker(&mut self) -> Variance {
2301 if self.check(&TokenKind::In) {
2302 self.advance();
2303 return Variance::Contravariant;
2304 }
2305 if self.check_identifier("out") {
2306 if let Some(kind) = self.peek_kind() {
2307 if matches!(kind, TokenKind::Identifier(_)) {
2308 self.advance();
2309 return Variance::Covariant;
2310 }
2311 }
2312 }
2313 Variance::Invariant
2314 }
2315
2316 fn parse_where_clauses(&mut self) -> Result<Vec<WhereClause>, ParserError> {
2318 if let Some(tok) = self.current() {
2319 if let TokenKind::Identifier(ref id) = tok.kind {
2320 if id == "where" {
2321 self.advance();
2322 let mut clauses = Vec::new();
2323 loop {
2324 self.skip_newlines();
2325 if self.check(&TokenKind::LBrace) || self.is_at_end() {
2326 break;
2327 }
2328 let type_name = self.consume_identifier("type parameter name")?;
2329 self.consume(&TokenKind::Colon, ":")?;
2330 let bound = self.consume_identifier("type bound")?;
2331 clauses.push(WhereClause { type_name, bound });
2332 if self.check(&TokenKind::Comma) {
2333 self.advance();
2334 } else {
2335 break;
2336 }
2337 }
2338 return Ok(clauses);
2339 }
2340 }
2341 }
2342 Ok(Vec::new())
2343 }
2344
2345 fn try_parse_type_annotation(&mut self) -> Result<Option<TypeExpr>, ParserError> {
2347 if !self.check(&TokenKind::Colon) {
2348 return Ok(None);
2349 }
2350 self.advance();
2351 Ok(Some(self.parse_type_expr()?))
2352 }
2353
2354 fn parse_type_expr(&mut self) -> Result<TypeExpr, ParserError> {
2356 self.skip_newlines();
2357 let first = self.parse_type_primary()?;
2358
2359 if self.check(&TokenKind::Bar) {
2360 let mut types = vec![first];
2361 while self.check(&TokenKind::Bar) {
2362 self.advance();
2363 types.push(self.parse_type_primary()?);
2364 }
2365 return Ok(TypeExpr::Union(types));
2366 }
2367
2368 Ok(first)
2369 }
2370
2371 fn parse_type_primary(&mut self) -> Result<TypeExpr, ParserError> {
2373 self.skip_newlines();
2374 if self.check(&TokenKind::LBrace) {
2375 return self.parse_shape_type();
2376 }
2377 if let Some(tok) = self.current() {
2378 match &tok.kind {
2379 TokenKind::Nil => {
2380 self.advance();
2381 return Ok(TypeExpr::Named("nil".to_string()));
2382 }
2383 TokenKind::True | TokenKind::False => {
2384 self.advance();
2385 return Ok(TypeExpr::Named("bool".to_string()));
2386 }
2387 TokenKind::StringLiteral(text) | TokenKind::RawStringLiteral(text) => {
2388 let text = text.clone();
2389 self.advance();
2390 return Ok(TypeExpr::LitString(text));
2391 }
2392 TokenKind::IntLiteral(value) => {
2393 let value = *value;
2394 self.advance();
2395 return Ok(TypeExpr::LitInt(value));
2396 }
2397 TokenKind::Minus => {
2398 if let Some(TokenKind::IntLiteral(v)) = self.peek_kind_at(1) {
2400 let v = *v;
2401 self.advance();
2402 self.advance();
2403 return Ok(TypeExpr::LitInt(-v));
2404 }
2405 }
2406 _ => {}
2407 }
2408 }
2409 if self.check(&TokenKind::Fn) {
2410 self.advance();
2411 self.consume(&TokenKind::LParen, "(")?;
2412 let mut params = Vec::new();
2413 self.skip_newlines();
2414 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2415 params.push(self.parse_type_expr()?);
2416 self.skip_newlines();
2417 if self.check(&TokenKind::Comma) {
2418 self.advance();
2419 self.skip_newlines();
2420 }
2421 }
2422 self.consume(&TokenKind::RParen, ")")?;
2423 self.consume(&TokenKind::Arrow, "->")?;
2424 let return_type = self.parse_type_expr()?;
2425 return Ok(TypeExpr::FnType {
2426 params,
2427 return_type: Box::new(return_type),
2428 });
2429 }
2430 let name = self.consume_identifier("type name")?;
2431 if name == "never" {
2432 return Ok(TypeExpr::Never);
2433 }
2434 if self.check(&TokenKind::Lt) {
2435 self.advance();
2436 let mut type_args = vec![self.parse_type_expr()?];
2437 while self.check(&TokenKind::Comma) {
2438 self.advance();
2439 type_args.push(self.parse_type_expr()?);
2440 }
2441 self.consume(&TokenKind::Gt, ">")?;
2442 if name == "list" && type_args.len() == 1 {
2443 return Ok(TypeExpr::List(Box::new(type_args.remove(0))));
2444 } else if name == "dict" && type_args.len() == 2 {
2445 return Ok(TypeExpr::DictType(
2446 Box::new(type_args.remove(0)),
2447 Box::new(type_args.remove(0)),
2448 ));
2449 } else if (name == "iter" || name == "Iter") && type_args.len() == 1 {
2450 return Ok(TypeExpr::Iter(Box::new(type_args.remove(0))));
2451 }
2452 return Ok(TypeExpr::Applied {
2453 name,
2454 args: type_args,
2455 });
2456 }
2457 Ok(TypeExpr::Named(name))
2458 }
2459
2460 fn parse_shape_type(&mut self) -> Result<TypeExpr, ParserError> {
2462 self.consume(&TokenKind::LBrace, "{")?;
2463 let mut fields = Vec::new();
2464 self.skip_newlines();
2465
2466 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
2467 let name = self.consume_identifier("field name")?;
2468 let optional = if self.check(&TokenKind::Question) {
2469 self.advance();
2470 true
2471 } else {
2472 false
2473 };
2474 self.consume(&TokenKind::Colon, ":")?;
2475 let type_expr = self.parse_type_expr()?;
2476 fields.push(ShapeField {
2477 name,
2478 type_expr,
2479 optional,
2480 });
2481 self.skip_newlines();
2482 if self.check(&TokenKind::Comma) {
2483 self.advance();
2484 self.skip_newlines();
2485 }
2486 }
2487
2488 self.consume(&TokenKind::RBrace, "}")?;
2489 Ok(TypeExpr::Shape(fields))
2490 }
2491
2492 fn parse_arg_list(&mut self) -> Result<Vec<SNode>, ParserError> {
2493 let mut args = Vec::new();
2494 self.skip_newlines();
2495
2496 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2497 if self.check(&TokenKind::Dot) {
2498 let saved_pos = self.pos;
2499 self.advance();
2500 if self.check(&TokenKind::Dot) {
2501 self.advance();
2502 self.consume(&TokenKind::Dot, ".")?;
2503 let spread_start = self.tokens[saved_pos].span;
2504 let expr = self.parse_expression()?;
2505 args.push(spanned(
2506 Node::Spread(Box::new(expr)),
2507 Span::merge(spread_start, self.prev_span()),
2508 ));
2509 } else {
2510 self.pos = saved_pos;
2511 args.push(self.parse_expression()?);
2512 }
2513 } else {
2514 args.push(self.parse_expression()?);
2515 }
2516 self.skip_newlines();
2517 if self.check(&TokenKind::Comma) {
2518 self.advance();
2519 self.skip_newlines();
2520 }
2521 }
2522 Ok(args)
2523 }
2524
2525 fn is_at_end(&self) -> bool {
2526 self.pos >= self.tokens.len()
2527 || matches!(self.tokens.get(self.pos), Some(t) if t.kind == TokenKind::Eof)
2528 }
2529
2530 fn current(&self) -> Option<&Token> {
2531 self.tokens.get(self.pos)
2532 }
2533
2534 fn peek_kind(&self) -> Option<&TokenKind> {
2535 self.tokens.get(self.pos + 1).map(|t| &t.kind)
2536 }
2537
2538 fn peek_kind_at(&self, offset: usize) -> Option<&TokenKind> {
2539 self.tokens.get(self.pos + offset).map(|t| &t.kind)
2540 }
2541
2542 fn check(&self, kind: &TokenKind) -> bool {
2543 self.current()
2544 .map(|t| std::mem::discriminant(&t.kind) == std::mem::discriminant(kind))
2545 .unwrap_or(false)
2546 }
2547
2548 fn check_skip_newlines(&mut self, kind: &TokenKind) -> bool {
2551 let saved = self.pos;
2552 self.skip_newlines();
2553 if self.check(kind) {
2554 true
2555 } else {
2556 self.pos = saved;
2557 false
2558 }
2559 }
2560
2561 fn check_identifier(&self, name: &str) -> bool {
2563 matches!(self.current().map(|t| &t.kind), Some(TokenKind::Identifier(s)) if s == name)
2564 }
2565
2566 fn advance(&mut self) {
2567 if self.pos < self.tokens.len() {
2568 self.pos += 1;
2569 }
2570 }
2571
2572 fn consume(&mut self, kind: &TokenKind, expected: &str) -> Result<Token, ParserError> {
2573 self.skip_newlines();
2574 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2575 if std::mem::discriminant(&tok.kind) != std::mem::discriminant(kind) {
2576 return Err(self.make_error(expected));
2577 }
2578 let tok = tok.clone();
2579 self.advance();
2580 Ok(tok)
2581 }
2582
2583 fn consume_identifier(&mut self, expected: &str) -> Result<String, ParserError> {
2584 self.skip_newlines();
2585 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2586 if let TokenKind::Identifier(name) = &tok.kind {
2587 let name = name.clone();
2588 self.advance();
2589 Ok(name)
2590 } else {
2591 let kw_name = harn_lexer::KEYWORDS
2594 .iter()
2595 .find(|&&kw| kw == tok.kind.to_string());
2596 if let Some(kw) = kw_name {
2597 Err(ParserError::Unexpected {
2598 got: format!("'{kw}' (reserved keyword)"),
2599 expected: expected.into(),
2600 span: tok.span,
2601 })
2602 } else {
2603 Err(self.make_error(expected))
2604 }
2605 }
2606 }
2607
2608 fn consume_identifier_or_keyword(&mut self, expected: &str) -> Result<String, ParserError> {
2612 self.skip_newlines();
2613 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2614 if let TokenKind::Identifier(name) = &tok.kind {
2615 let name = name.clone();
2616 self.advance();
2617 return Ok(name);
2618 }
2619 let name = match &tok.kind {
2620 TokenKind::Pipeline => "pipeline",
2621 TokenKind::Extends => "extends",
2622 TokenKind::Override => "override",
2623 TokenKind::Let => "let",
2624 TokenKind::Var => "var",
2625 TokenKind::If => "if",
2626 TokenKind::Else => "else",
2627 TokenKind::For => "for",
2628 TokenKind::In => "in",
2629 TokenKind::Match => "match",
2630 TokenKind::Retry => "retry",
2631 TokenKind::Parallel => "parallel",
2632 TokenKind::Return => "return",
2633 TokenKind::Import => "import",
2634 TokenKind::True => "true",
2635 TokenKind::False => "false",
2636 TokenKind::Nil => "nil",
2637 TokenKind::Try => "try",
2638 TokenKind::Catch => "catch",
2639 TokenKind::Throw => "throw",
2640 TokenKind::Fn => "fn",
2641 TokenKind::Spawn => "spawn",
2642 TokenKind::While => "while",
2643 TokenKind::TypeKw => "type",
2644 TokenKind::Enum => "enum",
2645 TokenKind::Struct => "struct",
2646 TokenKind::Interface => "interface",
2647 TokenKind::Pub => "pub",
2648 TokenKind::From => "from",
2649 TokenKind::To => "to",
2650 TokenKind::Tool => "tool",
2651 TokenKind::Exclusive => "exclusive",
2652 TokenKind::Guard => "guard",
2653 TokenKind::Deadline => "deadline",
2654 TokenKind::Defer => "defer",
2655 TokenKind::Yield => "yield",
2656 TokenKind::Mutex => "mutex",
2657 TokenKind::Break => "break",
2658 TokenKind::Continue => "continue",
2659 TokenKind::Impl => "impl",
2660 _ => return Err(self.make_error(expected)),
2661 };
2662 let name = name.to_string();
2663 self.advance();
2664 Ok(name)
2665 }
2666
2667 fn skip_newlines(&mut self) {
2668 while self.pos < self.tokens.len() && self.tokens[self.pos].kind == TokenKind::Newline {
2669 self.pos += 1;
2670 }
2671 }
2672
2673 fn make_error(&self, expected: &str) -> ParserError {
2674 if let Some(tok) = self.tokens.get(self.pos) {
2675 if tok.kind == TokenKind::Eof {
2676 return ParserError::UnexpectedEof {
2677 expected: expected.into(),
2678 span: tok.span,
2679 };
2680 }
2681 ParserError::Unexpected {
2682 got: tok.kind.to_string(),
2683 expected: expected.into(),
2684 span: tok.span,
2685 }
2686 } else {
2687 ParserError::UnexpectedEof {
2688 expected: expected.into(),
2689 span: self.prev_span(),
2690 }
2691 }
2692 }
2693
2694 fn error(&self, expected: &str) -> ParserError {
2695 self.make_error(expected)
2696 }
2697}
2698
2699#[cfg(test)]
2700mod tests {
2701 use super::*;
2702 use harn_lexer::Lexer;
2703
2704 fn parse_source(source: &str) -> Result<Vec<SNode>, ParserError> {
2705 let mut lexer = Lexer::new(source);
2706 let tokens = lexer.tokenize().unwrap();
2707 let mut parser = Parser::new(tokens);
2708 parser.parse()
2709 }
2710
2711 #[test]
2712 fn parses_match_expression_with_let_in_arm_body() {
2713 let source = r#"
2714pipeline p() {
2715 let x = match 1 {
2716 1 -> {
2717 let a = 1
2718 a
2719 }
2720 _ -> { 0 }
2721 }
2722}
2723"#;
2724
2725 assert!(parse_source(source).is_ok());
2726 }
2727
2728 #[test]
2729 fn parses_public_declarations_and_generic_interfaces() {
2730 let source = r#"
2731pub pipeline build(task) extends base {
2732 return
2733}
2734
2735pub enum Result {
2736 Ok(value: string),
2737 Err(message: string, code: int),
2738}
2739
2740pub struct Config {
2741 host: string
2742 port?: int
2743}
2744
2745interface Repository<T> {
2746 type Item
2747 fn get(id: string) -> T
2748 fn map<U>(value: T, f: fn(T) -> U) -> U
2749}
2750"#;
2751
2752 let program = parse_source(source).expect("should parse");
2753 assert!(matches!(
2754 &program[0].node,
2755 Node::Pipeline {
2756 is_pub: true,
2757 extends: Some(base),
2758 ..
2759 } if base == "base"
2760 ));
2761 assert!(matches!(
2762 &program[1].node,
2763 Node::EnumDecl {
2764 is_pub: true,
2765 type_params,
2766 ..
2767 } if type_params.is_empty()
2768 ));
2769 assert!(matches!(
2770 &program[2].node,
2771 Node::StructDecl {
2772 is_pub: true,
2773 type_params,
2774 ..
2775 } if type_params.is_empty()
2776 ));
2777 assert!(matches!(
2778 &program[3].node,
2779 Node::InterfaceDecl {
2780 type_params,
2781 associated_types,
2782 methods,
2783 ..
2784 }
2785 if type_params.len() == 1
2786 && associated_types.len() == 1
2787 && methods.len() == 2
2788 && methods[1].type_params.len() == 1
2789 ));
2790 }
2791
2792 #[test]
2793 fn parses_generic_structs_and_enums() {
2794 let source = r#"
2795struct Pair<A, B> {
2796 first: A
2797 second: B
2798}
2799
2800enum Option<T> {
2801 Some(value: T)
2802 None
2803}
2804"#;
2805
2806 let program = parse_source(source).expect("should parse");
2807 assert!(matches!(
2808 &program[0].node,
2809 Node::StructDecl { type_params, .. } if type_params.len() == 2
2810 ));
2811 assert!(matches!(
2812 &program[1].node,
2813 Node::EnumDecl { type_params, .. } if type_params.len() == 1
2814 ));
2815 }
2816
2817 #[test]
2818 fn parses_struct_literal_syntax_for_known_structs() {
2819 let source = r#"
2820struct Point {
2821 x: int
2822 y: int
2823}
2824
2825pipeline test(task) {
2826 let point = Point { x: 3, y: 4 }
2827}
2828"#;
2829
2830 let program = parse_source(source).expect("should parse");
2831 let pipeline = program
2832 .iter()
2833 .find(|node| matches!(node.node, Node::Pipeline { .. }))
2834 .expect("pipeline node");
2835 let body = match &pipeline.node {
2836 Node::Pipeline { body, .. } => body,
2837 _ => unreachable!(),
2838 };
2839 assert!(matches!(
2840 &body[0].node,
2841 Node::LetBinding { value, .. }
2842 if matches!(
2843 value.node,
2844 Node::StructConstruct { ref struct_name, ref fields }
2845 if struct_name == "Point" && fields.len() == 2
2846 )
2847 ));
2848 }
2849
2850 #[test]
2851 fn parses_exponentiation_as_right_associative() {
2852 let mut lexer = Lexer::new("a ** b ** c");
2853 let tokens = lexer.tokenize().expect("tokens");
2854 let mut parser = Parser::new(tokens);
2855 let expr = parser.parse_single_expression().expect("expression");
2856
2857 assert!(matches!(
2858 expr.node,
2859 Node::BinaryOp { ref op, ref left, ref right }
2860 if op == "**"
2861 && matches!(left.node, Node::Identifier(ref name) if name == "a")
2862 && matches!(
2863 right.node,
2864 Node::BinaryOp { ref op, ref left, ref right }
2865 if op == "**"
2866 && matches!(left.node, Node::Identifier(ref name) if name == "b")
2867 && matches!(right.node, Node::Identifier(ref name) if name == "c")
2868 )
2869 ));
2870 }
2871
2872 #[test]
2873 fn parses_exponentiation_tighter_than_multiplication() {
2874 let mut lexer = Lexer::new("a * b ** c");
2875 let tokens = lexer.tokenize().expect("tokens");
2876 let mut parser = Parser::new(tokens);
2877 let expr = parser.parse_single_expression().expect("expression");
2878
2879 assert!(matches!(
2880 expr.node,
2881 Node::BinaryOp { ref op, ref left, ref right }
2882 if op == "*"
2883 && matches!(left.node, Node::Identifier(ref name) if name == "a")
2884 && matches!(
2885 right.node,
2886 Node::BinaryOp { ref op, ref left, ref right }
2887 if op == "**"
2888 && matches!(left.node, Node::Identifier(ref name) if name == "b")
2889 && matches!(right.node, Node::Identifier(ref name) if name == "c")
2890 )
2891 ));
2892 }
2893}