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_exponent()?;
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_exponent()?;
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_exponent(&mut self) -> Result<SNode, ParserError> {
1572 let left = self.parse_unary()?;
1573 if !self.check_skip_newlines(&TokenKind::Pow) {
1574 return Ok(left);
1575 }
1576
1577 let start = left.span;
1578 self.advance();
1579 let right = self.parse_exponent()?;
1580 Ok(spanned(
1581 Node::BinaryOp {
1582 op: "**".into(),
1583 left: Box::new(left),
1584 right: Box::new(right),
1585 },
1586 Span::merge(start, self.prev_span()),
1587 ))
1588 }
1589
1590 fn parse_unary(&mut self) -> Result<SNode, ParserError> {
1591 if self.check(&TokenKind::Not) {
1592 let start = self.current_span();
1593 self.advance();
1594 let operand = self.parse_unary()?;
1595 return Ok(spanned(
1596 Node::UnaryOp {
1597 op: "!".into(),
1598 operand: Box::new(operand),
1599 },
1600 Span::merge(start, self.prev_span()),
1601 ));
1602 }
1603 if self.check(&TokenKind::Minus) {
1604 let start = self.current_span();
1605 self.advance();
1606 let operand = self.parse_unary()?;
1607 return Ok(spanned(
1608 Node::UnaryOp {
1609 op: "-".into(),
1610 operand: Box::new(operand),
1611 },
1612 Span::merge(start, self.prev_span()),
1613 ));
1614 }
1615 self.parse_postfix()
1616 }
1617
1618 fn parse_postfix(&mut self) -> Result<SNode, ParserError> {
1619 let mut expr = self.parse_primary()?;
1620
1621 loop {
1622 if self.check_skip_newlines(&TokenKind::Dot)
1623 || self.check_skip_newlines(&TokenKind::QuestionDot)
1624 {
1625 let optional = self.check(&TokenKind::QuestionDot);
1626 let start = expr.span;
1627 self.advance();
1628 let member = self.consume_identifier_or_keyword("member name")?;
1629 if self.check(&TokenKind::LParen) {
1630 self.advance();
1631 let args = self.parse_arg_list()?;
1632 self.consume(&TokenKind::RParen, ")")?;
1633 if optional {
1634 expr = spanned(
1635 Node::OptionalMethodCall {
1636 object: Box::new(expr),
1637 method: member,
1638 args,
1639 },
1640 Span::merge(start, self.prev_span()),
1641 );
1642 } else {
1643 expr = spanned(
1644 Node::MethodCall {
1645 object: Box::new(expr),
1646 method: member,
1647 args,
1648 },
1649 Span::merge(start, self.prev_span()),
1650 );
1651 }
1652 } else if optional {
1653 expr = spanned(
1654 Node::OptionalPropertyAccess {
1655 object: Box::new(expr),
1656 property: member,
1657 },
1658 Span::merge(start, self.prev_span()),
1659 );
1660 } else {
1661 expr = spanned(
1662 Node::PropertyAccess {
1663 object: Box::new(expr),
1664 property: member,
1665 },
1666 Span::merge(start, self.prev_span()),
1667 );
1668 }
1669 } else if self.check(&TokenKind::LBracket) {
1670 let start = expr.span;
1671 self.advance();
1672
1673 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: None,
1690 end: end_expr,
1691 },
1692 Span::merge(start, self.prev_span()),
1693 );
1694 } else {
1695 let index = self.parse_expression()?;
1696 if self.check(&TokenKind::Colon) {
1697 self.advance(); let end_expr = if self.check(&TokenKind::RBracket) {
1700 None
1701 } else {
1702 Some(Box::new(self.parse_expression()?))
1703 };
1704 self.consume(&TokenKind::RBracket, "]")?;
1705 expr = spanned(
1706 Node::SliceAccess {
1707 object: Box::new(expr),
1708 start: Some(Box::new(index)),
1709 end: end_expr,
1710 },
1711 Span::merge(start, self.prev_span()),
1712 );
1713 } else {
1714 self.consume(&TokenKind::RBracket, "]")?;
1715 expr = spanned(
1716 Node::SubscriptAccess {
1717 object: Box::new(expr),
1718 index: Box::new(index),
1719 },
1720 Span::merge(start, self.prev_span()),
1721 );
1722 }
1723 }
1724 } else if self.check(&TokenKind::LBrace)
1725 && matches!(&expr.node, Node::Identifier(name) if self.struct_names.contains(name))
1726 {
1727 let start = expr.span;
1728 let struct_name = match expr.node {
1729 Node::Identifier(name) => name,
1730 _ => unreachable!("checked above"),
1731 };
1732 self.advance();
1733 let dict = self.parse_dict_literal(start)?;
1734 let fields = match dict.node {
1735 Node::DictLiteral(fields) => fields,
1736 _ => unreachable!("dict parser must return a dict literal"),
1737 };
1738 expr = spanned(
1739 Node::StructConstruct {
1740 struct_name,
1741 fields,
1742 },
1743 dict.span,
1744 );
1745 } else if self.check(&TokenKind::LParen) && matches!(expr.node, Node::Identifier(_)) {
1746 let start = expr.span;
1747 self.advance();
1748 let args = self.parse_arg_list()?;
1749 self.consume(&TokenKind::RParen, ")")?;
1750 if let Node::Identifier(name) = expr.node {
1751 expr = spanned(
1752 Node::FunctionCall { name, args },
1753 Span::merge(start, self.prev_span()),
1754 );
1755 }
1756 } else if self.check(&TokenKind::Question) {
1757 let next_pos = self.pos + 1;
1760 let is_ternary = self.tokens.get(next_pos).is_some_and(|t| {
1761 matches!(
1762 t.kind,
1763 TokenKind::Identifier(_)
1764 | TokenKind::IntLiteral(_)
1765 | TokenKind::FloatLiteral(_)
1766 | TokenKind::StringLiteral(_)
1767 | TokenKind::InterpolatedString(_)
1768 | TokenKind::True
1769 | TokenKind::False
1770 | TokenKind::Nil
1771 | TokenKind::LParen
1772 | TokenKind::LBracket
1773 | TokenKind::LBrace
1774 | TokenKind::Not
1775 | TokenKind::Minus
1776 | TokenKind::Fn
1777 )
1778 });
1779 if is_ternary {
1780 break;
1781 }
1782 let start = expr.span;
1783 self.advance(); expr = spanned(
1785 Node::TryOperator {
1786 operand: Box::new(expr),
1787 },
1788 Span::merge(start, self.prev_span()),
1789 );
1790 } else {
1791 break;
1792 }
1793 }
1794
1795 Ok(expr)
1796 }
1797
1798 fn parse_primary(&mut self) -> Result<SNode, ParserError> {
1799 let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
1800 expected: "expression".into(),
1801 span: self.prev_span(),
1802 })?;
1803 let start = self.current_span();
1804
1805 match &tok.kind {
1806 TokenKind::StringLiteral(s) => {
1807 let s = s.clone();
1808 self.advance();
1809 Ok(spanned(
1810 Node::StringLiteral(s),
1811 Span::merge(start, self.prev_span()),
1812 ))
1813 }
1814 TokenKind::RawStringLiteral(s) => {
1815 let s = s.clone();
1816 self.advance();
1817 Ok(spanned(
1818 Node::RawStringLiteral(s),
1819 Span::merge(start, self.prev_span()),
1820 ))
1821 }
1822 TokenKind::InterpolatedString(segments) => {
1823 let segments = segments.clone();
1824 self.advance();
1825 Ok(spanned(
1826 Node::InterpolatedString(segments),
1827 Span::merge(start, self.prev_span()),
1828 ))
1829 }
1830 TokenKind::IntLiteral(n) => {
1831 let n = *n;
1832 self.advance();
1833 Ok(spanned(
1834 Node::IntLiteral(n),
1835 Span::merge(start, self.prev_span()),
1836 ))
1837 }
1838 TokenKind::FloatLiteral(n) => {
1839 let n = *n;
1840 self.advance();
1841 Ok(spanned(
1842 Node::FloatLiteral(n),
1843 Span::merge(start, self.prev_span()),
1844 ))
1845 }
1846 TokenKind::True => {
1847 self.advance();
1848 Ok(spanned(
1849 Node::BoolLiteral(true),
1850 Span::merge(start, self.prev_span()),
1851 ))
1852 }
1853 TokenKind::False => {
1854 self.advance();
1855 Ok(spanned(
1856 Node::BoolLiteral(false),
1857 Span::merge(start, self.prev_span()),
1858 ))
1859 }
1860 TokenKind::Nil => {
1861 self.advance();
1862 Ok(spanned(
1863 Node::NilLiteral,
1864 Span::merge(start, self.prev_span()),
1865 ))
1866 }
1867 TokenKind::Identifier(name) => {
1868 let name = name.clone();
1869 self.advance();
1870 Ok(spanned(
1871 Node::Identifier(name),
1872 Span::merge(start, self.prev_span()),
1873 ))
1874 }
1875 TokenKind::LParen => {
1876 self.advance();
1877 let expr = self.parse_expression()?;
1878 self.consume(&TokenKind::RParen, ")")?;
1879 Ok(expr)
1880 }
1881 TokenKind::LBracket => self.parse_list_literal(),
1882 TokenKind::LBrace => self.parse_dict_or_closure(),
1883 TokenKind::Parallel => self.parse_parallel(),
1884 TokenKind::Retry => self.parse_retry(),
1885 TokenKind::If => self.parse_if_else(),
1886 TokenKind::Spawn => self.parse_spawn_expr(),
1887 TokenKind::DurationLiteral(ms) => {
1888 let ms = *ms;
1889 self.advance();
1890 Ok(spanned(
1891 Node::DurationLiteral(ms),
1892 Span::merge(start, self.prev_span()),
1893 ))
1894 }
1895 TokenKind::Deadline => self.parse_deadline(),
1896 TokenKind::Try => self.parse_try_catch(),
1897 TokenKind::Match => self.parse_match(),
1898 TokenKind::Fn => self.parse_fn_expr(),
1899 _ => Err(self.error("expression")),
1900 }
1901 }
1902
1903 fn parse_fn_expr(&mut self) -> Result<SNode, ParserError> {
1907 let start = self.current_span();
1908 self.consume(&TokenKind::Fn, "fn")?;
1909 self.consume(&TokenKind::LParen, "(")?;
1910 let params = self.parse_typed_param_list()?;
1911 self.consume(&TokenKind::RParen, ")")?;
1912 self.consume(&TokenKind::LBrace, "{")?;
1913 let body = self.parse_block()?;
1914 self.consume(&TokenKind::RBrace, "}")?;
1915 Ok(spanned(
1916 Node::Closure {
1917 params,
1918 body,
1919 fn_syntax: true,
1920 },
1921 Span::merge(start, self.prev_span()),
1922 ))
1923 }
1924
1925 fn parse_spawn_expr(&mut self) -> Result<SNode, ParserError> {
1926 let start = self.current_span();
1927 self.consume(&TokenKind::Spawn, "spawn")?;
1928 self.consume(&TokenKind::LBrace, "{")?;
1929 let body = self.parse_block()?;
1930 self.consume(&TokenKind::RBrace, "}")?;
1931 Ok(spanned(
1932 Node::SpawnExpr { body },
1933 Span::merge(start, self.prev_span()),
1934 ))
1935 }
1936
1937 fn parse_list_literal(&mut self) -> Result<SNode, ParserError> {
1938 let start = self.current_span();
1939 self.consume(&TokenKind::LBracket, "[")?;
1940 let mut elements = Vec::new();
1941 self.skip_newlines();
1942
1943 while !self.is_at_end() && !self.check(&TokenKind::RBracket) {
1944 if self.check(&TokenKind::Dot) {
1946 let saved_pos = self.pos;
1947 self.advance(); if self.check(&TokenKind::Dot) {
1949 self.advance(); self.consume(&TokenKind::Dot, ".")?; let spread_start = self.tokens[saved_pos].span;
1952 let expr = self.parse_expression()?;
1953 elements.push(spanned(
1954 Node::Spread(Box::new(expr)),
1955 Span::merge(spread_start, self.prev_span()),
1956 ));
1957 } else {
1958 self.pos = saved_pos;
1960 elements.push(self.parse_expression()?);
1961 }
1962 } else {
1963 elements.push(self.parse_expression()?);
1964 }
1965 self.skip_newlines();
1966 if self.check(&TokenKind::Comma) {
1967 self.advance();
1968 self.skip_newlines();
1969 }
1970 }
1971
1972 self.consume(&TokenKind::RBracket, "]")?;
1973 Ok(spanned(
1974 Node::ListLiteral(elements),
1975 Span::merge(start, self.prev_span()),
1976 ))
1977 }
1978
1979 fn parse_dict_or_closure(&mut self) -> Result<SNode, ParserError> {
1980 let start = self.current_span();
1981 self.consume(&TokenKind::LBrace, "{")?;
1982 self.skip_newlines();
1983
1984 if self.check(&TokenKind::RBrace) {
1986 self.advance();
1987 return Ok(spanned(
1988 Node::DictLiteral(Vec::new()),
1989 Span::merge(start, self.prev_span()),
1990 ));
1991 }
1992
1993 let saved = self.pos;
1995 if self.is_closure_lookahead() {
1996 self.pos = saved;
1997 return self.parse_closure_body(start);
1998 }
1999 self.pos = saved;
2000 self.parse_dict_literal(start)
2001 }
2002
2003 fn is_closure_lookahead(&mut self) -> bool {
2006 let mut depth = 0;
2007 while !self.is_at_end() {
2008 if let Some(tok) = self.current() {
2009 match &tok.kind {
2010 TokenKind::Arrow if depth == 0 => return true,
2011 TokenKind::LBrace | TokenKind::LParen | TokenKind::LBracket => depth += 1,
2012 TokenKind::RBrace if depth == 0 => return false,
2013 TokenKind::RBrace => depth -= 1,
2014 TokenKind::RParen | TokenKind::RBracket => {
2015 if depth > 0 {
2016 depth -= 1;
2017 }
2018 }
2019 _ => {}
2020 }
2021 self.advance();
2022 } else {
2023 return false;
2024 }
2025 }
2026 false
2027 }
2028
2029 fn parse_closure_body(&mut self, start: Span) -> Result<SNode, ParserError> {
2031 let params = self.parse_typed_param_list_until_arrow()?;
2032 self.consume(&TokenKind::Arrow, "->")?;
2033 let body = self.parse_block()?;
2034 self.consume(&TokenKind::RBrace, "}")?;
2035 Ok(spanned(
2036 Node::Closure {
2037 params,
2038 body,
2039 fn_syntax: false,
2040 },
2041 Span::merge(start, self.prev_span()),
2042 ))
2043 }
2044
2045 fn parse_typed_param_list_until_arrow(&mut self) -> Result<Vec<TypedParam>, ParserError> {
2047 self.parse_typed_params_until(|tok| tok == &TokenKind::Arrow)
2048 }
2049
2050 fn parse_dict_literal(&mut self, start: Span) -> Result<SNode, ParserError> {
2051 let entries = self.parse_dict_entries()?;
2052 Ok(spanned(
2053 Node::DictLiteral(entries),
2054 Span::merge(start, self.prev_span()),
2055 ))
2056 }
2057
2058 fn parse_dict_entries(&mut self) -> Result<Vec<DictEntry>, ParserError> {
2059 let mut entries = Vec::new();
2060 self.skip_newlines();
2061
2062 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
2063 if self.check(&TokenKind::Dot) {
2065 let saved_pos = self.pos;
2066 self.advance(); if self.check(&TokenKind::Dot) {
2068 self.advance(); if self.check(&TokenKind::Dot) {
2070 self.advance(); let spread_start = self.tokens[saved_pos].span;
2072 let expr = self.parse_expression()?;
2073 entries.push(DictEntry {
2074 key: spanned(Node::NilLiteral, spread_start),
2075 value: spanned(
2076 Node::Spread(Box::new(expr)),
2077 Span::merge(spread_start, self.prev_span()),
2078 ),
2079 });
2080 self.skip_newlines();
2081 if self.check(&TokenKind::Comma) {
2082 self.advance();
2083 self.skip_newlines();
2084 }
2085 continue;
2086 }
2087 self.pos = saved_pos;
2089 } else {
2090 self.pos = saved_pos;
2091 }
2092 }
2093 let key = if self.check(&TokenKind::LBracket) {
2094 self.advance();
2096 let k = self.parse_expression()?;
2097 self.consume(&TokenKind::RBracket, "]")?;
2098 k
2099 } else if matches!(
2100 self.current().map(|t| &t.kind),
2101 Some(TokenKind::StringLiteral(_))
2102 ) {
2103 let key_span = self.current_span();
2105 let name =
2106 if let Some(TokenKind::StringLiteral(s)) = self.current().map(|t| &t.kind) {
2107 s.clone()
2108 } else {
2109 unreachable!()
2110 };
2111 self.advance();
2112 spanned(Node::StringLiteral(name), key_span)
2113 } else {
2114 let key_span = self.current_span();
2116 let name = self.consume_identifier_or_keyword("dict key")?;
2117 spanned(Node::StringLiteral(name), key_span)
2118 };
2119 self.consume(&TokenKind::Colon, ":")?;
2120 let value = self.parse_expression()?;
2121 entries.push(DictEntry { key, value });
2122 self.skip_newlines();
2123 if self.check(&TokenKind::Comma) {
2124 self.advance();
2125 self.skip_newlines();
2126 }
2127 }
2128
2129 self.consume(&TokenKind::RBrace, "}")?;
2130 Ok(entries)
2131 }
2132
2133 fn parse_param_list(&mut self) -> Result<Vec<String>, ParserError> {
2137 let mut params = Vec::new();
2138 self.skip_newlines();
2139
2140 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2141 params.push(self.consume_identifier("parameter name")?);
2142 if self.check(&TokenKind::Comma) {
2143 self.advance();
2144 self.skip_newlines();
2145 }
2146 }
2147 Ok(params)
2148 }
2149
2150 fn parse_typed_param_list(&mut self) -> Result<Vec<TypedParam>, ParserError> {
2152 self.parse_typed_params_until(|tok| tok == &TokenKind::RParen)
2153 }
2154
2155 fn parse_typed_params_until(
2158 &mut self,
2159 is_terminator: impl Fn(&TokenKind) -> bool,
2160 ) -> Result<Vec<TypedParam>, ParserError> {
2161 let mut params = Vec::new();
2162 let mut seen_default = false;
2163 self.skip_newlines();
2164
2165 while !self.is_at_end() {
2166 if let Some(tok) = self.current() {
2167 if is_terminator(&tok.kind) {
2168 break;
2169 }
2170 } else {
2171 break;
2172 }
2173 let is_rest = if self.check(&TokenKind::Dot) {
2175 let p1 = self.pos + 1;
2177 let p2 = self.pos + 2;
2178 let is_ellipsis = p1 < self.tokens.len()
2179 && p2 < self.tokens.len()
2180 && self.tokens[p1].kind == TokenKind::Dot
2181 && self.tokens[p2].kind == TokenKind::Dot;
2182 if is_ellipsis {
2183 self.advance(); self.advance(); self.advance(); true
2187 } else {
2188 false
2189 }
2190 } else {
2191 false
2192 };
2193 let name = self.consume_identifier("parameter name")?;
2194 let type_expr = self.try_parse_type_annotation()?;
2195 let default_value = if self.check(&TokenKind::Assign) {
2196 self.advance();
2197 seen_default = true;
2198 Some(Box::new(self.parse_expression()?))
2199 } else {
2200 if seen_default && !is_rest {
2201 return Err(self.error(
2202 "Required parameter cannot follow a parameter with a default value",
2203 ));
2204 }
2205 None
2206 };
2207 if is_rest
2208 && !is_terminator(
2209 &self
2210 .current()
2211 .map(|t| t.kind.clone())
2212 .unwrap_or(TokenKind::Eof),
2213 )
2214 {
2215 return Err(self.error("Rest parameter must be the last parameter"));
2216 }
2217 params.push(TypedParam {
2218 name,
2219 type_expr,
2220 default_value,
2221 rest: is_rest,
2222 });
2223 if self.check(&TokenKind::Comma) {
2224 self.advance();
2225 self.skip_newlines();
2226 }
2227 }
2228 Ok(params)
2229 }
2230
2231 fn parse_type_param_list(&mut self) -> Result<Vec<TypeParam>, ParserError> {
2233 let mut params = Vec::new();
2234 self.skip_newlines();
2235 while !self.is_at_end() && !self.check(&TokenKind::Gt) {
2236 let name = self.consume_identifier("type parameter name")?;
2237 params.push(TypeParam { name });
2238 if self.check(&TokenKind::Comma) {
2239 self.advance();
2240 self.skip_newlines();
2241 }
2242 }
2243 self.consume(&TokenKind::Gt, ">")?;
2244 Ok(params)
2245 }
2246
2247 fn parse_where_clauses(&mut self) -> Result<Vec<WhereClause>, ParserError> {
2250 if let Some(tok) = self.current() {
2252 if let TokenKind::Identifier(ref id) = tok.kind {
2253 if id == "where" {
2254 self.advance(); let mut clauses = Vec::new();
2256 loop {
2257 self.skip_newlines();
2258 if self.check(&TokenKind::LBrace) || self.is_at_end() {
2260 break;
2261 }
2262 let type_name = self.consume_identifier("type parameter name")?;
2263 self.consume(&TokenKind::Colon, ":")?;
2264 let bound = self.consume_identifier("type bound")?;
2265 clauses.push(WhereClause { type_name, bound });
2266 if self.check(&TokenKind::Comma) {
2267 self.advance();
2268 } else {
2269 break;
2270 }
2271 }
2272 return Ok(clauses);
2273 }
2274 }
2275 }
2276 Ok(Vec::new())
2277 }
2278
2279 fn try_parse_type_annotation(&mut self) -> Result<Option<TypeExpr>, ParserError> {
2282 if !self.check(&TokenKind::Colon) {
2283 return Ok(None);
2284 }
2285 self.advance(); Ok(Some(self.parse_type_expr()?))
2287 }
2288
2289 fn parse_type_expr(&mut self) -> Result<TypeExpr, ParserError> {
2291 self.skip_newlines();
2292 let first = self.parse_type_primary()?;
2293
2294 if self.check(&TokenKind::Bar) {
2296 let mut types = vec![first];
2297 while self.check(&TokenKind::Bar) {
2298 self.advance(); types.push(self.parse_type_primary()?);
2300 }
2301 return Ok(TypeExpr::Union(types));
2302 }
2303
2304 Ok(first)
2305 }
2306
2307 fn parse_type_primary(&mut self) -> Result<TypeExpr, ParserError> {
2310 self.skip_newlines();
2311 if self.check(&TokenKind::LBrace) {
2312 return self.parse_shape_type();
2313 }
2314 if let Some(tok) = self.current() {
2316 let type_name = match &tok.kind {
2317 TokenKind::Nil => {
2318 self.advance();
2319 return Ok(TypeExpr::Named("nil".to_string()));
2320 }
2321 TokenKind::True | TokenKind::False => {
2322 self.advance();
2323 return Ok(TypeExpr::Named("bool".to_string()));
2324 }
2325 _ => None,
2326 };
2327 if let Some(name) = type_name {
2328 return Ok(TypeExpr::Named(name));
2329 }
2330 }
2331 if self.check(&TokenKind::Fn) {
2333 self.advance(); self.consume(&TokenKind::LParen, "(")?;
2335 let mut params = Vec::new();
2336 self.skip_newlines();
2337 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2338 params.push(self.parse_type_expr()?);
2339 self.skip_newlines();
2340 if self.check(&TokenKind::Comma) {
2341 self.advance();
2342 self.skip_newlines();
2343 }
2344 }
2345 self.consume(&TokenKind::RParen, ")")?;
2346 self.consume(&TokenKind::Arrow, "->")?;
2347 let return_type = self.parse_type_expr()?;
2348 return Ok(TypeExpr::FnType {
2349 params,
2350 return_type: Box::new(return_type),
2351 });
2352 }
2353 let name = self.consume_identifier("type name")?;
2354 if name == "never" {
2356 return Ok(TypeExpr::Never);
2357 }
2358 if self.check(&TokenKind::Lt) {
2360 self.advance(); let mut type_args = vec![self.parse_type_expr()?];
2362 while self.check(&TokenKind::Comma) {
2363 self.advance();
2364 type_args.push(self.parse_type_expr()?);
2365 }
2366 self.consume(&TokenKind::Gt, ">")?;
2367 if name == "list" && type_args.len() == 1 {
2368 return Ok(TypeExpr::List(Box::new(type_args.remove(0))));
2369 } else if name == "dict" && type_args.len() == 2 {
2370 return Ok(TypeExpr::DictType(
2371 Box::new(type_args.remove(0)),
2372 Box::new(type_args.remove(0)),
2373 ));
2374 }
2375 return Ok(TypeExpr::Applied {
2376 name,
2377 args: type_args,
2378 });
2379 }
2380 Ok(TypeExpr::Named(name))
2381 }
2382
2383 fn parse_shape_type(&mut self) -> Result<TypeExpr, ParserError> {
2385 self.consume(&TokenKind::LBrace, "{")?;
2386 let mut fields = Vec::new();
2387 self.skip_newlines();
2388
2389 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
2390 let name = self.consume_identifier("field name")?;
2391 let optional = if self.check(&TokenKind::Question) {
2392 self.advance();
2393 true
2394 } else {
2395 false
2396 };
2397 self.consume(&TokenKind::Colon, ":")?;
2398 let type_expr = self.parse_type_expr()?;
2399 fields.push(ShapeField {
2400 name,
2401 type_expr,
2402 optional,
2403 });
2404 self.skip_newlines();
2405 if self.check(&TokenKind::Comma) {
2406 self.advance();
2407 self.skip_newlines();
2408 }
2409 }
2410
2411 self.consume(&TokenKind::RBrace, "}")?;
2412 Ok(TypeExpr::Shape(fields))
2413 }
2414
2415 fn parse_arg_list(&mut self) -> Result<Vec<SNode>, ParserError> {
2416 let mut args = Vec::new();
2417 self.skip_newlines();
2418
2419 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2420 if self.check(&TokenKind::Dot) {
2422 let saved_pos = self.pos;
2423 self.advance(); if self.check(&TokenKind::Dot) {
2425 self.advance(); self.consume(&TokenKind::Dot, ".")?; let spread_start = self.tokens[saved_pos].span;
2428 let expr = self.parse_expression()?;
2429 args.push(spanned(
2430 Node::Spread(Box::new(expr)),
2431 Span::merge(spread_start, self.prev_span()),
2432 ));
2433 } else {
2434 self.pos = saved_pos;
2436 args.push(self.parse_expression()?);
2437 }
2438 } else {
2439 args.push(self.parse_expression()?);
2440 }
2441 self.skip_newlines();
2442 if self.check(&TokenKind::Comma) {
2443 self.advance();
2444 self.skip_newlines();
2445 }
2446 }
2447 Ok(args)
2448 }
2449
2450 fn is_at_end(&self) -> bool {
2451 self.pos >= self.tokens.len()
2452 || matches!(self.tokens.get(self.pos), Some(t) if t.kind == TokenKind::Eof)
2453 }
2454
2455 fn current(&self) -> Option<&Token> {
2456 self.tokens.get(self.pos)
2457 }
2458
2459 fn peek_kind(&self) -> Option<&TokenKind> {
2460 self.tokens.get(self.pos + 1).map(|t| &t.kind)
2461 }
2462
2463 fn check(&self, kind: &TokenKind) -> bool {
2464 self.current()
2465 .map(|t| std::mem::discriminant(&t.kind) == std::mem::discriminant(kind))
2466 .unwrap_or(false)
2467 }
2468
2469 fn check_skip_newlines(&mut self, kind: &TokenKind) -> bool {
2472 let saved = self.pos;
2473 self.skip_newlines();
2474 if self.check(kind) {
2475 true
2476 } else {
2477 self.pos = saved;
2478 false
2479 }
2480 }
2481
2482 fn check_identifier(&self, name: &str) -> bool {
2484 matches!(self.current().map(|t| &t.kind), Some(TokenKind::Identifier(s)) if s == name)
2485 }
2486
2487 fn advance(&mut self) {
2488 if self.pos < self.tokens.len() {
2489 self.pos += 1;
2490 }
2491 }
2492
2493 fn consume(&mut self, kind: &TokenKind, expected: &str) -> Result<Token, ParserError> {
2494 self.skip_newlines();
2495 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2496 if std::mem::discriminant(&tok.kind) != std::mem::discriminant(kind) {
2497 return Err(self.make_error(expected));
2498 }
2499 let tok = tok.clone();
2500 self.advance();
2501 Ok(tok)
2502 }
2503
2504 fn consume_identifier(&mut self, expected: &str) -> Result<String, ParserError> {
2505 self.skip_newlines();
2506 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2507 if let TokenKind::Identifier(name) = &tok.kind {
2508 let name = name.clone();
2509 self.advance();
2510 Ok(name)
2511 } else {
2512 let kw_name = harn_lexer::KEYWORDS
2515 .iter()
2516 .find(|&&kw| kw == tok.kind.to_string());
2517 if let Some(kw) = kw_name {
2518 Err(ParserError::Unexpected {
2519 got: format!("'{kw}' (reserved keyword)"),
2520 expected: expected.into(),
2521 span: tok.span,
2522 })
2523 } else {
2524 Err(self.make_error(expected))
2525 }
2526 }
2527 }
2528
2529 fn consume_identifier_or_keyword(&mut self, expected: &str) -> Result<String, ParserError> {
2533 self.skip_newlines();
2534 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2535 if let TokenKind::Identifier(name) = &tok.kind {
2536 let name = name.clone();
2537 self.advance();
2538 return Ok(name);
2539 }
2540 let name = match &tok.kind {
2542 TokenKind::Pipeline => "pipeline",
2543 TokenKind::Extends => "extends",
2544 TokenKind::Override => "override",
2545 TokenKind::Let => "let",
2546 TokenKind::Var => "var",
2547 TokenKind::If => "if",
2548 TokenKind::Else => "else",
2549 TokenKind::For => "for",
2550 TokenKind::In => "in",
2551 TokenKind::Match => "match",
2552 TokenKind::Retry => "retry",
2553 TokenKind::Parallel => "parallel",
2554 TokenKind::Return => "return",
2555 TokenKind::Import => "import",
2556 TokenKind::True => "true",
2557 TokenKind::False => "false",
2558 TokenKind::Nil => "nil",
2559 TokenKind::Try => "try",
2560 TokenKind::Catch => "catch",
2561 TokenKind::Throw => "throw",
2562 TokenKind::Fn => "fn",
2563 TokenKind::Spawn => "spawn",
2564 TokenKind::While => "while",
2565 TokenKind::TypeKw => "type",
2566 TokenKind::Enum => "enum",
2567 TokenKind::Struct => "struct",
2568 TokenKind::Interface => "interface",
2569 TokenKind::Pub => "pub",
2570 TokenKind::From => "from",
2571 TokenKind::Thru => "thru",
2572 TokenKind::Tool => "tool",
2573 TokenKind::Upto => "upto",
2574 TokenKind::Guard => "guard",
2575 TokenKind::Deadline => "deadline",
2576 TokenKind::Defer => "defer",
2577 TokenKind::Yield => "yield",
2578 TokenKind::Mutex => "mutex",
2579 TokenKind::Break => "break",
2580 TokenKind::Continue => "continue",
2581 TokenKind::Impl => "impl",
2582 _ => return Err(self.make_error(expected)),
2583 };
2584 let name = name.to_string();
2585 self.advance();
2586 Ok(name)
2587 }
2588
2589 fn skip_newlines(&mut self) {
2590 while self.pos < self.tokens.len() && self.tokens[self.pos].kind == TokenKind::Newline {
2591 self.pos += 1;
2592 }
2593 }
2594
2595 fn make_error(&self, expected: &str) -> ParserError {
2596 if let Some(tok) = self.tokens.get(self.pos) {
2597 if tok.kind == TokenKind::Eof {
2598 return ParserError::UnexpectedEof {
2599 expected: expected.into(),
2600 span: tok.span,
2601 };
2602 }
2603 ParserError::Unexpected {
2604 got: tok.kind.to_string(),
2605 expected: expected.into(),
2606 span: tok.span,
2607 }
2608 } else {
2609 ParserError::UnexpectedEof {
2610 expected: expected.into(),
2611 span: self.prev_span(),
2612 }
2613 }
2614 }
2615
2616 fn error(&self, expected: &str) -> ParserError {
2617 self.make_error(expected)
2618 }
2619}
2620
2621#[cfg(test)]
2622mod tests {
2623 use super::*;
2624 use harn_lexer::Lexer;
2625
2626 fn parse_source(source: &str) -> Result<Vec<SNode>, ParserError> {
2627 let mut lexer = Lexer::new(source);
2628 let tokens = lexer.tokenize().unwrap();
2629 let mut parser = Parser::new(tokens);
2630 parser.parse()
2631 }
2632
2633 #[test]
2634 fn parses_match_expression_with_let_in_arm_body() {
2635 let source = r#"
2636pipeline p() {
2637 let x = match 1 {
2638 1 -> {
2639 let a = 1
2640 a
2641 }
2642 _ -> { 0 }
2643 }
2644}
2645"#;
2646
2647 assert!(parse_source(source).is_ok());
2648 }
2649
2650 #[test]
2651 fn parses_public_declarations_and_generic_interfaces() {
2652 let source = r#"
2653pub pipeline build(task) extends base {
2654 return
2655}
2656
2657pub enum Result {
2658 Ok(value: string),
2659 Err(message: string, code: int),
2660}
2661
2662pub struct Config {
2663 host: string
2664 port?: int
2665}
2666
2667interface Repository<T> {
2668 type Item
2669 fn get(id: string) -> T
2670 fn map<U>(value: T, f: fn(T) -> U) -> U
2671}
2672"#;
2673
2674 let program = parse_source(source).expect("should parse");
2675 assert!(matches!(
2676 &program[0].node,
2677 Node::Pipeline {
2678 is_pub: true,
2679 extends: Some(base),
2680 ..
2681 } if base == "base"
2682 ));
2683 assert!(matches!(
2684 &program[1].node,
2685 Node::EnumDecl {
2686 is_pub: true,
2687 type_params,
2688 ..
2689 } if type_params.is_empty()
2690 ));
2691 assert!(matches!(
2692 &program[2].node,
2693 Node::StructDecl {
2694 is_pub: true,
2695 type_params,
2696 ..
2697 } if type_params.is_empty()
2698 ));
2699 assert!(matches!(
2700 &program[3].node,
2701 Node::InterfaceDecl {
2702 type_params,
2703 associated_types,
2704 methods,
2705 ..
2706 }
2707 if type_params.len() == 1
2708 && associated_types.len() == 1
2709 && methods.len() == 2
2710 && methods[1].type_params.len() == 1
2711 ));
2712 }
2713
2714 #[test]
2715 fn parses_generic_structs_and_enums() {
2716 let source = r#"
2717struct Pair<A, B> {
2718 first: A
2719 second: B
2720}
2721
2722enum Option<T> {
2723 Some(value: T)
2724 None
2725}
2726"#;
2727
2728 let program = parse_source(source).expect("should parse");
2729 assert!(matches!(
2730 &program[0].node,
2731 Node::StructDecl { type_params, .. } if type_params.len() == 2
2732 ));
2733 assert!(matches!(
2734 &program[1].node,
2735 Node::EnumDecl { type_params, .. } if type_params.len() == 1
2736 ));
2737 }
2738
2739 #[test]
2740 fn parses_struct_literal_syntax_for_known_structs() {
2741 let source = r#"
2742struct Point {
2743 x: int
2744 y: int
2745}
2746
2747pipeline test(task) {
2748 let point = Point { x: 3, y: 4 }
2749}
2750"#;
2751
2752 let program = parse_source(source).expect("should parse");
2753 let pipeline = program
2754 .iter()
2755 .find(|node| matches!(node.node, Node::Pipeline { .. }))
2756 .expect("pipeline node");
2757 let body = match &pipeline.node {
2758 Node::Pipeline { body, .. } => body,
2759 _ => unreachable!(),
2760 };
2761 assert!(matches!(
2762 &body[0].node,
2763 Node::LetBinding { value, .. }
2764 if matches!(
2765 value.node,
2766 Node::StructConstruct { ref struct_name, ref fields }
2767 if struct_name == "Point" && fields.len() == 2
2768 )
2769 ));
2770 }
2771
2772 #[test]
2773 fn parses_exponentiation_as_right_associative() {
2774 let mut lexer = Lexer::new("a ** b ** c");
2775 let tokens = lexer.tokenize().expect("tokens");
2776 let mut parser = Parser::new(tokens);
2777 let expr = parser.parse_single_expression().expect("expression");
2778
2779 assert!(matches!(
2780 expr.node,
2781 Node::BinaryOp { ref op, ref left, ref right }
2782 if op == "**"
2783 && matches!(left.node, Node::Identifier(ref name) if name == "a")
2784 && matches!(
2785 right.node,
2786 Node::BinaryOp { ref op, ref left, ref right }
2787 if op == "**"
2788 && matches!(left.node, Node::Identifier(ref name) if name == "b")
2789 && matches!(right.node, Node::Identifier(ref name) if name == "c")
2790 )
2791 ));
2792 }
2793
2794 #[test]
2795 fn parses_exponentiation_tighter_than_multiplication() {
2796 let mut lexer = Lexer::new("a * b ** c");
2797 let tokens = lexer.tokenize().expect("tokens");
2798 let mut parser = Parser::new(tokens);
2799 let expr = parser.parse_single_expression().expect("expression");
2800
2801 assert!(matches!(
2802 expr.node,
2803 Node::BinaryOp { ref op, ref left, ref right }
2804 if op == "*"
2805 && matches!(left.node, Node::Identifier(ref name) if name == "a")
2806 && matches!(
2807 right.node,
2808 Node::BinaryOp { ref op, ref left, ref right }
2809 if op == "**"
2810 && matches!(left.node, Node::Identifier(ref name) if name == "b")
2811 && matches!(right.node, Node::Identifier(ref name) if name == "c")
2812 )
2813 ));
2814 }
2815}