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