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