1use crate::ast::*;
2use harn_lexer::{Span, Token, TokenKind};
3use std::fmt;
4
5#[derive(Debug, Clone, PartialEq)]
7pub enum ParserError {
8 Unexpected {
9 got: String,
10 expected: String,
11 span: Span,
12 },
13 UnexpectedEof {
14 expected: String,
15 span: Span,
16 },
17}
18
19impl fmt::Display for ParserError {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 match self {
22 ParserError::Unexpected {
23 got,
24 expected,
25 span,
26 } => write!(
27 f,
28 "Expected {expected}, got {got} at {}:{}",
29 span.line, span.column
30 ),
31 ParserError::UnexpectedEof { expected, .. } => {
32 write!(f, "Unexpected end of file, expected {expected}")
33 }
34 }
35 }
36}
37
38impl std::error::Error for ParserError {}
39
40pub struct Parser {
42 tokens: Vec<Token>,
43 pos: usize,
44 errors: Vec<ParserError>,
45}
46
47impl Parser {
48 pub fn new(tokens: Vec<Token>) -> Self {
49 Self {
50 tokens,
51 pos: 0,
52 errors: Vec::new(),
53 }
54 }
55
56 fn current_span(&self) -> Span {
57 self.tokens
58 .get(self.pos)
59 .map(|t| t.span)
60 .unwrap_or(Span::dummy())
61 }
62
63 fn current_kind(&self) -> Option<&TokenKind> {
64 self.tokens.get(self.pos).map(|t| &t.kind)
65 }
66
67 fn prev_span(&self) -> Span {
68 if self.pos > 0 {
69 self.tokens[self.pos - 1].span
70 } else {
71 Span::dummy()
72 }
73 }
74
75 pub fn parse(&mut self) -> Result<Vec<SNode>, ParserError> {
77 let mut nodes = Vec::new();
78 self.skip_newlines();
79
80 while !self.is_at_end() {
81 if self.check(&TokenKind::RBrace) {
83 self.advance();
84 self.skip_newlines();
85 continue;
86 }
87
88 let result = if self.check(&TokenKind::Import) {
89 self.parse_import()
90 } else if self.check(&TokenKind::Pipeline) {
91 self.parse_pipeline()
92 } else {
93 self.parse_statement()
94 };
95
96 match result {
97 Ok(node) => nodes.push(node),
98 Err(err) => {
99 self.errors.push(err);
100 self.synchronize();
101 }
102 }
103 self.skip_newlines();
104 }
105
106 if let Some(first) = self.errors.first() {
107 return Err(first.clone());
108 }
109 Ok(nodes)
110 }
111
112 pub fn all_errors(&self) -> &[ParserError] {
114 &self.errors
115 }
116
117 fn is_statement_start(&self) -> bool {
119 matches!(
120 self.current_kind(),
121 Some(
122 TokenKind::Let
123 | TokenKind::Var
124 | TokenKind::If
125 | TokenKind::For
126 | TokenKind::While
127 | TokenKind::Match
128 | TokenKind::Retry
129 | TokenKind::Return
130 | TokenKind::Throw
131 | TokenKind::Fn
132 | TokenKind::Pub
133 | TokenKind::Try
134 | TokenKind::Select
135 | TokenKind::Pipeline
136 | TokenKind::Import
137 | TokenKind::Parallel
138 | TokenKind::ParallelMap
139 | TokenKind::ParallelSettle
140 | TokenKind::Enum
141 | TokenKind::Struct
142 | TokenKind::Interface
143 | TokenKind::Guard
144 | TokenKind::Require
145 | TokenKind::Deadline
146 | TokenKind::Yield
147 | TokenKind::Mutex
148 | TokenKind::Tool
149 )
150 )
151 }
152
153 fn synchronize(&mut self) {
155 while !self.is_at_end() {
156 if self.check(&TokenKind::Newline) {
157 self.advance();
158 if self.is_at_end() || self.is_statement_start() {
159 return;
160 }
161 continue;
162 }
163 if self.check(&TokenKind::RBrace) {
164 return;
165 }
166 self.advance();
167 }
168 }
169
170 pub fn parse_single_expression(&mut self) -> Result<SNode, ParserError> {
172 self.skip_newlines();
173 self.parse_expression()
174 }
175
176 fn parse_pipeline_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
179 let start = self.current_span();
180 self.consume(&TokenKind::Pipeline, "pipeline")?;
181 let name = self.consume_identifier("pipeline name")?;
182
183 self.consume(&TokenKind::LParen, "(")?;
184 let params = self.parse_param_list()?;
185 self.consume(&TokenKind::RParen, ")")?;
186
187 let extends = if self.check(&TokenKind::Extends) {
188 self.advance();
189 Some(self.consume_identifier("parent pipeline name")?)
190 } else {
191 None
192 };
193
194 self.consume(&TokenKind::LBrace, "{")?;
195 let body = self.parse_block()?;
196 self.consume(&TokenKind::RBrace, "}")?;
197
198 Ok(spanned(
199 Node::Pipeline {
200 name,
201 params,
202 body,
203 extends,
204 is_pub,
205 },
206 Span::merge(start, self.prev_span()),
207 ))
208 }
209
210 fn parse_pipeline(&mut self) -> Result<SNode, ParserError> {
211 self.parse_pipeline_with_pub(false)
212 }
213
214 fn parse_import(&mut self) -> Result<SNode, ParserError> {
215 let start = self.current_span();
216 self.consume(&TokenKind::Import, "import")?;
217
218 if self.check(&TokenKind::LBrace) {
220 self.advance(); self.skip_newlines();
222 let mut names = Vec::new();
223 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
224 let name = self.consume_identifier("import name")?;
225 names.push(name);
226 self.skip_newlines();
227 if self.check(&TokenKind::Comma) {
228 self.advance();
229 self.skip_newlines();
230 }
231 }
232 self.consume(&TokenKind::RBrace, "}")?;
233 self.consume(&TokenKind::From, "from")?;
234 if let Some(tok) = self.current() {
235 if let TokenKind::StringLiteral(path) = &tok.kind {
236 let path = path.clone();
237 self.advance();
238 return Ok(spanned(
239 Node::SelectiveImport { names, path },
240 Span::merge(start, self.prev_span()),
241 ));
242 }
243 }
244 return Err(self.error("import path string"));
245 }
246
247 if let Some(tok) = self.current() {
248 if let TokenKind::StringLiteral(path) = &tok.kind {
249 let path = path.clone();
250 self.advance();
251 return Ok(spanned(
252 Node::ImportDecl { path },
253 Span::merge(start, self.prev_span()),
254 ));
255 }
256 }
257 Err(self.error("import path string"))
258 }
259
260 fn parse_block(&mut self) -> Result<Vec<SNode>, ParserError> {
263 let mut stmts = Vec::new();
264 self.skip_newlines();
265
266 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
267 stmts.push(self.parse_statement()?);
268 self.skip_newlines();
269 }
270 Ok(stmts)
271 }
272
273 fn parse_statement(&mut self) -> Result<SNode, ParserError> {
274 self.skip_newlines();
275
276 let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
277 expected: "statement".into(),
278 span: self.prev_span(),
279 })?;
280
281 match &tok.kind {
282 TokenKind::Let => self.parse_let_binding(),
283 TokenKind::Var => self.parse_var_binding(),
284 TokenKind::If => self.parse_if_else(),
285 TokenKind::For => self.parse_for_in(),
286 TokenKind::Match => self.parse_match(),
287 TokenKind::Retry => self.parse_retry(),
288 TokenKind::While => self.parse_while_loop(),
289 TokenKind::Parallel => self.parse_parallel(),
290 TokenKind::ParallelMap => self.parse_parallel_map(),
291 TokenKind::ParallelSettle => self.parse_parallel_settle(),
292 TokenKind::Return => self.parse_return(),
293 TokenKind::Throw => self.parse_throw(),
294 TokenKind::Override => self.parse_override(),
295 TokenKind::Try => self.parse_try_catch(),
296 TokenKind::Select => self.parse_select(),
297 TokenKind::Fn => self.parse_fn_decl_with_pub(false),
298 TokenKind::Tool => self.parse_tool_decl(false),
299 TokenKind::Pub => {
300 self.advance(); let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
302 expected: "fn, struct, enum, or pipeline after pub".into(),
303 span: self.prev_span(),
304 })?;
305 match &tok.kind {
306 TokenKind::Fn => self.parse_fn_decl_with_pub(true),
307 TokenKind::Tool => self.parse_tool_decl(true),
308 TokenKind::Pipeline => self.parse_pipeline_with_pub(true),
309 TokenKind::Enum => self.parse_enum_decl_with_pub(true),
310 TokenKind::Struct => self.parse_struct_decl_with_pub(true),
311 _ => Err(self.error("fn, tool, struct, enum, or pipeline after pub")),
312 }
313 }
314 TokenKind::TypeKw => self.parse_type_decl(),
315 TokenKind::Enum => self.parse_enum_decl(),
316 TokenKind::Struct => self.parse_struct_decl(),
317 TokenKind::Interface => self.parse_interface_decl(),
318 TokenKind::Impl => self.parse_impl_block(),
319 TokenKind::Guard => self.parse_guard(),
320 TokenKind::Require => self.parse_require(),
321 TokenKind::Deadline => self.parse_deadline(),
322 TokenKind::Yield => self.parse_yield(),
323 TokenKind::Mutex => self.parse_mutex(),
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 self.consume(&TokenKind::Arrow, "->")?;
537 self.consume(&TokenKind::LBrace, "{")?;
538 let body = self.parse_block()?;
539 self.consume(&TokenKind::RBrace, "}")?;
540 arms.push(MatchArm { pattern, body });
541 self.skip_newlines();
542 }
543
544 self.consume(&TokenKind::RBrace, "}")?;
545 Ok(spanned(
546 Node::MatchExpr {
547 value: Box::new(value),
548 arms,
549 },
550 Span::merge(start, self.prev_span()),
551 ))
552 }
553
554 fn parse_while_loop(&mut self) -> Result<SNode, ParserError> {
555 let start = self.current_span();
556 self.consume(&TokenKind::While, "while")?;
557 let condition = if self.check(&TokenKind::LParen) {
558 self.advance();
559 let c = self.parse_expression()?;
560 self.consume(&TokenKind::RParen, ")")?;
561 c
562 } else {
563 self.parse_expression()?
564 };
565 self.consume(&TokenKind::LBrace, "{")?;
566 let body = self.parse_block()?;
567 self.consume(&TokenKind::RBrace, "}")?;
568 Ok(spanned(
569 Node::WhileLoop {
570 condition: Box::new(condition),
571 body,
572 },
573 Span::merge(start, self.prev_span()),
574 ))
575 }
576
577 fn parse_retry(&mut self) -> Result<SNode, ParserError> {
578 let start = self.current_span();
579 self.consume(&TokenKind::Retry, "retry")?;
580 let count = if self.check(&TokenKind::LParen) {
581 self.advance();
582 let c = self.parse_expression()?;
583 self.consume(&TokenKind::RParen, ")")?;
584 c
585 } else {
586 self.parse_primary()?
587 };
588 self.consume(&TokenKind::LBrace, "{")?;
589 let body = self.parse_block()?;
590 self.consume(&TokenKind::RBrace, "}")?;
591 Ok(spanned(
592 Node::Retry {
593 count: Box::new(count),
594 body,
595 },
596 Span::merge(start, self.prev_span()),
597 ))
598 }
599
600 fn parse_parallel(&mut self) -> Result<SNode, ParserError> {
601 let start = self.current_span();
602 self.consume(&TokenKind::Parallel, "parallel")?;
603 self.consume(&TokenKind::LParen, "(")?;
604 let count = self.parse_expression()?;
605 self.consume(&TokenKind::RParen, ")")?;
606 self.consume(&TokenKind::LBrace, "{")?;
607
608 let mut variable = None;
610 self.skip_newlines();
611 if let Some(tok) = self.current() {
612 if let TokenKind::Identifier(name) = &tok.kind {
613 if self.peek_kind() == Some(&TokenKind::Arrow) {
614 let name = name.clone();
615 self.advance(); self.advance(); variable = Some(name);
618 }
619 }
620 }
621
622 let body = self.parse_block()?;
623 self.consume(&TokenKind::RBrace, "}")?;
624 Ok(spanned(
625 Node::Parallel {
626 count: Box::new(count),
627 variable,
628 body,
629 },
630 Span::merge(start, self.prev_span()),
631 ))
632 }
633
634 fn parse_parallel_map(&mut self) -> Result<SNode, ParserError> {
635 let start = self.current_span();
636 self.consume(&TokenKind::ParallelMap, "parallel_map")?;
637 self.consume(&TokenKind::LParen, "(")?;
638 let list = self.parse_expression()?;
639 self.consume(&TokenKind::RParen, ")")?;
640 self.consume(&TokenKind::LBrace, "{")?;
641
642 self.skip_newlines();
643 let variable = self.consume_identifier("map variable")?;
644 self.consume(&TokenKind::Arrow, "->")?;
645
646 let body = self.parse_block()?;
647 self.consume(&TokenKind::RBrace, "}")?;
648 Ok(spanned(
649 Node::ParallelMap {
650 list: Box::new(list),
651 variable,
652 body,
653 },
654 Span::merge(start, self.prev_span()),
655 ))
656 }
657
658 fn parse_parallel_settle(&mut self) -> Result<SNode, ParserError> {
659 let start = self.current_span();
660 self.consume(&TokenKind::ParallelSettle, "parallel_settle")?;
661 self.consume(&TokenKind::LParen, "(")?;
662 let list = self.parse_expression()?;
663 self.consume(&TokenKind::RParen, ")")?;
664 self.consume(&TokenKind::LBrace, "{")?;
665
666 self.skip_newlines();
667 let variable = self.consume_identifier("settle variable")?;
668 self.consume(&TokenKind::Arrow, "->")?;
669
670 let body = self.parse_block()?;
671 self.consume(&TokenKind::RBrace, "}")?;
672 Ok(spanned(
673 Node::ParallelSettle {
674 list: Box::new(list),
675 variable,
676 body,
677 },
678 Span::merge(start, self.prev_span()),
679 ))
680 }
681
682 fn parse_return(&mut self) -> Result<SNode, ParserError> {
683 let start = self.current_span();
684 self.consume(&TokenKind::Return, "return")?;
685 if self.is_at_end() || self.check(&TokenKind::Newline) || self.check(&TokenKind::RBrace) {
686 return Ok(spanned(
687 Node::ReturnStmt { value: None },
688 Span::merge(start, self.prev_span()),
689 ));
690 }
691 let value = self.parse_expression()?;
692 Ok(spanned(
693 Node::ReturnStmt {
694 value: Some(Box::new(value)),
695 },
696 Span::merge(start, self.prev_span()),
697 ))
698 }
699
700 fn parse_throw(&mut self) -> Result<SNode, ParserError> {
701 let start = self.current_span();
702 self.consume(&TokenKind::Throw, "throw")?;
703 let value = self.parse_expression()?;
704 Ok(spanned(
705 Node::ThrowStmt {
706 value: Box::new(value),
707 },
708 Span::merge(start, self.prev_span()),
709 ))
710 }
711
712 fn parse_override(&mut self) -> Result<SNode, ParserError> {
713 let start = self.current_span();
714 self.consume(&TokenKind::Override, "override")?;
715 let name = self.consume_identifier("override name")?;
716 self.consume(&TokenKind::LParen, "(")?;
717 let params = self.parse_param_list()?;
718 self.consume(&TokenKind::RParen, ")")?;
719 self.consume(&TokenKind::LBrace, "{")?;
720 let body = self.parse_block()?;
721 self.consume(&TokenKind::RBrace, "}")?;
722 Ok(spanned(
723 Node::OverrideDecl { name, params, body },
724 Span::merge(start, self.prev_span()),
725 ))
726 }
727
728 fn parse_try_catch(&mut self) -> Result<SNode, ParserError> {
729 let start = self.current_span();
730 self.consume(&TokenKind::Try, "try")?;
731 self.consume(&TokenKind::LBrace, "{")?;
732 let body = self.parse_block()?;
733 self.consume(&TokenKind::RBrace, "}")?;
734 self.skip_newlines();
735
736 let has_catch = self.check(&TokenKind::Catch);
738 let (error_var, error_type, catch_body) = if has_catch {
739 self.advance();
740 let (ev, et) = if self.check(&TokenKind::LParen) {
741 self.advance();
743 let name = self.consume_identifier("error variable")?;
744 let ty = self.try_parse_type_annotation()?;
745 self.consume(&TokenKind::RParen, ")")?;
746 (Some(name), ty)
747 } else if matches!(
748 self.current().map(|t| &t.kind),
749 Some(TokenKind::Identifier(_))
750 ) {
751 let name = self.consume_identifier("error variable")?;
753 (Some(name), None)
754 } else {
755 (None, None)
756 };
757 self.consume(&TokenKind::LBrace, "{")?;
758 let cb = self.parse_block()?;
759 self.consume(&TokenKind::RBrace, "}")?;
760 (ev, et, cb)
761 } else {
762 (None, None, Vec::new())
763 };
764
765 self.skip_newlines();
766
767 let finally_body = if self.check(&TokenKind::Finally) {
769 self.advance();
770 self.consume(&TokenKind::LBrace, "{")?;
771 let fb = self.parse_block()?;
772 self.consume(&TokenKind::RBrace, "}")?;
773 Some(fb)
774 } else {
775 None
776 };
777
778 if !has_catch && finally_body.is_none() {
780 return Ok(spanned(
781 Node::TryExpr { body },
782 Span::merge(start, self.prev_span()),
783 ));
784 }
785
786 Ok(spanned(
787 Node::TryCatch {
788 body,
789 error_var,
790 error_type,
791 catch_body,
792 finally_body,
793 },
794 Span::merge(start, self.prev_span()),
795 ))
796 }
797
798 fn parse_select(&mut self) -> Result<SNode, ParserError> {
799 let start = self.current_span();
800 self.consume(&TokenKind::Select, "select")?;
801 self.consume(&TokenKind::LBrace, "{")?;
802 self.skip_newlines();
803
804 let mut cases = Vec::new();
805 let mut timeout = None;
806 let mut default_body = None;
807
808 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
809 self.skip_newlines();
810 if let Some(tok) = self.current() {
812 if let TokenKind::Identifier(ref id) = tok.kind {
813 if id == "timeout" {
814 self.advance();
815 let duration = self.parse_expression()?;
816 self.consume(&TokenKind::LBrace, "{")?;
817 let body = self.parse_block()?;
818 self.consume(&TokenKind::RBrace, "}")?;
819 timeout = Some((Box::new(duration), body));
820 self.skip_newlines();
821 continue;
822 }
823 if id == "default" {
824 self.advance();
825 self.consume(&TokenKind::LBrace, "{")?;
826 let body = self.parse_block()?;
827 self.consume(&TokenKind::RBrace, "}")?;
828 default_body = Some(body);
829 self.skip_newlines();
830 continue;
831 }
832 }
833 }
834 let variable = self.consume_identifier("select case variable")?;
836 self.consume(&TokenKind::From, "from")?;
837 let channel = self.parse_expression()?;
838 self.consume(&TokenKind::LBrace, "{")?;
839 let body = self.parse_block()?;
840 self.consume(&TokenKind::RBrace, "}")?;
841 cases.push(SelectCase {
842 variable,
843 channel: Box::new(channel),
844 body,
845 });
846 self.skip_newlines();
847 }
848
849 self.consume(&TokenKind::RBrace, "}")?;
850
851 if cases.is_empty() && timeout.is_none() && default_body.is_none() {
852 return Err(self.error("at least one select case"));
853 }
854 if timeout.is_some() && default_body.is_some() {
855 return Err(self.error("select cannot have both timeout and default"));
856 }
857
858 Ok(spanned(
859 Node::SelectExpr {
860 cases,
861 timeout,
862 default_body,
863 },
864 Span::merge(start, self.prev_span()),
865 ))
866 }
867
868 fn parse_fn_decl_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
869 let start = self.current_span();
870 self.consume(&TokenKind::Fn, "fn")?;
871 let name = self.consume_identifier("function name")?;
872
873 let type_params = if self.check(&TokenKind::Lt) {
875 self.advance(); self.parse_type_param_list()?
877 } else {
878 Vec::new()
879 };
880
881 self.consume(&TokenKind::LParen, "(")?;
882 let params = self.parse_typed_param_list()?;
883 self.consume(&TokenKind::RParen, ")")?;
884 let return_type = if self.check(&TokenKind::Arrow) {
886 self.advance();
887 Some(self.parse_type_expr()?)
888 } else {
889 None
890 };
891
892 let where_clauses = self.parse_where_clauses()?;
894
895 self.consume(&TokenKind::LBrace, "{")?;
896 let body = self.parse_block()?;
897 self.consume(&TokenKind::RBrace, "}")?;
898 Ok(spanned(
899 Node::FnDecl {
900 name,
901 type_params,
902 params,
903 return_type,
904 where_clauses,
905 body,
906 is_pub,
907 },
908 Span::merge(start, self.prev_span()),
909 ))
910 }
911
912 fn parse_tool_decl(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
913 let start = self.current_span();
914 self.consume(&TokenKind::Tool, "tool")?;
915 let name = self.consume_identifier("tool name")?;
916
917 self.consume(&TokenKind::LParen, "(")?;
918 let params = self.parse_typed_param_list()?;
919 self.consume(&TokenKind::RParen, ")")?;
920
921 let return_type = if self.check(&TokenKind::Arrow) {
923 self.advance();
924 Some(self.parse_type_expr()?)
925 } else {
926 None
927 };
928
929 self.consume(&TokenKind::LBrace, "{")?;
930
931 self.skip_newlines();
933 let mut description = None;
934 if let Some(TokenKind::Identifier(id)) = self.current_kind().cloned() {
935 if id == "description" {
936 let saved_pos = self.pos;
938 self.advance(); self.skip_newlines();
940 if let Some(TokenKind::StringLiteral(s)) = self.current_kind().cloned() {
941 description = Some(s);
942 self.advance(); } else {
944 self.pos = saved_pos;
946 }
947 }
948 }
949
950 let body = self.parse_block()?;
951 self.consume(&TokenKind::RBrace, "}")?;
952
953 Ok(spanned(
954 Node::ToolDecl {
955 name,
956 description,
957 params,
958 return_type,
959 body,
960 is_pub,
961 },
962 Span::merge(start, self.prev_span()),
963 ))
964 }
965
966 fn parse_type_decl(&mut self) -> Result<SNode, ParserError> {
967 let start = self.current_span();
968 self.consume(&TokenKind::TypeKw, "type")?;
969 let name = self.consume_identifier("type name")?;
970 self.consume(&TokenKind::Assign, "=")?;
971 let type_expr = self.parse_type_expr()?;
972 Ok(spanned(
973 Node::TypeDecl { name, type_expr },
974 Span::merge(start, self.prev_span()),
975 ))
976 }
977
978 fn parse_enum_decl_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
979 let start = self.current_span();
980 self.consume(&TokenKind::Enum, "enum")?;
981 let name = self.consume_identifier("enum name")?;
982 self.consume(&TokenKind::LBrace, "{")?;
983 self.skip_newlines();
984
985 let mut variants = Vec::new();
986 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
987 let variant_name = self.consume_identifier("variant name")?;
988 let fields = if self.check(&TokenKind::LParen) {
989 self.advance();
990 let params = self.parse_typed_param_list()?;
991 self.consume(&TokenKind::RParen, ")")?;
992 params
993 } else {
994 Vec::new()
995 };
996 variants.push(EnumVariant {
997 name: variant_name,
998 fields,
999 });
1000 self.skip_newlines();
1001 if self.check(&TokenKind::Comma) {
1002 self.advance();
1003 self.skip_newlines();
1004 }
1005 }
1006
1007 self.consume(&TokenKind::RBrace, "}")?;
1008 Ok(spanned(
1009 Node::EnumDecl {
1010 name,
1011 variants,
1012 is_pub,
1013 },
1014 Span::merge(start, self.prev_span()),
1015 ))
1016 }
1017
1018 fn parse_enum_decl(&mut self) -> Result<SNode, ParserError> {
1019 self.parse_enum_decl_with_pub(false)
1020 }
1021
1022 fn parse_struct_decl_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
1023 let start = self.current_span();
1024 self.consume(&TokenKind::Struct, "struct")?;
1025 let name = self.consume_identifier("struct name")?;
1026 self.consume(&TokenKind::LBrace, "{")?;
1027 self.skip_newlines();
1028
1029 let mut fields = Vec::new();
1030 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1031 let field_name = self.consume_identifier("field name")?;
1032 let optional = if self.check(&TokenKind::Question) {
1033 self.advance();
1034 true
1035 } else {
1036 false
1037 };
1038 let type_expr = self.try_parse_type_annotation()?;
1039 fields.push(StructField {
1040 name: field_name,
1041 type_expr,
1042 optional,
1043 });
1044 self.skip_newlines();
1045 if self.check(&TokenKind::Comma) {
1046 self.advance();
1047 self.skip_newlines();
1048 }
1049 }
1050
1051 self.consume(&TokenKind::RBrace, "}")?;
1052 Ok(spanned(
1053 Node::StructDecl {
1054 name,
1055 fields,
1056 is_pub,
1057 },
1058 Span::merge(start, self.prev_span()),
1059 ))
1060 }
1061
1062 fn parse_struct_decl(&mut self) -> Result<SNode, ParserError> {
1063 self.parse_struct_decl_with_pub(false)
1064 }
1065
1066 fn parse_interface_decl(&mut self) -> Result<SNode, ParserError> {
1067 let start = self.current_span();
1068 self.consume(&TokenKind::Interface, "interface")?;
1069 let name = self.consume_identifier("interface name")?;
1070 let type_params = if self.check(&TokenKind::Lt) {
1071 self.advance();
1072 self.parse_type_param_list()?
1073 } else {
1074 Vec::new()
1075 };
1076 self.consume(&TokenKind::LBrace, "{")?;
1077 self.skip_newlines();
1078
1079 let mut methods = Vec::new();
1080 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1081 self.consume(&TokenKind::Fn, "fn")?;
1082 let method_name = self.consume_identifier("method name")?;
1083 let method_type_params = if self.check(&TokenKind::Lt) {
1084 self.advance();
1085 self.parse_type_param_list()?
1086 } else {
1087 Vec::new()
1088 };
1089 self.consume(&TokenKind::LParen, "(")?;
1090 let params = self.parse_typed_param_list()?;
1091 self.consume(&TokenKind::RParen, ")")?;
1092 let return_type = if self.check(&TokenKind::Arrow) {
1094 self.advance();
1095 Some(self.parse_type_expr()?)
1096 } else {
1097 None
1098 };
1099 methods.push(InterfaceMethod {
1100 name: method_name,
1101 type_params: method_type_params,
1102 params,
1103 return_type,
1104 });
1105 self.skip_newlines();
1106 }
1107
1108 self.consume(&TokenKind::RBrace, "}")?;
1109 Ok(spanned(
1110 Node::InterfaceDecl {
1111 name,
1112 type_params,
1113 methods,
1114 },
1115 Span::merge(start, self.prev_span()),
1116 ))
1117 }
1118
1119 fn parse_impl_block(&mut self) -> Result<SNode, ParserError> {
1120 let start = self.current_span();
1121 self.consume(&TokenKind::Impl, "impl")?;
1122 let type_name = self.consume_identifier("type name")?;
1123 self.consume(&TokenKind::LBrace, "{")?;
1124 self.skip_newlines();
1125
1126 let mut methods = Vec::new();
1127 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1128 let is_pub = self.check(&TokenKind::Pub);
1129 if is_pub {
1130 self.advance();
1131 }
1132 let method = self.parse_fn_decl_with_pub(is_pub)?;
1133 methods.push(method);
1134 self.skip_newlines();
1135 }
1136
1137 self.consume(&TokenKind::RBrace, "}")?;
1138 Ok(spanned(
1139 Node::ImplBlock { type_name, methods },
1140 Span::merge(start, self.prev_span()),
1141 ))
1142 }
1143
1144 fn parse_guard(&mut self) -> Result<SNode, ParserError> {
1145 let start = self.current_span();
1146 self.consume(&TokenKind::Guard, "guard")?;
1147 let condition = self.parse_expression()?;
1148 self.consume(&TokenKind::Else, "else")?;
1150 self.consume(&TokenKind::LBrace, "{")?;
1151 let else_body = self.parse_block()?;
1152 self.consume(&TokenKind::RBrace, "}")?;
1153 Ok(spanned(
1154 Node::GuardStmt {
1155 condition: Box::new(condition),
1156 else_body,
1157 },
1158 Span::merge(start, self.prev_span()),
1159 ))
1160 }
1161
1162 fn parse_require(&mut self) -> Result<SNode, ParserError> {
1163 let start = self.current_span();
1164 self.consume(&TokenKind::Require, "require")?;
1165 let condition = self.parse_expression()?;
1166 let message = if self.check(&TokenKind::Comma) {
1167 self.advance();
1168 Some(Box::new(self.parse_expression()?))
1169 } else {
1170 None
1171 };
1172 Ok(spanned(
1173 Node::RequireStmt {
1174 condition: Box::new(condition),
1175 message,
1176 },
1177 Span::merge(start, self.prev_span()),
1178 ))
1179 }
1180
1181 fn parse_deadline(&mut self) -> Result<SNode, ParserError> {
1182 let start = self.current_span();
1183 self.consume(&TokenKind::Deadline, "deadline")?;
1184 let duration = self.parse_primary()?;
1185 self.consume(&TokenKind::LBrace, "{")?;
1186 let body = self.parse_block()?;
1187 self.consume(&TokenKind::RBrace, "}")?;
1188 Ok(spanned(
1189 Node::DeadlineBlock {
1190 duration: Box::new(duration),
1191 body,
1192 },
1193 Span::merge(start, self.prev_span()),
1194 ))
1195 }
1196
1197 fn parse_yield(&mut self) -> Result<SNode, ParserError> {
1198 let start = self.current_span();
1199 self.consume(&TokenKind::Yield, "yield")?;
1200 if self.is_at_end() || self.check(&TokenKind::Newline) || self.check(&TokenKind::RBrace) {
1201 return Ok(spanned(
1202 Node::YieldExpr { value: None },
1203 Span::merge(start, self.prev_span()),
1204 ));
1205 }
1206 let value = self.parse_expression()?;
1207 Ok(spanned(
1208 Node::YieldExpr {
1209 value: Some(Box::new(value)),
1210 },
1211 Span::merge(start, self.prev_span()),
1212 ))
1213 }
1214
1215 fn parse_mutex(&mut self) -> Result<SNode, ParserError> {
1216 let start = self.current_span();
1217 self.consume(&TokenKind::Mutex, "mutex")?;
1218 self.consume(&TokenKind::LBrace, "{")?;
1219 let body = self.parse_block()?;
1220 self.consume(&TokenKind::RBrace, "}")?;
1221 Ok(spanned(
1222 Node::MutexBlock { body },
1223 Span::merge(start, self.prev_span()),
1224 ))
1225 }
1226
1227 fn parse_ask_expr(&mut self) -> Result<SNode, ParserError> {
1228 let start = self.current_span();
1229 self.consume(&TokenKind::Ask, "ask")?;
1230 self.consume(&TokenKind::LBrace, "{")?;
1231 let mut entries = Vec::new();
1233 self.skip_newlines();
1234 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1235 let key_span = self.current_span();
1236 let name = self.consume_identifier("ask field")?;
1237 let key = spanned(Node::StringLiteral(name), key_span);
1238 self.consume(&TokenKind::Colon, ":")?;
1239 let value = self.parse_expression()?;
1240 entries.push(DictEntry { key, value });
1241 self.skip_newlines();
1242 if self.check(&TokenKind::Comma) {
1243 self.advance();
1244 self.skip_newlines();
1245 }
1246 }
1247 self.consume(&TokenKind::RBrace, "}")?;
1248 Ok(spanned(
1249 Node::AskExpr { fields: entries },
1250 Span::merge(start, self.prev_span()),
1251 ))
1252 }
1253
1254 fn parse_expression_statement(&mut self) -> Result<SNode, ParserError> {
1257 let start = self.current_span();
1258 let expr = self.parse_expression()?;
1259
1260 let is_assignable = matches!(
1263 expr.node,
1264 Node::Identifier(_) | Node::PropertyAccess { .. } | Node::SubscriptAccess { .. }
1265 );
1266 if is_assignable {
1267 if self.check(&TokenKind::Assign) {
1268 self.advance();
1269 let value = self.parse_expression()?;
1270 return Ok(spanned(
1271 Node::Assignment {
1272 target: Box::new(expr),
1273 value: Box::new(value),
1274 op: None,
1275 },
1276 Span::merge(start, self.prev_span()),
1277 ));
1278 }
1279 let compound_op = if self.check(&TokenKind::PlusAssign) {
1280 Some("+")
1281 } else if self.check(&TokenKind::MinusAssign) {
1282 Some("-")
1283 } else if self.check(&TokenKind::StarAssign) {
1284 Some("*")
1285 } else if self.check(&TokenKind::SlashAssign) {
1286 Some("/")
1287 } else if self.check(&TokenKind::PercentAssign) {
1288 Some("%")
1289 } else {
1290 None
1291 };
1292 if let Some(op) = compound_op {
1293 self.advance();
1294 let value = self.parse_expression()?;
1295 return Ok(spanned(
1296 Node::Assignment {
1297 target: Box::new(expr),
1298 value: Box::new(value),
1299 op: Some(op.into()),
1300 },
1301 Span::merge(start, self.prev_span()),
1302 ));
1303 }
1304 }
1305
1306 Ok(expr)
1307 }
1308
1309 fn parse_expression(&mut self) -> Result<SNode, ParserError> {
1310 self.skip_newlines();
1311 self.parse_pipe()
1312 }
1313
1314 fn parse_pipe(&mut self) -> Result<SNode, ParserError> {
1315 let mut left = self.parse_range()?;
1316 while self.check_skip_newlines(&TokenKind::Pipe) {
1317 let start = left.span;
1318 self.advance();
1319 let right = self.parse_range()?;
1320 left = spanned(
1321 Node::BinaryOp {
1322 op: "|>".into(),
1323 left: Box::new(left),
1324 right: Box::new(right),
1325 },
1326 Span::merge(start, self.prev_span()),
1327 );
1328 }
1329 Ok(left)
1330 }
1331
1332 fn parse_range(&mut self) -> Result<SNode, ParserError> {
1333 let left = self.parse_ternary()?;
1334 if self.check(&TokenKind::Thru) {
1335 let start = left.span;
1336 self.advance();
1337 let right = self.parse_ternary()?;
1338 return Ok(spanned(
1339 Node::RangeExpr {
1340 start: Box::new(left),
1341 end: Box::new(right),
1342 inclusive: true,
1343 },
1344 Span::merge(start, self.prev_span()),
1345 ));
1346 }
1347 if self.check(&TokenKind::Upto) {
1348 let start = left.span;
1349 self.advance();
1350 let right = self.parse_ternary()?;
1351 return Ok(spanned(
1352 Node::RangeExpr {
1353 start: Box::new(left),
1354 end: Box::new(right),
1355 inclusive: false,
1356 },
1357 Span::merge(start, self.prev_span()),
1358 ));
1359 }
1360 Ok(left)
1361 }
1362
1363 fn parse_ternary(&mut self) -> Result<SNode, ParserError> {
1364 let condition = self.parse_logical_or()?;
1365 if !self.check(&TokenKind::Question) {
1366 return Ok(condition);
1367 }
1368 let start = condition.span;
1369 self.advance(); let true_val = self.parse_logical_or()?;
1371 self.consume(&TokenKind::Colon, ":")?;
1372 let false_val = self.parse_logical_or()?;
1373 Ok(spanned(
1374 Node::Ternary {
1375 condition: Box::new(condition),
1376 true_expr: Box::new(true_val),
1377 false_expr: Box::new(false_val),
1378 },
1379 Span::merge(start, self.prev_span()),
1380 ))
1381 }
1382
1383 fn parse_nil_coalescing(&mut self) -> Result<SNode, ParserError> {
1391 let mut left = self.parse_multiplicative()?;
1392 while self.check(&TokenKind::NilCoal) {
1393 let start = left.span;
1394 self.advance();
1395 let right = self.parse_multiplicative()?;
1396 left = spanned(
1397 Node::BinaryOp {
1398 op: "??".into(),
1399 left: Box::new(left),
1400 right: Box::new(right),
1401 },
1402 Span::merge(start, self.prev_span()),
1403 );
1404 }
1405 Ok(left)
1406 }
1407
1408 fn parse_logical_or(&mut self) -> Result<SNode, ParserError> {
1409 let mut left = self.parse_logical_and()?;
1410 while self.check_skip_newlines(&TokenKind::Or) {
1411 let start = left.span;
1412 self.advance();
1413 let right = self.parse_logical_and()?;
1414 left = spanned(
1415 Node::BinaryOp {
1416 op: "||".into(),
1417 left: Box::new(left),
1418 right: Box::new(right),
1419 },
1420 Span::merge(start, self.prev_span()),
1421 );
1422 }
1423 Ok(left)
1424 }
1425
1426 fn parse_logical_and(&mut self) -> Result<SNode, ParserError> {
1427 let mut left = self.parse_equality()?;
1428 while self.check_skip_newlines(&TokenKind::And) {
1429 let start = left.span;
1430 self.advance();
1431 let right = self.parse_equality()?;
1432 left = spanned(
1433 Node::BinaryOp {
1434 op: "&&".into(),
1435 left: Box::new(left),
1436 right: Box::new(right),
1437 },
1438 Span::merge(start, self.prev_span()),
1439 );
1440 }
1441 Ok(left)
1442 }
1443
1444 fn parse_equality(&mut self) -> Result<SNode, ParserError> {
1445 let mut left = self.parse_comparison()?;
1446 while self.check(&TokenKind::Eq) || self.check(&TokenKind::Neq) {
1447 let start = left.span;
1448 let op = if self.check(&TokenKind::Eq) {
1449 "=="
1450 } else {
1451 "!="
1452 };
1453 self.advance();
1454 let right = self.parse_comparison()?;
1455 left = spanned(
1456 Node::BinaryOp {
1457 op: op.into(),
1458 left: Box::new(left),
1459 right: Box::new(right),
1460 },
1461 Span::merge(start, self.prev_span()),
1462 );
1463 }
1464 Ok(left)
1465 }
1466
1467 fn parse_comparison(&mut self) -> Result<SNode, ParserError> {
1468 let mut left = self.parse_additive()?;
1469 loop {
1470 if self.check(&TokenKind::Lt)
1471 || self.check(&TokenKind::Gt)
1472 || self.check(&TokenKind::Lte)
1473 || self.check(&TokenKind::Gte)
1474 {
1475 let start = left.span;
1476 let op = match self.current().map(|t| &t.kind) {
1477 Some(TokenKind::Lt) => "<",
1478 Some(TokenKind::Gt) => ">",
1479 Some(TokenKind::Lte) => "<=",
1480 Some(TokenKind::Gte) => ">=",
1481 _ => "<",
1482 };
1483 self.advance();
1484 let right = self.parse_additive()?;
1485 left = spanned(
1486 Node::BinaryOp {
1487 op: op.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(&TokenKind::In) {
1494 let start = left.span;
1495 self.advance();
1496 let right = self.parse_additive()?;
1497 left = spanned(
1498 Node::BinaryOp {
1499 op: "in".into(),
1500 left: Box::new(left),
1501 right: Box::new(right),
1502 },
1503 Span::merge(start, self.prev_span()),
1504 );
1505 } else if self.check_identifier("not") {
1506 let saved = self.pos;
1508 self.advance(); if self.check(&TokenKind::In) {
1510 let start = left.span;
1511 self.advance(); let right = self.parse_additive()?;
1513 left = spanned(
1514 Node::BinaryOp {
1515 op: "not_in".into(),
1516 left: Box::new(left),
1517 right: Box::new(right),
1518 },
1519 Span::merge(start, self.prev_span()),
1520 );
1521 } else {
1522 self.pos = saved;
1523 break;
1524 }
1525 } else {
1526 break;
1527 }
1528 }
1529 Ok(left)
1530 }
1531
1532 fn parse_additive(&mut self) -> Result<SNode, ParserError> {
1533 let mut left = self.parse_nil_coalescing()?;
1534 while self.check_skip_newlines(&TokenKind::Plus) || self.check(&TokenKind::Minus) {
1535 let start = left.span;
1536 let op = if self.check(&TokenKind::Plus) {
1537 "+"
1538 } else {
1539 "-"
1540 };
1541 self.advance();
1542 let right = self.parse_nil_coalescing()?;
1543 left = spanned(
1544 Node::BinaryOp {
1545 op: op.into(),
1546 left: Box::new(left),
1547 right: Box::new(right),
1548 },
1549 Span::merge(start, self.prev_span()),
1550 );
1551 }
1552 Ok(left)
1553 }
1554
1555 fn parse_multiplicative(&mut self) -> Result<SNode, ParserError> {
1556 let mut left = self.parse_unary()?;
1557 while self.check_skip_newlines(&TokenKind::Star)
1558 || self.check_skip_newlines(&TokenKind::Slash)
1559 || self.check_skip_newlines(&TokenKind::Percent)
1560 {
1561 let start = left.span;
1562 let op = if self.check(&TokenKind::Star) {
1563 "*"
1564 } else if self.check(&TokenKind::Slash) {
1565 "/"
1566 } else {
1567 "%"
1568 };
1569 self.advance();
1570 let right = self.parse_unary()?;
1571 left = spanned(
1572 Node::BinaryOp {
1573 op: op.into(),
1574 left: Box::new(left),
1575 right: Box::new(right),
1576 },
1577 Span::merge(start, self.prev_span()),
1578 );
1579 }
1580 Ok(left)
1581 }
1582
1583 fn parse_unary(&mut self) -> Result<SNode, ParserError> {
1584 if self.check(&TokenKind::Not) {
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 if self.check(&TokenKind::Minus) {
1597 let start = self.current_span();
1598 self.advance();
1599 let operand = self.parse_unary()?;
1600 return Ok(spanned(
1601 Node::UnaryOp {
1602 op: "-".into(),
1603 operand: Box::new(operand),
1604 },
1605 Span::merge(start, self.prev_span()),
1606 ));
1607 }
1608 self.parse_postfix()
1609 }
1610
1611 fn parse_postfix(&mut self) -> Result<SNode, ParserError> {
1612 let mut expr = self.parse_primary()?;
1613
1614 loop {
1615 if self.check_skip_newlines(&TokenKind::Dot)
1616 || self.check_skip_newlines(&TokenKind::QuestionDot)
1617 {
1618 let optional = self.check(&TokenKind::QuestionDot);
1619 let start = expr.span;
1620 self.advance();
1621 let member = self.consume_identifier_or_keyword("member name")?;
1622 if self.check(&TokenKind::LParen) {
1623 self.advance();
1624 let args = self.parse_arg_list()?;
1625 self.consume(&TokenKind::RParen, ")")?;
1626 if optional {
1627 expr = spanned(
1628 Node::OptionalMethodCall {
1629 object: Box::new(expr),
1630 method: member,
1631 args,
1632 },
1633 Span::merge(start, self.prev_span()),
1634 );
1635 } else {
1636 expr = spanned(
1637 Node::MethodCall {
1638 object: Box::new(expr),
1639 method: member,
1640 args,
1641 },
1642 Span::merge(start, self.prev_span()),
1643 );
1644 }
1645 } else if optional {
1646 expr = spanned(
1647 Node::OptionalPropertyAccess {
1648 object: Box::new(expr),
1649 property: member,
1650 },
1651 Span::merge(start, self.prev_span()),
1652 );
1653 } else {
1654 expr = spanned(
1655 Node::PropertyAccess {
1656 object: Box::new(expr),
1657 property: member,
1658 },
1659 Span::merge(start, self.prev_span()),
1660 );
1661 }
1662 } else if self.check(&TokenKind::LBracket) {
1663 let start = expr.span;
1664 self.advance();
1665
1666 if self.check(&TokenKind::Colon) {
1671 self.advance(); let end_expr = if self.check(&TokenKind::RBracket) {
1674 None
1675 } else {
1676 Some(Box::new(self.parse_expression()?))
1677 };
1678 self.consume(&TokenKind::RBracket, "]")?;
1679 expr = spanned(
1680 Node::SliceAccess {
1681 object: Box::new(expr),
1682 start: None,
1683 end: end_expr,
1684 },
1685 Span::merge(start, self.prev_span()),
1686 );
1687 } else {
1688 let index = self.parse_expression()?;
1689 if self.check(&TokenKind::Colon) {
1690 self.advance(); let end_expr = if self.check(&TokenKind::RBracket) {
1693 None
1694 } else {
1695 Some(Box::new(self.parse_expression()?))
1696 };
1697 self.consume(&TokenKind::RBracket, "]")?;
1698 expr = spanned(
1699 Node::SliceAccess {
1700 object: Box::new(expr),
1701 start: Some(Box::new(index)),
1702 end: end_expr,
1703 },
1704 Span::merge(start, self.prev_span()),
1705 );
1706 } else {
1707 self.consume(&TokenKind::RBracket, "]")?;
1708 expr = spanned(
1709 Node::SubscriptAccess {
1710 object: Box::new(expr),
1711 index: Box::new(index),
1712 },
1713 Span::merge(start, self.prev_span()),
1714 );
1715 }
1716 }
1717 } else if self.check(&TokenKind::LParen) && matches!(expr.node, Node::Identifier(_)) {
1718 let start = expr.span;
1719 self.advance();
1720 let args = self.parse_arg_list()?;
1721 self.consume(&TokenKind::RParen, ")")?;
1722 if let Node::Identifier(name) = expr.node {
1723 expr = spanned(
1724 Node::FunctionCall { name, args },
1725 Span::merge(start, self.prev_span()),
1726 );
1727 }
1728 } else if self.check(&TokenKind::Question) {
1729 let next_pos = self.pos + 1;
1732 let is_ternary = self.tokens.get(next_pos).is_some_and(|t| {
1733 matches!(
1734 t.kind,
1735 TokenKind::Identifier(_)
1736 | TokenKind::IntLiteral(_)
1737 | TokenKind::FloatLiteral(_)
1738 | TokenKind::StringLiteral(_)
1739 | TokenKind::InterpolatedString(_)
1740 | TokenKind::True
1741 | TokenKind::False
1742 | TokenKind::Nil
1743 | TokenKind::LParen
1744 | TokenKind::LBracket
1745 | TokenKind::LBrace
1746 | TokenKind::Not
1747 | TokenKind::Minus
1748 | TokenKind::Fn
1749 )
1750 });
1751 if is_ternary {
1752 break;
1753 }
1754 let start = expr.span;
1755 self.advance(); expr = spanned(
1757 Node::TryOperator {
1758 operand: Box::new(expr),
1759 },
1760 Span::merge(start, self.prev_span()),
1761 );
1762 } else {
1763 break;
1764 }
1765 }
1766
1767 Ok(expr)
1768 }
1769
1770 fn parse_primary(&mut self) -> Result<SNode, ParserError> {
1771 let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
1772 expected: "expression".into(),
1773 span: self.prev_span(),
1774 })?;
1775 let start = self.current_span();
1776
1777 match &tok.kind {
1778 TokenKind::StringLiteral(s) => {
1779 let s = s.clone();
1780 self.advance();
1781 Ok(spanned(
1782 Node::StringLiteral(s),
1783 Span::merge(start, self.prev_span()),
1784 ))
1785 }
1786 TokenKind::RawStringLiteral(s) => {
1787 let s = s.clone();
1788 self.advance();
1789 Ok(spanned(
1790 Node::RawStringLiteral(s),
1791 Span::merge(start, self.prev_span()),
1792 ))
1793 }
1794 TokenKind::InterpolatedString(segments) => {
1795 let segments = segments.clone();
1796 self.advance();
1797 Ok(spanned(
1798 Node::InterpolatedString(segments),
1799 Span::merge(start, self.prev_span()),
1800 ))
1801 }
1802 TokenKind::IntLiteral(n) => {
1803 let n = *n;
1804 self.advance();
1805 Ok(spanned(
1806 Node::IntLiteral(n),
1807 Span::merge(start, self.prev_span()),
1808 ))
1809 }
1810 TokenKind::FloatLiteral(n) => {
1811 let n = *n;
1812 self.advance();
1813 Ok(spanned(
1814 Node::FloatLiteral(n),
1815 Span::merge(start, self.prev_span()),
1816 ))
1817 }
1818 TokenKind::True => {
1819 self.advance();
1820 Ok(spanned(
1821 Node::BoolLiteral(true),
1822 Span::merge(start, self.prev_span()),
1823 ))
1824 }
1825 TokenKind::False => {
1826 self.advance();
1827 Ok(spanned(
1828 Node::BoolLiteral(false),
1829 Span::merge(start, self.prev_span()),
1830 ))
1831 }
1832 TokenKind::Nil => {
1833 self.advance();
1834 Ok(spanned(
1835 Node::NilLiteral,
1836 Span::merge(start, self.prev_span()),
1837 ))
1838 }
1839 TokenKind::Identifier(name) => {
1840 let name = name.clone();
1841 self.advance();
1842 Ok(spanned(
1843 Node::Identifier(name),
1844 Span::merge(start, self.prev_span()),
1845 ))
1846 }
1847 TokenKind::LParen => {
1848 self.advance();
1849 let expr = self.parse_expression()?;
1850 self.consume(&TokenKind::RParen, ")")?;
1851 Ok(expr)
1852 }
1853 TokenKind::LBracket => self.parse_list_literal(),
1854 TokenKind::LBrace => self.parse_dict_or_closure(),
1855 TokenKind::Parallel => self.parse_parallel(),
1856 TokenKind::ParallelMap => self.parse_parallel_map(),
1857 TokenKind::ParallelSettle => self.parse_parallel_settle(),
1858 TokenKind::Retry => self.parse_retry(),
1859 TokenKind::If => self.parse_if_else(),
1860 TokenKind::Spawn => self.parse_spawn_expr(),
1861 TokenKind::DurationLiteral(ms) => {
1862 let ms = *ms;
1863 self.advance();
1864 Ok(spanned(
1865 Node::DurationLiteral(ms),
1866 Span::merge(start, self.prev_span()),
1867 ))
1868 }
1869 TokenKind::Ask => self.parse_ask_expr(),
1870 TokenKind::Deadline => self.parse_deadline(),
1871 TokenKind::Try => self.parse_try_catch(),
1872 TokenKind::Match => self.parse_match(),
1873 TokenKind::Fn => self.parse_fn_expr(),
1874 _ => Err(self.error("expression")),
1875 }
1876 }
1877
1878 fn parse_fn_expr(&mut self) -> Result<SNode, ParserError> {
1882 let start = self.current_span();
1883 self.consume(&TokenKind::Fn, "fn")?;
1884 self.consume(&TokenKind::LParen, "(")?;
1885 let params = self.parse_typed_param_list()?;
1886 self.consume(&TokenKind::RParen, ")")?;
1887 self.consume(&TokenKind::LBrace, "{")?;
1888 let body = self.parse_block()?;
1889 self.consume(&TokenKind::RBrace, "}")?;
1890 Ok(spanned(
1891 Node::Closure {
1892 params,
1893 body,
1894 fn_syntax: true,
1895 },
1896 Span::merge(start, self.prev_span()),
1897 ))
1898 }
1899
1900 fn parse_spawn_expr(&mut self) -> Result<SNode, ParserError> {
1901 let start = self.current_span();
1902 self.consume(&TokenKind::Spawn, "spawn")?;
1903 self.consume(&TokenKind::LBrace, "{")?;
1904 let body = self.parse_block()?;
1905 self.consume(&TokenKind::RBrace, "}")?;
1906 Ok(spanned(
1907 Node::SpawnExpr { body },
1908 Span::merge(start, self.prev_span()),
1909 ))
1910 }
1911
1912 fn parse_list_literal(&mut self) -> Result<SNode, ParserError> {
1913 let start = self.current_span();
1914 self.consume(&TokenKind::LBracket, "[")?;
1915 let mut elements = Vec::new();
1916 self.skip_newlines();
1917
1918 while !self.is_at_end() && !self.check(&TokenKind::RBracket) {
1919 if self.check(&TokenKind::Dot) {
1921 let saved_pos = self.pos;
1922 self.advance(); if self.check(&TokenKind::Dot) {
1924 self.advance(); self.consume(&TokenKind::Dot, ".")?; let spread_start = self.tokens[saved_pos].span;
1927 let expr = self.parse_expression()?;
1928 elements.push(spanned(
1929 Node::Spread(Box::new(expr)),
1930 Span::merge(spread_start, self.prev_span()),
1931 ));
1932 } else {
1933 self.pos = saved_pos;
1935 elements.push(self.parse_expression()?);
1936 }
1937 } else {
1938 elements.push(self.parse_expression()?);
1939 }
1940 self.skip_newlines();
1941 if self.check(&TokenKind::Comma) {
1942 self.advance();
1943 self.skip_newlines();
1944 }
1945 }
1946
1947 self.consume(&TokenKind::RBracket, "]")?;
1948 Ok(spanned(
1949 Node::ListLiteral(elements),
1950 Span::merge(start, self.prev_span()),
1951 ))
1952 }
1953
1954 fn parse_dict_or_closure(&mut self) -> Result<SNode, ParserError> {
1955 let start = self.current_span();
1956 self.consume(&TokenKind::LBrace, "{")?;
1957 self.skip_newlines();
1958
1959 if self.check(&TokenKind::RBrace) {
1961 self.advance();
1962 return Ok(spanned(
1963 Node::DictLiteral(Vec::new()),
1964 Span::merge(start, self.prev_span()),
1965 ));
1966 }
1967
1968 let saved = self.pos;
1970 if self.is_closure_lookahead() {
1971 self.pos = saved;
1972 return self.parse_closure_body(start);
1973 }
1974 self.pos = saved;
1975 self.parse_dict_literal(start)
1976 }
1977
1978 fn is_closure_lookahead(&mut self) -> bool {
1981 let mut depth = 0;
1982 while !self.is_at_end() {
1983 if let Some(tok) = self.current() {
1984 match &tok.kind {
1985 TokenKind::Arrow if depth == 0 => return true,
1986 TokenKind::LBrace | TokenKind::LParen | TokenKind::LBracket => depth += 1,
1987 TokenKind::RBrace if depth == 0 => return false,
1988 TokenKind::RBrace => depth -= 1,
1989 TokenKind::RParen | TokenKind::RBracket => {
1990 if depth > 0 {
1991 depth -= 1;
1992 }
1993 }
1994 _ => {}
1995 }
1996 self.advance();
1997 } else {
1998 return false;
1999 }
2000 }
2001 false
2002 }
2003
2004 fn parse_closure_body(&mut self, start: Span) -> Result<SNode, ParserError> {
2006 let params = self.parse_typed_param_list_until_arrow()?;
2007 self.consume(&TokenKind::Arrow, "->")?;
2008 let body = self.parse_block()?;
2009 self.consume(&TokenKind::RBrace, "}")?;
2010 Ok(spanned(
2011 Node::Closure {
2012 params,
2013 body,
2014 fn_syntax: false,
2015 },
2016 Span::merge(start, self.prev_span()),
2017 ))
2018 }
2019
2020 fn parse_typed_param_list_until_arrow(&mut self) -> Result<Vec<TypedParam>, ParserError> {
2022 self.parse_typed_params_until(|tok| tok == &TokenKind::Arrow)
2023 }
2024
2025 fn parse_dict_literal(&mut self, start: Span) -> Result<SNode, ParserError> {
2026 let mut entries = Vec::new();
2027 self.skip_newlines();
2028
2029 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
2030 if self.check(&TokenKind::Dot) {
2032 let saved_pos = self.pos;
2033 self.advance(); if self.check(&TokenKind::Dot) {
2035 self.advance(); if self.check(&TokenKind::Dot) {
2037 self.advance(); let spread_start = self.tokens[saved_pos].span;
2039 let expr = self.parse_expression()?;
2040 entries.push(DictEntry {
2041 key: spanned(Node::NilLiteral, spread_start),
2042 value: spanned(
2043 Node::Spread(Box::new(expr)),
2044 Span::merge(spread_start, self.prev_span()),
2045 ),
2046 });
2047 self.skip_newlines();
2048 if self.check(&TokenKind::Comma) {
2049 self.advance();
2050 self.skip_newlines();
2051 }
2052 continue;
2053 }
2054 self.pos = saved_pos;
2056 } else {
2057 self.pos = saved_pos;
2058 }
2059 }
2060 let key = if self.check(&TokenKind::LBracket) {
2061 self.advance();
2063 let k = self.parse_expression()?;
2064 self.consume(&TokenKind::RBracket, "]")?;
2065 k
2066 } else if matches!(
2067 self.current().map(|t| &t.kind),
2068 Some(TokenKind::StringLiteral(_))
2069 ) {
2070 let key_span = self.current_span();
2072 let name =
2073 if let Some(TokenKind::StringLiteral(s)) = self.current().map(|t| &t.kind) {
2074 s.clone()
2075 } else {
2076 unreachable!()
2077 };
2078 self.advance();
2079 spanned(Node::StringLiteral(name), key_span)
2080 } else {
2081 let key_span = self.current_span();
2083 let name = self.consume_identifier_or_keyword("dict key")?;
2084 spanned(Node::StringLiteral(name), key_span)
2085 };
2086 self.consume(&TokenKind::Colon, ":")?;
2087 let value = self.parse_expression()?;
2088 entries.push(DictEntry { key, value });
2089 self.skip_newlines();
2090 if self.check(&TokenKind::Comma) {
2091 self.advance();
2092 self.skip_newlines();
2093 }
2094 }
2095
2096 self.consume(&TokenKind::RBrace, "}")?;
2097 Ok(spanned(
2098 Node::DictLiteral(entries),
2099 Span::merge(start, self.prev_span()),
2100 ))
2101 }
2102
2103 fn parse_param_list(&mut self) -> Result<Vec<String>, ParserError> {
2107 let mut params = Vec::new();
2108 self.skip_newlines();
2109
2110 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2111 params.push(self.consume_identifier("parameter name")?);
2112 if self.check(&TokenKind::Comma) {
2113 self.advance();
2114 self.skip_newlines();
2115 }
2116 }
2117 Ok(params)
2118 }
2119
2120 fn parse_typed_param_list(&mut self) -> Result<Vec<TypedParam>, ParserError> {
2122 self.parse_typed_params_until(|tok| tok == &TokenKind::RParen)
2123 }
2124
2125 fn parse_typed_params_until(
2128 &mut self,
2129 is_terminator: impl Fn(&TokenKind) -> bool,
2130 ) -> Result<Vec<TypedParam>, ParserError> {
2131 let mut params = Vec::new();
2132 let mut seen_default = false;
2133 self.skip_newlines();
2134
2135 while !self.is_at_end() {
2136 if let Some(tok) = self.current() {
2137 if is_terminator(&tok.kind) {
2138 break;
2139 }
2140 } else {
2141 break;
2142 }
2143 let is_rest = if self.check(&TokenKind::Dot) {
2145 let p1 = self.pos + 1;
2147 let p2 = self.pos + 2;
2148 let is_ellipsis = p1 < self.tokens.len()
2149 && p2 < self.tokens.len()
2150 && self.tokens[p1].kind == TokenKind::Dot
2151 && self.tokens[p2].kind == TokenKind::Dot;
2152 if is_ellipsis {
2153 self.advance(); self.advance(); self.advance(); true
2157 } else {
2158 false
2159 }
2160 } else {
2161 false
2162 };
2163 let name = self.consume_identifier("parameter name")?;
2164 let type_expr = self.try_parse_type_annotation()?;
2165 let default_value = if self.check(&TokenKind::Assign) {
2166 self.advance();
2167 seen_default = true;
2168 Some(Box::new(self.parse_expression()?))
2169 } else {
2170 if seen_default && !is_rest {
2171 return Err(self.error(
2172 "Required parameter cannot follow a parameter with a default value",
2173 ));
2174 }
2175 None
2176 };
2177 if is_rest
2178 && !is_terminator(
2179 &self
2180 .current()
2181 .map(|t| t.kind.clone())
2182 .unwrap_or(TokenKind::Eof),
2183 )
2184 {
2185 return Err(self.error("Rest parameter must be the last parameter"));
2186 }
2187 params.push(TypedParam {
2188 name,
2189 type_expr,
2190 default_value,
2191 rest: is_rest,
2192 });
2193 if self.check(&TokenKind::Comma) {
2194 self.advance();
2195 self.skip_newlines();
2196 }
2197 }
2198 Ok(params)
2199 }
2200
2201 fn parse_type_param_list(&mut self) -> Result<Vec<TypeParam>, ParserError> {
2203 let mut params = Vec::new();
2204 self.skip_newlines();
2205 while !self.is_at_end() && !self.check(&TokenKind::Gt) {
2206 let name = self.consume_identifier("type parameter name")?;
2207 params.push(TypeParam { name });
2208 if self.check(&TokenKind::Comma) {
2209 self.advance();
2210 self.skip_newlines();
2211 }
2212 }
2213 self.consume(&TokenKind::Gt, ">")?;
2214 Ok(params)
2215 }
2216
2217 fn parse_where_clauses(&mut self) -> Result<Vec<WhereClause>, ParserError> {
2220 if let Some(tok) = self.current() {
2222 if let TokenKind::Identifier(ref id) = tok.kind {
2223 if id == "where" {
2224 self.advance(); let mut clauses = Vec::new();
2226 loop {
2227 self.skip_newlines();
2228 if self.check(&TokenKind::LBrace) || self.is_at_end() {
2230 break;
2231 }
2232 let type_name = self.consume_identifier("type parameter name")?;
2233 self.consume(&TokenKind::Colon, ":")?;
2234 let bound = self.consume_identifier("type bound")?;
2235 clauses.push(WhereClause { type_name, bound });
2236 if self.check(&TokenKind::Comma) {
2237 self.advance();
2238 } else {
2239 break;
2240 }
2241 }
2242 return Ok(clauses);
2243 }
2244 }
2245 }
2246 Ok(Vec::new())
2247 }
2248
2249 fn try_parse_type_annotation(&mut self) -> Result<Option<TypeExpr>, ParserError> {
2252 if !self.check(&TokenKind::Colon) {
2253 return Ok(None);
2254 }
2255 self.advance(); Ok(Some(self.parse_type_expr()?))
2257 }
2258
2259 fn parse_type_expr(&mut self) -> Result<TypeExpr, ParserError> {
2261 self.skip_newlines();
2262 let first = self.parse_type_primary()?;
2263
2264 if self.check(&TokenKind::Bar) {
2266 let mut types = vec![first];
2267 while self.check(&TokenKind::Bar) {
2268 self.advance(); types.push(self.parse_type_primary()?);
2270 }
2271 return Ok(TypeExpr::Union(types));
2272 }
2273
2274 Ok(first)
2275 }
2276
2277 fn parse_type_primary(&mut self) -> Result<TypeExpr, ParserError> {
2280 self.skip_newlines();
2281 if self.check(&TokenKind::LBrace) {
2282 return self.parse_shape_type();
2283 }
2284 if let Some(tok) = self.current() {
2286 let type_name = match &tok.kind {
2287 TokenKind::Nil => {
2288 self.advance();
2289 return Ok(TypeExpr::Named("nil".to_string()));
2290 }
2291 TokenKind::True | TokenKind::False => {
2292 self.advance();
2293 return Ok(TypeExpr::Named("bool".to_string()));
2294 }
2295 _ => None,
2296 };
2297 if let Some(name) = type_name {
2298 return Ok(TypeExpr::Named(name));
2299 }
2300 }
2301 if self.check(&TokenKind::Fn) {
2303 self.advance(); self.consume(&TokenKind::LParen, "(")?;
2305 let mut params = Vec::new();
2306 self.skip_newlines();
2307 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2308 params.push(self.parse_type_expr()?);
2309 self.skip_newlines();
2310 if self.check(&TokenKind::Comma) {
2311 self.advance();
2312 self.skip_newlines();
2313 }
2314 }
2315 self.consume(&TokenKind::RParen, ")")?;
2316 self.consume(&TokenKind::Arrow, "->")?;
2317 let return_type = self.parse_type_expr()?;
2318 return Ok(TypeExpr::FnType {
2319 params,
2320 return_type: Box::new(return_type),
2321 });
2322 }
2323 let name = self.consume_identifier("type name")?;
2324 if name == "never" {
2326 return Ok(TypeExpr::Never);
2327 }
2328 if self.check(&TokenKind::Lt) {
2330 self.advance(); let first_param = self.parse_type_expr()?;
2332 if name == "list" {
2333 self.consume(&TokenKind::Gt, ">")?;
2334 return Ok(TypeExpr::List(Box::new(first_param)));
2335 } else if name == "dict" {
2336 self.consume(&TokenKind::Comma, ",")?;
2337 let second_param = self.parse_type_expr()?;
2338 self.consume(&TokenKind::Gt, ">")?;
2339 return Ok(TypeExpr::DictType(
2340 Box::new(first_param),
2341 Box::new(second_param),
2342 ));
2343 }
2344 self.consume(&TokenKind::Gt, ">")?;
2346 }
2347 Ok(TypeExpr::Named(name))
2348 }
2349
2350 fn parse_shape_type(&mut self) -> Result<TypeExpr, ParserError> {
2352 self.consume(&TokenKind::LBrace, "{")?;
2353 let mut fields = Vec::new();
2354 self.skip_newlines();
2355
2356 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
2357 let name = self.consume_identifier("field name")?;
2358 let optional = if self.check(&TokenKind::Question) {
2359 self.advance();
2360 true
2361 } else {
2362 false
2363 };
2364 self.consume(&TokenKind::Colon, ":")?;
2365 let type_expr = self.parse_type_expr()?;
2366 fields.push(ShapeField {
2367 name,
2368 type_expr,
2369 optional,
2370 });
2371 self.skip_newlines();
2372 if self.check(&TokenKind::Comma) {
2373 self.advance();
2374 self.skip_newlines();
2375 }
2376 }
2377
2378 self.consume(&TokenKind::RBrace, "}")?;
2379 Ok(TypeExpr::Shape(fields))
2380 }
2381
2382 fn parse_arg_list(&mut self) -> Result<Vec<SNode>, ParserError> {
2383 let mut args = Vec::new();
2384 self.skip_newlines();
2385
2386 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2387 if self.check(&TokenKind::Dot) {
2389 let saved_pos = self.pos;
2390 self.advance(); if self.check(&TokenKind::Dot) {
2392 self.advance(); self.consume(&TokenKind::Dot, ".")?; let spread_start = self.tokens[saved_pos].span;
2395 let expr = self.parse_expression()?;
2396 args.push(spanned(
2397 Node::Spread(Box::new(expr)),
2398 Span::merge(spread_start, self.prev_span()),
2399 ));
2400 } else {
2401 self.pos = saved_pos;
2403 args.push(self.parse_expression()?);
2404 }
2405 } else {
2406 args.push(self.parse_expression()?);
2407 }
2408 self.skip_newlines();
2409 if self.check(&TokenKind::Comma) {
2410 self.advance();
2411 self.skip_newlines();
2412 }
2413 }
2414 Ok(args)
2415 }
2416
2417 fn is_at_end(&self) -> bool {
2418 self.pos >= self.tokens.len()
2419 || matches!(self.tokens.get(self.pos), Some(t) if t.kind == TokenKind::Eof)
2420 }
2421
2422 fn current(&self) -> Option<&Token> {
2423 self.tokens.get(self.pos)
2424 }
2425
2426 fn peek_kind(&self) -> Option<&TokenKind> {
2427 self.tokens.get(self.pos + 1).map(|t| &t.kind)
2428 }
2429
2430 fn check(&self, kind: &TokenKind) -> bool {
2431 self.current()
2432 .map(|t| std::mem::discriminant(&t.kind) == std::mem::discriminant(kind))
2433 .unwrap_or(false)
2434 }
2435
2436 fn check_skip_newlines(&mut self, kind: &TokenKind) -> bool {
2439 let saved = self.pos;
2440 self.skip_newlines();
2441 if self.check(kind) {
2442 true
2443 } else {
2444 self.pos = saved;
2445 false
2446 }
2447 }
2448
2449 fn check_identifier(&self, name: &str) -> bool {
2451 matches!(self.current().map(|t| &t.kind), Some(TokenKind::Identifier(s)) if s == name)
2452 }
2453
2454 fn advance(&mut self) {
2455 if self.pos < self.tokens.len() {
2456 self.pos += 1;
2457 }
2458 }
2459
2460 fn consume(&mut self, kind: &TokenKind, expected: &str) -> Result<Token, ParserError> {
2461 self.skip_newlines();
2462 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2463 if std::mem::discriminant(&tok.kind) != std::mem::discriminant(kind) {
2464 return Err(self.make_error(expected));
2465 }
2466 let tok = tok.clone();
2467 self.advance();
2468 Ok(tok)
2469 }
2470
2471 fn consume_identifier(&mut self, expected: &str) -> Result<String, ParserError> {
2472 self.skip_newlines();
2473 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2474 if let TokenKind::Identifier(name) = &tok.kind {
2475 let name = name.clone();
2476 self.advance();
2477 Ok(name)
2478 } else {
2479 let kw_name = harn_lexer::KEYWORDS
2482 .iter()
2483 .find(|&&kw| kw == tok.kind.to_string());
2484 if let Some(kw) = kw_name {
2485 Err(ParserError::Unexpected {
2486 got: format!("'{kw}' (reserved keyword)"),
2487 expected: expected.into(),
2488 span: tok.span,
2489 })
2490 } else {
2491 Err(self.make_error(expected))
2492 }
2493 }
2494 }
2495
2496 fn consume_identifier_or_keyword(&mut self, expected: &str) -> Result<String, ParserError> {
2500 self.skip_newlines();
2501 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2502 if let TokenKind::Identifier(name) = &tok.kind {
2503 let name = name.clone();
2504 self.advance();
2505 return Ok(name);
2506 }
2507 let name = match &tok.kind {
2509 TokenKind::Pipeline => "pipeline",
2510 TokenKind::Extends => "extends",
2511 TokenKind::Override => "override",
2512 TokenKind::Let => "let",
2513 TokenKind::Var => "var",
2514 TokenKind::If => "if",
2515 TokenKind::Else => "else",
2516 TokenKind::For => "for",
2517 TokenKind::In => "in",
2518 TokenKind::Match => "match",
2519 TokenKind::Retry => "retry",
2520 TokenKind::Parallel => "parallel",
2521 TokenKind::ParallelMap => "parallel_map",
2522 TokenKind::ParallelSettle => "parallel_settle",
2523 TokenKind::Return => "return",
2524 TokenKind::Import => "import",
2525 TokenKind::True => "true",
2526 TokenKind::False => "false",
2527 TokenKind::Nil => "nil",
2528 TokenKind::Try => "try",
2529 TokenKind::Catch => "catch",
2530 TokenKind::Throw => "throw",
2531 TokenKind::Fn => "fn",
2532 TokenKind::Spawn => "spawn",
2533 TokenKind::While => "while",
2534 TokenKind::TypeKw => "type",
2535 TokenKind::Enum => "enum",
2536 TokenKind::Struct => "struct",
2537 TokenKind::Interface => "interface",
2538 TokenKind::Pub => "pub",
2539 TokenKind::From => "from",
2540 TokenKind::Thru => "thru",
2541 TokenKind::Tool => "tool",
2542 TokenKind::Upto => "upto",
2543 TokenKind::Guard => "guard",
2544 TokenKind::Ask => "ask",
2545 TokenKind::Deadline => "deadline",
2546 TokenKind::Yield => "yield",
2547 TokenKind::Mutex => "mutex",
2548 TokenKind::Break => "break",
2549 TokenKind::Continue => "continue",
2550 TokenKind::Impl => "impl",
2551 _ => return Err(self.make_error(expected)),
2552 };
2553 let name = name.to_string();
2554 self.advance();
2555 Ok(name)
2556 }
2557
2558 fn skip_newlines(&mut self) {
2559 while self.pos < self.tokens.len() && self.tokens[self.pos].kind == TokenKind::Newline {
2560 self.pos += 1;
2561 }
2562 }
2563
2564 fn make_error(&self, expected: &str) -> ParserError {
2565 if let Some(tok) = self.tokens.get(self.pos) {
2566 if tok.kind == TokenKind::Eof {
2567 return ParserError::UnexpectedEof {
2568 expected: expected.into(),
2569 span: tok.span,
2570 };
2571 }
2572 ParserError::Unexpected {
2573 got: tok.kind.to_string(),
2574 expected: expected.into(),
2575 span: tok.span,
2576 }
2577 } else {
2578 ParserError::UnexpectedEof {
2579 expected: expected.into(),
2580 span: self.prev_span(),
2581 }
2582 }
2583 }
2584
2585 fn error(&self, expected: &str) -> ParserError {
2586 self.make_error(expected)
2587 }
2588}
2589
2590#[cfg(test)]
2591mod tests {
2592 use super::*;
2593 use harn_lexer::Lexer;
2594
2595 fn parse_source(source: &str) -> Result<Vec<SNode>, ParserError> {
2596 let mut lexer = Lexer::new(source);
2597 let tokens = lexer.tokenize().unwrap();
2598 let mut parser = Parser::new(tokens);
2599 parser.parse()
2600 }
2601
2602 #[test]
2603 fn parses_match_expression_with_let_in_arm_body() {
2604 let source = r#"
2605pipeline p() {
2606 let x = match 1 {
2607 1 -> {
2608 let a = 1
2609 a
2610 }
2611 _ -> { 0 }
2612 }
2613}
2614"#;
2615
2616 assert!(parse_source(source).is_ok());
2617 }
2618
2619 #[test]
2620 fn parses_public_declarations_and_generic_interfaces() {
2621 let source = r#"
2622pub pipeline build(task) extends base {
2623 return
2624}
2625
2626pub enum Result {
2627 Ok(value: string),
2628 Err(message: string, code: int),
2629}
2630
2631pub struct Config {
2632 host: string
2633 port?: int
2634}
2635
2636interface Repository<T> {
2637 fn get(id: string) -> T
2638 fn map<U>(value: T, f: fn(T) -> U) -> U
2639}
2640"#;
2641
2642 let program = parse_source(source).expect("should parse");
2643 assert!(matches!(
2644 &program[0].node,
2645 Node::Pipeline {
2646 is_pub: true,
2647 extends: Some(base),
2648 ..
2649 } if base == "base"
2650 ));
2651 assert!(matches!(
2652 &program[1].node,
2653 Node::EnumDecl { is_pub: true, .. }
2654 ));
2655 assert!(matches!(
2656 &program[2].node,
2657 Node::StructDecl { is_pub: true, .. }
2658 ));
2659 assert!(matches!(
2660 &program[3].node,
2661 Node::InterfaceDecl { type_params, methods, .. }
2662 if type_params.len() == 1
2663 && methods.len() == 2
2664 && methods[1].type_params.len() == 1
2665 ));
2666 }
2667}