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