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_nil_coalescing()?;
1292 if !self.check(&TokenKind::Question) {
1293 return Ok(condition);
1294 }
1295 let start = condition.span;
1296 self.advance(); let true_val = self.parse_nil_coalescing()?;
1298 self.consume(&TokenKind::Colon, ":")?;
1299 let false_val = self.parse_nil_coalescing()?;
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> {
1311 let mut left = self.parse_logical_or()?;
1312 while self.check(&TokenKind::NilCoal) {
1313 let start = left.span;
1314 self.advance();
1315 let right = self.parse_logical_or()?;
1316 left = spanned(
1317 Node::BinaryOp {
1318 op: "??".into(),
1319 left: Box::new(left),
1320 right: Box::new(right),
1321 },
1322 Span::merge(start, self.prev_span()),
1323 );
1324 }
1325 Ok(left)
1326 }
1327
1328 fn parse_logical_or(&mut self) -> Result<SNode, ParserError> {
1329 let mut left = self.parse_logical_and()?;
1330 while self.check_skip_newlines(&TokenKind::Or) {
1331 let start = left.span;
1332 self.advance();
1333 let right = self.parse_logical_and()?;
1334 left = spanned(
1335 Node::BinaryOp {
1336 op: "||".into(),
1337 left: Box::new(left),
1338 right: Box::new(right),
1339 },
1340 Span::merge(start, self.prev_span()),
1341 );
1342 }
1343 Ok(left)
1344 }
1345
1346 fn parse_logical_and(&mut self) -> Result<SNode, ParserError> {
1347 let mut left = self.parse_equality()?;
1348 while self.check_skip_newlines(&TokenKind::And) {
1349 let start = left.span;
1350 self.advance();
1351 let right = self.parse_equality()?;
1352 left = spanned(
1353 Node::BinaryOp {
1354 op: "&&".into(),
1355 left: Box::new(left),
1356 right: Box::new(right),
1357 },
1358 Span::merge(start, self.prev_span()),
1359 );
1360 }
1361 Ok(left)
1362 }
1363
1364 fn parse_equality(&mut self) -> Result<SNode, ParserError> {
1365 let mut left = self.parse_comparison()?;
1366 while self.check(&TokenKind::Eq) || self.check(&TokenKind::Neq) {
1367 let start = left.span;
1368 let op = if self.check(&TokenKind::Eq) {
1369 "=="
1370 } else {
1371 "!="
1372 };
1373 self.advance();
1374 let right = self.parse_comparison()?;
1375 left = spanned(
1376 Node::BinaryOp {
1377 op: op.into(),
1378 left: Box::new(left),
1379 right: Box::new(right),
1380 },
1381 Span::merge(start, self.prev_span()),
1382 );
1383 }
1384 Ok(left)
1385 }
1386
1387 fn parse_comparison(&mut self) -> Result<SNode, ParserError> {
1388 let mut left = self.parse_additive()?;
1389 loop {
1390 if self.check(&TokenKind::Lt)
1391 || self.check(&TokenKind::Gt)
1392 || self.check(&TokenKind::Lte)
1393 || self.check(&TokenKind::Gte)
1394 {
1395 let start = left.span;
1396 let op = match self.current().map(|t| &t.kind) {
1397 Some(TokenKind::Lt) => "<",
1398 Some(TokenKind::Gt) => ">",
1399 Some(TokenKind::Lte) => "<=",
1400 Some(TokenKind::Gte) => ">=",
1401 _ => "<",
1402 };
1403 self.advance();
1404 let right = self.parse_additive()?;
1405 left = spanned(
1406 Node::BinaryOp {
1407 op: op.into(),
1408 left: Box::new(left),
1409 right: Box::new(right),
1410 },
1411 Span::merge(start, self.prev_span()),
1412 );
1413 } else if self.check(&TokenKind::In) {
1414 let start = left.span;
1415 self.advance();
1416 let right = self.parse_additive()?;
1417 left = spanned(
1418 Node::BinaryOp {
1419 op: "in".into(),
1420 left: Box::new(left),
1421 right: Box::new(right),
1422 },
1423 Span::merge(start, self.prev_span()),
1424 );
1425 } else if self.check_identifier("not") {
1426 let saved = self.pos;
1428 self.advance(); if self.check(&TokenKind::In) {
1430 let start = left.span;
1431 self.advance(); let right = self.parse_additive()?;
1433 left = spanned(
1434 Node::BinaryOp {
1435 op: "not_in".into(),
1436 left: Box::new(left),
1437 right: Box::new(right),
1438 },
1439 Span::merge(start, self.prev_span()),
1440 );
1441 } else {
1442 self.pos = saved;
1443 break;
1444 }
1445 } else {
1446 break;
1447 }
1448 }
1449 Ok(left)
1450 }
1451
1452 fn parse_additive(&mut self) -> Result<SNode, ParserError> {
1453 let mut left = self.parse_multiplicative()?;
1454 while self.check_skip_newlines(&TokenKind::Plus) || self.check(&TokenKind::Minus) {
1455 let start = left.span;
1456 let op = if self.check(&TokenKind::Plus) {
1457 "+"
1458 } else {
1459 "-"
1460 };
1461 self.advance();
1462 let right = self.parse_multiplicative()?;
1463 left = spanned(
1464 Node::BinaryOp {
1465 op: op.into(),
1466 left: Box::new(left),
1467 right: Box::new(right),
1468 },
1469 Span::merge(start, self.prev_span()),
1470 );
1471 }
1472 Ok(left)
1473 }
1474
1475 fn parse_multiplicative(&mut self) -> Result<SNode, ParserError> {
1476 let mut left = self.parse_unary()?;
1477 while self.check_skip_newlines(&TokenKind::Star)
1478 || self.check_skip_newlines(&TokenKind::Slash)
1479 || self.check_skip_newlines(&TokenKind::Percent)
1480 {
1481 let start = left.span;
1482 let op = if self.check(&TokenKind::Star) {
1483 "*"
1484 } else if self.check(&TokenKind::Slash) {
1485 "/"
1486 } else {
1487 "%"
1488 };
1489 self.advance();
1490 let right = self.parse_unary()?;
1491 left = spanned(
1492 Node::BinaryOp {
1493 op: op.into(),
1494 left: Box::new(left),
1495 right: Box::new(right),
1496 },
1497 Span::merge(start, self.prev_span()),
1498 );
1499 }
1500 Ok(left)
1501 }
1502
1503 fn parse_unary(&mut self) -> Result<SNode, ParserError> {
1504 if self.check(&TokenKind::Not) {
1505 let start = self.current_span();
1506 self.advance();
1507 let operand = self.parse_unary()?;
1508 return Ok(spanned(
1509 Node::UnaryOp {
1510 op: "!".into(),
1511 operand: Box::new(operand),
1512 },
1513 Span::merge(start, self.prev_span()),
1514 ));
1515 }
1516 if self.check(&TokenKind::Minus) {
1517 let start = self.current_span();
1518 self.advance();
1519 let operand = self.parse_unary()?;
1520 return Ok(spanned(
1521 Node::UnaryOp {
1522 op: "-".into(),
1523 operand: Box::new(operand),
1524 },
1525 Span::merge(start, self.prev_span()),
1526 ));
1527 }
1528 self.parse_postfix()
1529 }
1530
1531 fn parse_postfix(&mut self) -> Result<SNode, ParserError> {
1532 let mut expr = self.parse_primary()?;
1533
1534 loop {
1535 if self.check_skip_newlines(&TokenKind::Dot)
1536 || self.check_skip_newlines(&TokenKind::QuestionDot)
1537 {
1538 let optional = self.check(&TokenKind::QuestionDot);
1539 let start = expr.span;
1540 self.advance();
1541 let member = self.consume_identifier_or_keyword("member name")?;
1542 if self.check(&TokenKind::LParen) {
1543 self.advance();
1544 let args = self.parse_arg_list()?;
1545 self.consume(&TokenKind::RParen, ")")?;
1546 if optional {
1547 expr = spanned(
1548 Node::OptionalMethodCall {
1549 object: Box::new(expr),
1550 method: member,
1551 args,
1552 },
1553 Span::merge(start, self.prev_span()),
1554 );
1555 } else {
1556 expr = spanned(
1557 Node::MethodCall {
1558 object: Box::new(expr),
1559 method: member,
1560 args,
1561 },
1562 Span::merge(start, self.prev_span()),
1563 );
1564 }
1565 } else if optional {
1566 expr = spanned(
1567 Node::OptionalPropertyAccess {
1568 object: Box::new(expr),
1569 property: member,
1570 },
1571 Span::merge(start, self.prev_span()),
1572 );
1573 } else {
1574 expr = spanned(
1575 Node::PropertyAccess {
1576 object: Box::new(expr),
1577 property: member,
1578 },
1579 Span::merge(start, self.prev_span()),
1580 );
1581 }
1582 } else if self.check(&TokenKind::LBracket) {
1583 let start = expr.span;
1584 self.advance();
1585
1586 if self.check(&TokenKind::Colon) {
1591 self.advance(); let end_expr = if self.check(&TokenKind::RBracket) {
1594 None
1595 } else {
1596 Some(Box::new(self.parse_expression()?))
1597 };
1598 self.consume(&TokenKind::RBracket, "]")?;
1599 expr = spanned(
1600 Node::SliceAccess {
1601 object: Box::new(expr),
1602 start: None,
1603 end: end_expr,
1604 },
1605 Span::merge(start, self.prev_span()),
1606 );
1607 } else {
1608 let index = self.parse_expression()?;
1609 if self.check(&TokenKind::Colon) {
1610 self.advance(); let end_expr = if self.check(&TokenKind::RBracket) {
1613 None
1614 } else {
1615 Some(Box::new(self.parse_expression()?))
1616 };
1617 self.consume(&TokenKind::RBracket, "]")?;
1618 expr = spanned(
1619 Node::SliceAccess {
1620 object: Box::new(expr),
1621 start: Some(Box::new(index)),
1622 end: end_expr,
1623 },
1624 Span::merge(start, self.prev_span()),
1625 );
1626 } else {
1627 self.consume(&TokenKind::RBracket, "]")?;
1628 expr = spanned(
1629 Node::SubscriptAccess {
1630 object: Box::new(expr),
1631 index: Box::new(index),
1632 },
1633 Span::merge(start, self.prev_span()),
1634 );
1635 }
1636 }
1637 } else if self.check(&TokenKind::LParen) && matches!(expr.node, Node::Identifier(_)) {
1638 let start = expr.span;
1639 self.advance();
1640 let args = self.parse_arg_list()?;
1641 self.consume(&TokenKind::RParen, ")")?;
1642 if let Node::Identifier(name) = expr.node {
1643 expr = spanned(
1644 Node::FunctionCall { name, args },
1645 Span::merge(start, self.prev_span()),
1646 );
1647 }
1648 } else if self.check(&TokenKind::Question) {
1649 let next_pos = self.pos + 1;
1652 let is_ternary = self.tokens.get(next_pos).is_some_and(|t| {
1653 matches!(
1654 t.kind,
1655 TokenKind::Identifier(_)
1656 | TokenKind::IntLiteral(_)
1657 | TokenKind::FloatLiteral(_)
1658 | TokenKind::StringLiteral(_)
1659 | TokenKind::InterpolatedString(_)
1660 | TokenKind::True
1661 | TokenKind::False
1662 | TokenKind::Nil
1663 | TokenKind::LParen
1664 | TokenKind::LBracket
1665 | TokenKind::LBrace
1666 | TokenKind::Not
1667 | TokenKind::Minus
1668 | TokenKind::Fn
1669 )
1670 });
1671 if is_ternary {
1672 break;
1673 }
1674 let start = expr.span;
1675 self.advance(); expr = spanned(
1677 Node::TryOperator {
1678 operand: Box::new(expr),
1679 },
1680 Span::merge(start, self.prev_span()),
1681 );
1682 } else {
1683 break;
1684 }
1685 }
1686
1687 Ok(expr)
1688 }
1689
1690 fn parse_primary(&mut self) -> Result<SNode, ParserError> {
1691 let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
1692 expected: "expression".into(),
1693 span: self.prev_span(),
1694 })?;
1695 let start = self.current_span();
1696
1697 match &tok.kind {
1698 TokenKind::StringLiteral(s) => {
1699 let s = s.clone();
1700 self.advance();
1701 Ok(spanned(
1702 Node::StringLiteral(s),
1703 Span::merge(start, self.prev_span()),
1704 ))
1705 }
1706 TokenKind::InterpolatedString(segments) => {
1707 let segments = segments.clone();
1708 self.advance();
1709 Ok(spanned(
1710 Node::InterpolatedString(segments),
1711 Span::merge(start, self.prev_span()),
1712 ))
1713 }
1714 TokenKind::IntLiteral(n) => {
1715 let n = *n;
1716 self.advance();
1717 Ok(spanned(
1718 Node::IntLiteral(n),
1719 Span::merge(start, self.prev_span()),
1720 ))
1721 }
1722 TokenKind::FloatLiteral(n) => {
1723 let n = *n;
1724 self.advance();
1725 Ok(spanned(
1726 Node::FloatLiteral(n),
1727 Span::merge(start, self.prev_span()),
1728 ))
1729 }
1730 TokenKind::True => {
1731 self.advance();
1732 Ok(spanned(
1733 Node::BoolLiteral(true),
1734 Span::merge(start, self.prev_span()),
1735 ))
1736 }
1737 TokenKind::False => {
1738 self.advance();
1739 Ok(spanned(
1740 Node::BoolLiteral(false),
1741 Span::merge(start, self.prev_span()),
1742 ))
1743 }
1744 TokenKind::Nil => {
1745 self.advance();
1746 Ok(spanned(
1747 Node::NilLiteral,
1748 Span::merge(start, self.prev_span()),
1749 ))
1750 }
1751 TokenKind::Identifier(name) => {
1752 let name = name.clone();
1753 self.advance();
1754 Ok(spanned(
1755 Node::Identifier(name),
1756 Span::merge(start, self.prev_span()),
1757 ))
1758 }
1759 TokenKind::LParen => {
1760 self.advance();
1761 let expr = self.parse_expression()?;
1762 self.consume(&TokenKind::RParen, ")")?;
1763 Ok(expr)
1764 }
1765 TokenKind::LBracket => self.parse_list_literal(),
1766 TokenKind::LBrace => self.parse_dict_or_closure(),
1767 TokenKind::Parallel => self.parse_parallel(),
1768 TokenKind::ParallelMap => self.parse_parallel_map(),
1769 TokenKind::ParallelSettle => self.parse_parallel_settle(),
1770 TokenKind::Retry => self.parse_retry(),
1771 TokenKind::If => self.parse_if_else(),
1772 TokenKind::Spawn => self.parse_spawn_expr(),
1773 TokenKind::DurationLiteral(ms) => {
1774 let ms = *ms;
1775 self.advance();
1776 Ok(spanned(
1777 Node::DurationLiteral(ms),
1778 Span::merge(start, self.prev_span()),
1779 ))
1780 }
1781 TokenKind::Ask => self.parse_ask_expr(),
1782 TokenKind::Deadline => self.parse_deadline(),
1783 TokenKind::Try => self.parse_try_catch(),
1784 TokenKind::Match => self.parse_match(),
1785 TokenKind::Fn => self.parse_fn_expr(),
1786 _ => Err(self.error("expression")),
1787 }
1788 }
1789
1790 fn parse_fn_expr(&mut self) -> Result<SNode, ParserError> {
1794 let start = self.current_span();
1795 self.consume(&TokenKind::Fn, "fn")?;
1796 self.consume(&TokenKind::LParen, "(")?;
1797 let params = self.parse_typed_param_list()?;
1798 self.consume(&TokenKind::RParen, ")")?;
1799 self.consume(&TokenKind::LBrace, "{")?;
1800 let body = self.parse_block()?;
1801 self.consume(&TokenKind::RBrace, "}")?;
1802 Ok(spanned(
1803 Node::Closure {
1804 params,
1805 body,
1806 fn_syntax: true,
1807 },
1808 Span::merge(start, self.prev_span()),
1809 ))
1810 }
1811
1812 fn parse_spawn_expr(&mut self) -> Result<SNode, ParserError> {
1813 let start = self.current_span();
1814 self.consume(&TokenKind::Spawn, "spawn")?;
1815 self.consume(&TokenKind::LBrace, "{")?;
1816 let body = self.parse_block()?;
1817 self.consume(&TokenKind::RBrace, "}")?;
1818 Ok(spanned(
1819 Node::SpawnExpr { body },
1820 Span::merge(start, self.prev_span()),
1821 ))
1822 }
1823
1824 fn parse_list_literal(&mut self) -> Result<SNode, ParserError> {
1825 let start = self.current_span();
1826 self.consume(&TokenKind::LBracket, "[")?;
1827 let mut elements = Vec::new();
1828 self.skip_newlines();
1829
1830 while !self.is_at_end() && !self.check(&TokenKind::RBracket) {
1831 if self.check(&TokenKind::Dot) {
1833 let saved_pos = self.pos;
1834 self.advance(); if self.check(&TokenKind::Dot) {
1836 self.advance(); self.consume(&TokenKind::Dot, ".")?; let spread_start = self.tokens[saved_pos].span;
1839 let expr = self.parse_expression()?;
1840 elements.push(spanned(
1841 Node::Spread(Box::new(expr)),
1842 Span::merge(spread_start, self.prev_span()),
1843 ));
1844 } else {
1845 self.pos = saved_pos;
1847 elements.push(self.parse_expression()?);
1848 }
1849 } else {
1850 elements.push(self.parse_expression()?);
1851 }
1852 self.skip_newlines();
1853 if self.check(&TokenKind::Comma) {
1854 self.advance();
1855 self.skip_newlines();
1856 }
1857 }
1858
1859 self.consume(&TokenKind::RBracket, "]")?;
1860 Ok(spanned(
1861 Node::ListLiteral(elements),
1862 Span::merge(start, self.prev_span()),
1863 ))
1864 }
1865
1866 fn parse_dict_or_closure(&mut self) -> Result<SNode, ParserError> {
1867 let start = self.current_span();
1868 self.consume(&TokenKind::LBrace, "{")?;
1869 self.skip_newlines();
1870
1871 if self.check(&TokenKind::RBrace) {
1873 self.advance();
1874 return Ok(spanned(
1875 Node::DictLiteral(Vec::new()),
1876 Span::merge(start, self.prev_span()),
1877 ));
1878 }
1879
1880 let saved = self.pos;
1882 if self.is_closure_lookahead() {
1883 self.pos = saved;
1884 return self.parse_closure_body(start);
1885 }
1886 self.pos = saved;
1887 self.parse_dict_literal(start)
1888 }
1889
1890 fn is_closure_lookahead(&mut self) -> bool {
1893 let mut depth = 0;
1894 while !self.is_at_end() {
1895 if let Some(tok) = self.current() {
1896 match &tok.kind {
1897 TokenKind::Arrow if depth == 0 => return true,
1898 TokenKind::LBrace | TokenKind::LParen | TokenKind::LBracket => depth += 1,
1899 TokenKind::RBrace if depth == 0 => return false,
1900 TokenKind::RBrace => depth -= 1,
1901 TokenKind::RParen | TokenKind::RBracket => {
1902 if depth > 0 {
1903 depth -= 1;
1904 }
1905 }
1906 _ => {}
1907 }
1908 self.advance();
1909 } else {
1910 return false;
1911 }
1912 }
1913 false
1914 }
1915
1916 fn parse_closure_body(&mut self, start: Span) -> Result<SNode, ParserError> {
1918 let params = self.parse_typed_param_list_until_arrow()?;
1919 self.consume(&TokenKind::Arrow, "->")?;
1920 let body = self.parse_block()?;
1921 self.consume(&TokenKind::RBrace, "}")?;
1922 Ok(spanned(
1923 Node::Closure {
1924 params,
1925 body,
1926 fn_syntax: false,
1927 },
1928 Span::merge(start, self.prev_span()),
1929 ))
1930 }
1931
1932 fn parse_typed_param_list_until_arrow(&mut self) -> Result<Vec<TypedParam>, ParserError> {
1934 self.parse_typed_params_until(|tok| tok == &TokenKind::Arrow)
1935 }
1936
1937 fn parse_dict_literal(&mut self, start: Span) -> Result<SNode, ParserError> {
1938 let mut entries = Vec::new();
1939 self.skip_newlines();
1940
1941 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1942 if self.check(&TokenKind::Dot) {
1944 let saved_pos = self.pos;
1945 self.advance(); if self.check(&TokenKind::Dot) {
1947 self.advance(); if self.check(&TokenKind::Dot) {
1949 self.advance(); let spread_start = self.tokens[saved_pos].span;
1951 let expr = self.parse_expression()?;
1952 entries.push(DictEntry {
1953 key: spanned(Node::NilLiteral, spread_start),
1954 value: spanned(
1955 Node::Spread(Box::new(expr)),
1956 Span::merge(spread_start, self.prev_span()),
1957 ),
1958 });
1959 self.skip_newlines();
1960 if self.check(&TokenKind::Comma) {
1961 self.advance();
1962 self.skip_newlines();
1963 }
1964 continue;
1965 }
1966 self.pos = saved_pos;
1968 } else {
1969 self.pos = saved_pos;
1970 }
1971 }
1972 let key = if self.check(&TokenKind::LBracket) {
1973 self.advance();
1975 let k = self.parse_expression()?;
1976 self.consume(&TokenKind::RBracket, "]")?;
1977 k
1978 } else if matches!(
1979 self.current().map(|t| &t.kind),
1980 Some(TokenKind::StringLiteral(_))
1981 ) {
1982 let key_span = self.current_span();
1984 let name =
1985 if let Some(TokenKind::StringLiteral(s)) = self.current().map(|t| &t.kind) {
1986 s.clone()
1987 } else {
1988 unreachable!()
1989 };
1990 self.advance();
1991 spanned(Node::StringLiteral(name), key_span)
1992 } else {
1993 let key_span = self.current_span();
1995 let name = self.consume_identifier_or_keyword("dict key")?;
1996 spanned(Node::StringLiteral(name), key_span)
1997 };
1998 self.consume(&TokenKind::Colon, ":")?;
1999 let value = self.parse_expression()?;
2000 entries.push(DictEntry { key, value });
2001 self.skip_newlines();
2002 if self.check(&TokenKind::Comma) {
2003 self.advance();
2004 self.skip_newlines();
2005 }
2006 }
2007
2008 self.consume(&TokenKind::RBrace, "}")?;
2009 Ok(spanned(
2010 Node::DictLiteral(entries),
2011 Span::merge(start, self.prev_span()),
2012 ))
2013 }
2014
2015 fn parse_param_list(&mut self) -> Result<Vec<String>, ParserError> {
2019 let mut params = Vec::new();
2020 self.skip_newlines();
2021
2022 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2023 params.push(self.consume_identifier("parameter name")?);
2024 if self.check(&TokenKind::Comma) {
2025 self.advance();
2026 self.skip_newlines();
2027 }
2028 }
2029 Ok(params)
2030 }
2031
2032 fn parse_typed_param_list(&mut self) -> Result<Vec<TypedParam>, ParserError> {
2034 self.parse_typed_params_until(|tok| tok == &TokenKind::RParen)
2035 }
2036
2037 fn parse_typed_params_until(
2040 &mut self,
2041 is_terminator: impl Fn(&TokenKind) -> bool,
2042 ) -> Result<Vec<TypedParam>, ParserError> {
2043 let mut params = Vec::new();
2044 let mut seen_default = false;
2045 self.skip_newlines();
2046
2047 while !self.is_at_end() {
2048 if let Some(tok) = self.current() {
2049 if is_terminator(&tok.kind) {
2050 break;
2051 }
2052 } else {
2053 break;
2054 }
2055 let name = self.consume_identifier("parameter name")?;
2056 let type_expr = self.try_parse_type_annotation()?;
2057 let default_value = if self.check(&TokenKind::Assign) {
2058 self.advance();
2059 seen_default = true;
2060 Some(Box::new(self.parse_expression()?))
2061 } else {
2062 if seen_default {
2063 return Err(self.error(
2064 "Required parameter cannot follow a parameter with a default value",
2065 ));
2066 }
2067 None
2068 };
2069 params.push(TypedParam {
2070 name,
2071 type_expr,
2072 default_value,
2073 });
2074 if self.check(&TokenKind::Comma) {
2075 self.advance();
2076 self.skip_newlines();
2077 }
2078 }
2079 Ok(params)
2080 }
2081
2082 fn parse_type_param_list(&mut self) -> Result<Vec<TypeParam>, ParserError> {
2084 let mut params = Vec::new();
2085 self.skip_newlines();
2086 while !self.is_at_end() && !self.check(&TokenKind::Gt) {
2087 let name = self.consume_identifier("type parameter name")?;
2088 params.push(TypeParam { name });
2089 if self.check(&TokenKind::Comma) {
2090 self.advance();
2091 self.skip_newlines();
2092 }
2093 }
2094 self.consume(&TokenKind::Gt, ">")?;
2095 Ok(params)
2096 }
2097
2098 fn parse_where_clauses(&mut self) -> Result<Vec<WhereClause>, ParserError> {
2101 if let Some(tok) = self.current() {
2103 if let TokenKind::Identifier(ref id) = tok.kind {
2104 if id == "where" {
2105 self.advance(); let mut clauses = Vec::new();
2107 loop {
2108 self.skip_newlines();
2109 if self.check(&TokenKind::LBrace) || self.is_at_end() {
2111 break;
2112 }
2113 let type_name = self.consume_identifier("type parameter name")?;
2114 self.consume(&TokenKind::Colon, ":")?;
2115 let bound = self.consume_identifier("type bound")?;
2116 clauses.push(WhereClause { type_name, bound });
2117 if self.check(&TokenKind::Comma) {
2118 self.advance();
2119 } else {
2120 break;
2121 }
2122 }
2123 return Ok(clauses);
2124 }
2125 }
2126 }
2127 Ok(Vec::new())
2128 }
2129
2130 fn try_parse_type_annotation(&mut self) -> Result<Option<TypeExpr>, ParserError> {
2133 if !self.check(&TokenKind::Colon) {
2134 return Ok(None);
2135 }
2136 self.advance(); Ok(Some(self.parse_type_expr()?))
2138 }
2139
2140 fn parse_type_expr(&mut self) -> Result<TypeExpr, ParserError> {
2142 self.skip_newlines();
2143 let first = self.parse_type_primary()?;
2144
2145 if self.check(&TokenKind::Bar) {
2147 let mut types = vec![first];
2148 while self.check(&TokenKind::Bar) {
2149 self.advance(); types.push(self.parse_type_primary()?);
2151 }
2152 return Ok(TypeExpr::Union(types));
2153 }
2154
2155 Ok(first)
2156 }
2157
2158 fn parse_type_primary(&mut self) -> Result<TypeExpr, ParserError> {
2161 self.skip_newlines();
2162 if self.check(&TokenKind::LBrace) {
2163 return self.parse_shape_type();
2164 }
2165 if let Some(tok) = self.current() {
2167 let type_name = match &tok.kind {
2168 TokenKind::Nil => {
2169 self.advance();
2170 return Ok(TypeExpr::Named("nil".to_string()));
2171 }
2172 TokenKind::True | TokenKind::False => {
2173 self.advance();
2174 return Ok(TypeExpr::Named("bool".to_string()));
2175 }
2176 _ => None,
2177 };
2178 if let Some(name) = type_name {
2179 return Ok(TypeExpr::Named(name));
2180 }
2181 }
2182 if self.check(&TokenKind::Fn) {
2184 self.advance(); self.consume(&TokenKind::LParen, "(")?;
2186 let mut params = Vec::new();
2187 self.skip_newlines();
2188 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2189 params.push(self.parse_type_expr()?);
2190 self.skip_newlines();
2191 if self.check(&TokenKind::Comma) {
2192 self.advance();
2193 self.skip_newlines();
2194 }
2195 }
2196 self.consume(&TokenKind::RParen, ")")?;
2197 self.consume(&TokenKind::Arrow, "->")?;
2198 let return_type = self.parse_type_expr()?;
2199 return Ok(TypeExpr::FnType {
2200 params,
2201 return_type: Box::new(return_type),
2202 });
2203 }
2204 let name = self.consume_identifier("type name")?;
2205 if self.check(&TokenKind::Lt) {
2207 self.advance(); let first_param = self.parse_type_expr()?;
2209 if name == "list" {
2210 self.consume(&TokenKind::Gt, ">")?;
2211 return Ok(TypeExpr::List(Box::new(first_param)));
2212 } else if name == "dict" {
2213 self.consume(&TokenKind::Comma, ",")?;
2214 let second_param = self.parse_type_expr()?;
2215 self.consume(&TokenKind::Gt, ">")?;
2216 return Ok(TypeExpr::DictType(
2217 Box::new(first_param),
2218 Box::new(second_param),
2219 ));
2220 }
2221 self.consume(&TokenKind::Gt, ">")?;
2223 }
2224 Ok(TypeExpr::Named(name))
2225 }
2226
2227 fn parse_shape_type(&mut self) -> Result<TypeExpr, ParserError> {
2229 self.consume(&TokenKind::LBrace, "{")?;
2230 let mut fields = Vec::new();
2231 self.skip_newlines();
2232
2233 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
2234 let name = self.consume_identifier("field name")?;
2235 let optional = if self.check(&TokenKind::Question) {
2236 self.advance();
2237 true
2238 } else {
2239 false
2240 };
2241 self.consume(&TokenKind::Colon, ":")?;
2242 let type_expr = self.parse_type_expr()?;
2243 fields.push(ShapeField {
2244 name,
2245 type_expr,
2246 optional,
2247 });
2248 self.skip_newlines();
2249 if self.check(&TokenKind::Comma) {
2250 self.advance();
2251 self.skip_newlines();
2252 }
2253 }
2254
2255 self.consume(&TokenKind::RBrace, "}")?;
2256 Ok(TypeExpr::Shape(fields))
2257 }
2258
2259 fn parse_arg_list(&mut self) -> Result<Vec<SNode>, ParserError> {
2260 let mut args = Vec::new();
2261 self.skip_newlines();
2262
2263 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2264 if self.check(&TokenKind::Dot) {
2266 let saved_pos = self.pos;
2267 self.advance(); if self.check(&TokenKind::Dot) {
2269 self.advance(); self.consume(&TokenKind::Dot, ".")?; let spread_start = self.tokens[saved_pos].span;
2272 let expr = self.parse_expression()?;
2273 args.push(spanned(
2274 Node::Spread(Box::new(expr)),
2275 Span::merge(spread_start, self.prev_span()),
2276 ));
2277 } else {
2278 self.pos = saved_pos;
2280 args.push(self.parse_expression()?);
2281 }
2282 } else {
2283 args.push(self.parse_expression()?);
2284 }
2285 self.skip_newlines();
2286 if self.check(&TokenKind::Comma) {
2287 self.advance();
2288 self.skip_newlines();
2289 }
2290 }
2291 Ok(args)
2292 }
2293
2294 fn is_at_end(&self) -> bool {
2295 self.pos >= self.tokens.len()
2296 || matches!(self.tokens.get(self.pos), Some(t) if t.kind == TokenKind::Eof)
2297 }
2298
2299 fn current(&self) -> Option<&Token> {
2300 self.tokens.get(self.pos)
2301 }
2302
2303 fn peek_kind(&self) -> Option<&TokenKind> {
2304 self.tokens.get(self.pos + 1).map(|t| &t.kind)
2305 }
2306
2307 fn check(&self, kind: &TokenKind) -> bool {
2308 self.current()
2309 .map(|t| std::mem::discriminant(&t.kind) == std::mem::discriminant(kind))
2310 .unwrap_or(false)
2311 }
2312
2313 fn check_skip_newlines(&mut self, kind: &TokenKind) -> bool {
2316 let saved = self.pos;
2317 self.skip_newlines();
2318 if self.check(kind) {
2319 true
2320 } else {
2321 self.pos = saved;
2322 false
2323 }
2324 }
2325
2326 fn check_identifier(&self, name: &str) -> bool {
2328 matches!(self.current().map(|t| &t.kind), Some(TokenKind::Identifier(s)) if s == name)
2329 }
2330
2331 fn advance(&mut self) {
2332 if self.pos < self.tokens.len() {
2333 self.pos += 1;
2334 }
2335 }
2336
2337 fn consume(&mut self, kind: &TokenKind, expected: &str) -> Result<Token, ParserError> {
2338 self.skip_newlines();
2339 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2340 if std::mem::discriminant(&tok.kind) != std::mem::discriminant(kind) {
2341 return Err(self.make_error(expected));
2342 }
2343 let tok = tok.clone();
2344 self.advance();
2345 Ok(tok)
2346 }
2347
2348 fn consume_identifier(&mut self, expected: &str) -> Result<String, ParserError> {
2349 self.skip_newlines();
2350 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2351 if let TokenKind::Identifier(name) = &tok.kind {
2352 let name = name.clone();
2353 self.advance();
2354 Ok(name)
2355 } else {
2356 Err(self.make_error(expected))
2357 }
2358 }
2359
2360 fn consume_identifier_or_keyword(&mut self, expected: &str) -> Result<String, ParserError> {
2364 self.skip_newlines();
2365 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2366 if let TokenKind::Identifier(name) = &tok.kind {
2367 let name = name.clone();
2368 self.advance();
2369 return Ok(name);
2370 }
2371 let name = match &tok.kind {
2373 TokenKind::Pipeline => "pipeline",
2374 TokenKind::Extends => "extends",
2375 TokenKind::Override => "override",
2376 TokenKind::Let => "let",
2377 TokenKind::Var => "var",
2378 TokenKind::If => "if",
2379 TokenKind::Else => "else",
2380 TokenKind::For => "for",
2381 TokenKind::In => "in",
2382 TokenKind::Match => "match",
2383 TokenKind::Retry => "retry",
2384 TokenKind::Parallel => "parallel",
2385 TokenKind::ParallelMap => "parallel_map",
2386 TokenKind::ParallelSettle => "parallel_settle",
2387 TokenKind::Return => "return",
2388 TokenKind::Import => "import",
2389 TokenKind::True => "true",
2390 TokenKind::False => "false",
2391 TokenKind::Nil => "nil",
2392 TokenKind::Try => "try",
2393 TokenKind::Catch => "catch",
2394 TokenKind::Throw => "throw",
2395 TokenKind::Fn => "fn",
2396 TokenKind::Spawn => "spawn",
2397 TokenKind::While => "while",
2398 TokenKind::TypeKw => "type",
2399 TokenKind::Enum => "enum",
2400 TokenKind::Struct => "struct",
2401 TokenKind::Interface => "interface",
2402 TokenKind::Pub => "pub",
2403 TokenKind::From => "from",
2404 TokenKind::Thru => "thru",
2405 TokenKind::Upto => "upto",
2406 TokenKind::Guard => "guard",
2407 TokenKind::Ask => "ask",
2408 TokenKind::Deadline => "deadline",
2409 TokenKind::Yield => "yield",
2410 TokenKind::Mutex => "mutex",
2411 TokenKind::Break => "break",
2412 TokenKind::Continue => "continue",
2413 TokenKind::Impl => "impl",
2414 _ => return Err(self.make_error(expected)),
2415 };
2416 let name = name.to_string();
2417 self.advance();
2418 Ok(name)
2419 }
2420
2421 fn skip_newlines(&mut self) {
2422 while self.pos < self.tokens.len() && self.tokens[self.pos].kind == TokenKind::Newline {
2423 self.pos += 1;
2424 }
2425 }
2426
2427 fn make_error(&self, expected: &str) -> ParserError {
2428 if let Some(tok) = self.tokens.get(self.pos) {
2429 if tok.kind == TokenKind::Eof {
2430 return ParserError::UnexpectedEof {
2431 expected: expected.into(),
2432 span: tok.span,
2433 };
2434 }
2435 ParserError::Unexpected {
2436 got: tok.kind.to_string(),
2437 expected: expected.into(),
2438 span: tok.span,
2439 }
2440 } else {
2441 ParserError::UnexpectedEof {
2442 expected: expected.into(),
2443 span: self.prev_span(),
2444 }
2445 }
2446 }
2447
2448 fn error(&self, expected: &str) -> ParserError {
2449 self.make_error(expected)
2450 }
2451}
2452
2453#[cfg(test)]
2454mod tests {
2455 use super::*;
2456 use harn_lexer::Lexer;
2457
2458 fn parse_source(source: &str) -> Result<Vec<SNode>, ParserError> {
2459 let mut lexer = Lexer::new(source);
2460 let tokens = lexer.tokenize().unwrap();
2461 let mut parser = Parser::new(tokens);
2462 parser.parse()
2463 }
2464
2465 #[test]
2466 fn parses_match_expression_with_let_in_arm_body() {
2467 let source = r#"
2468pipeline p() {
2469 let x = match 1 {
2470 1 -> {
2471 let a = 1
2472 a
2473 }
2474 _ -> { 0 }
2475 }
2476}
2477"#;
2478
2479 assert!(parse_source(source).is_ok());
2480 }
2481
2482 #[test]
2483 fn parses_public_declarations_and_generic_interfaces() {
2484 let source = r#"
2485pub pipeline build(task) extends base {
2486 return
2487}
2488
2489pub enum Result {
2490 Ok(value: string),
2491 Err(message: string, code: int),
2492}
2493
2494pub struct Config {
2495 host: string
2496 port?: int
2497}
2498
2499interface Repository<T> {
2500 fn get(id: string) -> T
2501 fn map<U>(value: T, f: fn(T) -> U) -> U
2502}
2503"#;
2504
2505 let program = parse_source(source).expect("should parse");
2506 assert!(matches!(
2507 &program[0].node,
2508 Node::Pipeline {
2509 is_pub: true,
2510 extends: Some(base),
2511 ..
2512 } if base == "base"
2513 ));
2514 assert!(matches!(
2515 &program[1].node,
2516 Node::EnumDecl { is_pub: true, .. }
2517 ));
2518 assert!(matches!(
2519 &program[2].node,
2520 Node::StructDecl { is_pub: true, .. }
2521 ));
2522 assert!(matches!(
2523 &program[3].node,
2524 Node::InterfaceDecl { type_params, methods, .. }
2525 if type_params.len() == 1
2526 && methods.len() == 2
2527 && methods[1].type_params.len() == 1
2528 ));
2529 }
2530}