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