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