1use crate::ast::*;
2use harn_lexer::{Span, Token, TokenKind};
3use std::collections::HashSet;
4use std::fmt;
5
6#[derive(Debug, Clone, PartialEq)]
8pub enum ParserError {
9 Unexpected {
10 got: String,
11 expected: String,
12 span: Span,
13 },
14 UnexpectedEof {
15 expected: String,
16 span: Span,
17 },
18}
19
20impl fmt::Display for ParserError {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 match self {
23 ParserError::Unexpected {
24 got,
25 expected,
26 span,
27 } => write!(
28 f,
29 "Expected {expected}, got {got} at {}:{}",
30 span.line, span.column
31 ),
32 ParserError::UnexpectedEof { expected, .. } => {
33 write!(f, "Unexpected end of file, expected {expected}")
34 }
35 }
36 }
37}
38
39impl std::error::Error for ParserError {}
40
41pub struct Parser {
43 tokens: Vec<Token>,
44 pos: usize,
45 errors: Vec<ParserError>,
46 struct_names: HashSet<String>,
47}
48
49impl Parser {
50 pub fn new(tokens: Vec<Token>) -> Self {
51 Self {
52 tokens,
53 pos: 0,
54 errors: Vec::new(),
55 struct_names: HashSet::new(),
56 }
57 }
58
59 fn current_span(&self) -> Span {
60 self.tokens
61 .get(self.pos)
62 .map(|t| t.span)
63 .unwrap_or(Span::dummy())
64 }
65
66 fn current_kind(&self) -> Option<&TokenKind> {
67 self.tokens.get(self.pos).map(|t| &t.kind)
68 }
69
70 fn prev_span(&self) -> Span {
71 if self.pos > 0 {
72 self.tokens[self.pos - 1].span
73 } else {
74 Span::dummy()
75 }
76 }
77
78 pub fn parse(&mut self) -> Result<Vec<SNode>, ParserError> {
80 let mut nodes = Vec::new();
81 self.skip_newlines();
82
83 while !self.is_at_end() {
84 if self.check(&TokenKind::RBrace) {
86 self.advance();
87 self.skip_newlines();
88 continue;
89 }
90
91 let result = if self.check(&TokenKind::Import) {
92 self.parse_import()
93 } else if self.check(&TokenKind::Pipeline) {
94 self.parse_pipeline()
95 } else {
96 self.parse_statement()
97 };
98
99 match result {
100 Ok(node) => nodes.push(node),
101 Err(err) => {
102 self.errors.push(err);
103 self.synchronize();
104 }
105 }
106 self.skip_newlines();
107 }
108
109 if let Some(first) = self.errors.first() {
110 return Err(first.clone());
111 }
112 Ok(nodes)
113 }
114
115 pub fn all_errors(&self) -> &[ParserError] {
117 &self.errors
118 }
119
120 fn is_statement_start(&self) -> bool {
122 matches!(
123 self.current_kind(),
124 Some(
125 TokenKind::Let
126 | TokenKind::Var
127 | TokenKind::If
128 | TokenKind::For
129 | TokenKind::While
130 | TokenKind::Match
131 | TokenKind::Retry
132 | TokenKind::Return
133 | TokenKind::Throw
134 | TokenKind::Fn
135 | TokenKind::Pub
136 | TokenKind::Try
137 | TokenKind::Select
138 | TokenKind::Pipeline
139 | TokenKind::Import
140 | TokenKind::Parallel
141 | TokenKind::Enum
142 | TokenKind::Struct
143 | TokenKind::Interface
144 | TokenKind::Guard
145 | TokenKind::Require
146 | TokenKind::Deadline
147 | TokenKind::Yield
148 | TokenKind::Mutex
149 | TokenKind::Tool
150 )
151 )
152 }
153
154 fn synchronize(&mut self) {
156 while !self.is_at_end() {
157 if self.check(&TokenKind::Newline) {
158 self.advance();
159 if self.is_at_end() || self.is_statement_start() {
160 return;
161 }
162 continue;
163 }
164 if self.check(&TokenKind::RBrace) {
165 return;
166 }
167 self.advance();
168 }
169 }
170
171 pub fn parse_single_expression(&mut self) -> Result<SNode, ParserError> {
173 self.skip_newlines();
174 self.parse_expression()
175 }
176
177 fn parse_pipeline_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
180 let start = self.current_span();
181 self.consume(&TokenKind::Pipeline, "pipeline")?;
182 let name = self.consume_identifier("pipeline name")?;
183
184 self.consume(&TokenKind::LParen, "(")?;
185 let params = self.parse_param_list()?;
186 self.consume(&TokenKind::RParen, ")")?;
187
188 let extends = if self.check(&TokenKind::Extends) {
189 self.advance();
190 Some(self.consume_identifier("parent pipeline name")?)
191 } else {
192 None
193 };
194
195 self.consume(&TokenKind::LBrace, "{")?;
196 let body = self.parse_block()?;
197 self.consume(&TokenKind::RBrace, "}")?;
198
199 Ok(spanned(
200 Node::Pipeline {
201 name,
202 params,
203 body,
204 extends,
205 is_pub,
206 },
207 Span::merge(start, self.prev_span()),
208 ))
209 }
210
211 fn parse_pipeline(&mut self) -> Result<SNode, ParserError> {
212 self.parse_pipeline_with_pub(false)
213 }
214
215 fn parse_import(&mut self) -> Result<SNode, ParserError> {
216 let start = self.current_span();
217 self.consume(&TokenKind::Import, "import")?;
218
219 if self.check(&TokenKind::LBrace) {
221 self.advance(); self.skip_newlines();
223 let mut names = Vec::new();
224 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
225 let name = self.consume_identifier("import name")?;
226 names.push(name);
227 self.skip_newlines();
228 if self.check(&TokenKind::Comma) {
229 self.advance();
230 self.skip_newlines();
231 }
232 }
233 self.consume(&TokenKind::RBrace, "}")?;
234 self.consume(&TokenKind::From, "from")?;
235 if let Some(tok) = self.current() {
236 if let TokenKind::StringLiteral(path) = &tok.kind {
237 let path = path.clone();
238 self.advance();
239 return Ok(spanned(
240 Node::SelectiveImport { names, path },
241 Span::merge(start, self.prev_span()),
242 ));
243 }
244 }
245 return Err(self.error("import path string"));
246 }
247
248 if let Some(tok) = self.current() {
249 if let TokenKind::StringLiteral(path) = &tok.kind {
250 let path = path.clone();
251 self.advance();
252 return Ok(spanned(
253 Node::ImportDecl { path },
254 Span::merge(start, self.prev_span()),
255 ));
256 }
257 }
258 Err(self.error("import path string"))
259 }
260
261 fn parse_block(&mut self) -> Result<Vec<SNode>, ParserError> {
264 let mut stmts = Vec::new();
265 self.skip_newlines();
266
267 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
268 stmts.push(self.parse_statement()?);
269 self.skip_newlines();
270 }
271 Ok(stmts)
272 }
273
274 fn parse_statement(&mut self) -> Result<SNode, ParserError> {
275 self.skip_newlines();
276
277 let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
278 expected: "statement".into(),
279 span: self.prev_span(),
280 })?;
281
282 match &tok.kind {
283 TokenKind::Let => self.parse_let_binding(),
284 TokenKind::Var => self.parse_var_binding(),
285 TokenKind::If => self.parse_if_else(),
286 TokenKind::For => self.parse_for_in(),
287 TokenKind::Match => self.parse_match(),
288 TokenKind::Retry => self.parse_retry(),
289 TokenKind::While => self.parse_while_loop(),
290 TokenKind::Parallel => self.parse_parallel(),
291 TokenKind::Return => self.parse_return(),
292 TokenKind::Throw => self.parse_throw(),
293 TokenKind::Override => self.parse_override(),
294 TokenKind::Try => self.parse_try_catch(),
295 TokenKind::Select => self.parse_select(),
296 TokenKind::Fn => self.parse_fn_decl_with_pub(false),
297 TokenKind::Tool => self.parse_tool_decl(false),
298 TokenKind::Pub => {
299 self.advance(); let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
301 expected: "fn, struct, enum, or pipeline after pub".into(),
302 span: self.prev_span(),
303 })?;
304 match &tok.kind {
305 TokenKind::Fn => self.parse_fn_decl_with_pub(true),
306 TokenKind::Tool => self.parse_tool_decl(true),
307 TokenKind::Pipeline => self.parse_pipeline_with_pub(true),
308 TokenKind::Enum => self.parse_enum_decl_with_pub(true),
309 TokenKind::Struct => self.parse_struct_decl_with_pub(true),
310 _ => Err(self.error("fn, tool, struct, enum, or pipeline after pub")),
311 }
312 }
313 TokenKind::TypeKw => self.parse_type_decl(),
314 TokenKind::Enum => self.parse_enum_decl(),
315 TokenKind::Struct => self.parse_struct_decl(),
316 TokenKind::Interface => self.parse_interface_decl(),
317 TokenKind::Impl => self.parse_impl_block(),
318 TokenKind::Guard => self.parse_guard(),
319 TokenKind::Require => self.parse_require(),
320 TokenKind::Deadline => self.parse_deadline(),
321 TokenKind::Yield => self.parse_yield(),
322 TokenKind::Mutex => self.parse_mutex(),
323 TokenKind::Defer => self.parse_defer(),
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 = if self.check(&TokenKind::LParen) {
417 self.advance(); let first = self.consume_identifier("pair pattern element")?;
420 self.consume(&TokenKind::Comma, ",")?;
421 let second = self.consume_identifier("pair pattern element")?;
422 self.consume(&TokenKind::RParen, ")")?;
423 BindingPattern::Pair(first, second)
424 } else {
425 self.parse_binding_pattern()?
426 };
427 self.consume(&TokenKind::In, "in")?;
428 let iterable = self.parse_expression()?;
429 self.consume(&TokenKind::LBrace, "{")?;
430 let body = self.parse_block()?;
431 self.consume(&TokenKind::RBrace, "}")?;
432 Ok(spanned(
433 Node::ForIn {
434 pattern,
435 iterable: Box::new(iterable),
436 body,
437 },
438 Span::merge(start, self.prev_span()),
439 ))
440 }
441
442 fn parse_binding_pattern(&mut self) -> Result<BindingPattern, ParserError> {
445 self.skip_newlines();
446 if self.check(&TokenKind::LBrace) {
447 self.advance(); let mut fields = Vec::new();
450 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
451 if self.check(&TokenKind::Dot) {
453 self.advance(); self.consume(&TokenKind::Dot, ".")?;
456 self.consume(&TokenKind::Dot, ".")?;
457 let name = self.consume_identifier("rest variable name")?;
458 fields.push(DictPatternField {
459 key: name,
460 alias: None,
461 is_rest: true,
462 default_value: None,
463 });
464 break;
466 }
467 let key = self.consume_identifier("field name")?;
468 let alias = if self.check(&TokenKind::Colon) {
469 self.advance(); Some(self.consume_identifier("alias name")?)
471 } else {
472 None
473 };
474 let default_value = if self.check(&TokenKind::Assign) {
475 self.advance(); Some(Box::new(self.parse_expression()?))
477 } else {
478 None
479 };
480 fields.push(DictPatternField {
481 key,
482 alias,
483 is_rest: false,
484 default_value,
485 });
486 if self.check(&TokenKind::Comma) {
487 self.advance();
488 }
489 }
490 self.consume(&TokenKind::RBrace, "}")?;
491 Ok(BindingPattern::Dict(fields))
492 } else if self.check(&TokenKind::LBracket) {
493 self.advance(); let mut elements = Vec::new();
496 while !self.is_at_end() && !self.check(&TokenKind::RBracket) {
497 if self.check(&TokenKind::Dot) {
499 self.advance(); self.consume(&TokenKind::Dot, ".")?;
501 self.consume(&TokenKind::Dot, ".")?;
502 let name = self.consume_identifier("rest variable name")?;
503 elements.push(ListPatternElement {
504 name,
505 is_rest: true,
506 default_value: None,
507 });
508 break;
510 }
511 let name = self.consume_identifier("element name")?;
512 let default_value = if self.check(&TokenKind::Assign) {
513 self.advance(); Some(Box::new(self.parse_expression()?))
515 } else {
516 None
517 };
518 elements.push(ListPatternElement {
519 name,
520 is_rest: false,
521 default_value,
522 });
523 if self.check(&TokenKind::Comma) {
524 self.advance();
525 }
526 }
527 self.consume(&TokenKind::RBracket, "]")?;
528 Ok(BindingPattern::List(elements))
529 } else {
530 let name = self.consume_identifier("variable name or destructuring pattern")?;
532 Ok(BindingPattern::Identifier(name))
533 }
534 }
535
536 fn parse_match(&mut self) -> Result<SNode, ParserError> {
537 let start = self.current_span();
538 self.consume(&TokenKind::Match, "match")?;
539 let value = self.parse_expression()?;
540 self.consume(&TokenKind::LBrace, "{")?;
541 self.skip_newlines();
542
543 let mut arms = Vec::new();
544 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
545 let pattern = self.parse_expression()?;
546 let guard = if self.check(&TokenKind::If) {
548 self.advance();
549 Some(Box::new(self.parse_expression()?))
550 } else {
551 None
552 };
553 self.consume(&TokenKind::Arrow, "->")?;
554 self.consume(&TokenKind::LBrace, "{")?;
555 let body = self.parse_block()?;
556 self.consume(&TokenKind::RBrace, "}")?;
557 arms.push(MatchArm {
558 pattern,
559 guard,
560 body,
561 });
562 self.skip_newlines();
563 }
564
565 self.consume(&TokenKind::RBrace, "}")?;
566 Ok(spanned(
567 Node::MatchExpr {
568 value: Box::new(value),
569 arms,
570 },
571 Span::merge(start, self.prev_span()),
572 ))
573 }
574
575 fn parse_while_loop(&mut self) -> Result<SNode, ParserError> {
576 let start = self.current_span();
577 self.consume(&TokenKind::While, "while")?;
578 let condition = if self.check(&TokenKind::LParen) {
579 self.advance();
580 let c = self.parse_expression()?;
581 self.consume(&TokenKind::RParen, ")")?;
582 c
583 } else {
584 self.parse_expression()?
585 };
586 self.consume(&TokenKind::LBrace, "{")?;
587 let body = self.parse_block()?;
588 self.consume(&TokenKind::RBrace, "}")?;
589 Ok(spanned(
590 Node::WhileLoop {
591 condition: Box::new(condition),
592 body,
593 },
594 Span::merge(start, self.prev_span()),
595 ))
596 }
597
598 fn parse_retry(&mut self) -> Result<SNode, ParserError> {
599 let start = self.current_span();
600 self.consume(&TokenKind::Retry, "retry")?;
601 let count = if self.check(&TokenKind::LParen) {
602 self.advance();
603 let c = self.parse_expression()?;
604 self.consume(&TokenKind::RParen, ")")?;
605 c
606 } else {
607 self.parse_primary()?
608 };
609 self.consume(&TokenKind::LBrace, "{")?;
610 let body = self.parse_block()?;
611 self.consume(&TokenKind::RBrace, "}")?;
612 Ok(spanned(
613 Node::Retry {
614 count: Box::new(count),
615 body,
616 },
617 Span::merge(start, self.prev_span()),
618 ))
619 }
620
621 fn parse_parallel(&mut self) -> Result<SNode, ParserError> {
622 let start = self.current_span();
623 self.consume(&TokenKind::Parallel, "parallel")?;
624
625 let mode = if self.check_identifier("each") {
628 self.advance();
629 ParallelMode::Each
630 } else if self.check_identifier("settle") {
631 self.advance();
632 ParallelMode::Settle
633 } else {
634 ParallelMode::Count
635 };
636
637 let expr = self.parse_expression()?;
638
639 let options = if self.check_identifier("with") {
644 self.advance();
645 self.consume(&TokenKind::LBrace, "{")?;
646 let mut options = Vec::new();
647 loop {
648 self.skip_newlines();
649 if matches!(
650 self.current().map(|t| &t.kind),
651 Some(&TokenKind::RBrace) | None
652 ) {
653 break;
654 }
655 let key_span = self.current_span();
656 let key = match self.current().map(|t| &t.kind) {
657 Some(TokenKind::Identifier(name)) => name.clone(),
658 _ => {
659 return Err(ParserError::Unexpected {
660 got: self
661 .current()
662 .map(|t| format!("{:?}", t.kind))
663 .unwrap_or_else(|| "end of input".to_string()),
664 expected: "option name in `parallel ... with { ... }` block"
665 .to_string(),
666 span: key_span,
667 });
668 }
669 };
670 self.advance();
671 if key != "max_concurrent" {
672 return Err(ParserError::Unexpected {
673 got: key.clone(),
674 expected: format!(
675 "known option (only `max_concurrent` is supported in \
676 `parallel ... with {{ ... }}`; got `{key}`)"
677 ),
678 span: key_span,
679 });
680 }
681 self.consume(&TokenKind::Colon, ":")?;
682 let value = self.parse_expression()?;
683 options.push((key, value));
684 self.skip_newlines();
685 if matches!(self.current().map(|t| &t.kind), Some(&TokenKind::Comma)) {
686 self.advance();
687 self.skip_newlines();
688 }
689 }
690 self.consume(&TokenKind::RBrace, "}")?;
691 options
692 } else {
693 Vec::new()
694 };
695
696 self.consume(&TokenKind::LBrace, "{")?;
697
698 let mut variable = None;
700 self.skip_newlines();
701 if let Some(tok) = self.current() {
702 if let TokenKind::Identifier(name) = &tok.kind {
703 if self.peek_kind() == Some(&TokenKind::Arrow) {
704 let name = name.clone();
705 self.advance(); self.advance(); variable = Some(name);
708 }
709 }
710 }
711
712 let body = self.parse_block()?;
713 self.consume(&TokenKind::RBrace, "}")?;
714 Ok(spanned(
715 Node::Parallel {
716 mode,
717 expr: Box::new(expr),
718 variable,
719 body,
720 options,
721 },
722 Span::merge(start, self.prev_span()),
723 ))
724 }
725
726 fn parse_return(&mut self) -> Result<SNode, ParserError> {
727 let start = self.current_span();
728 self.consume(&TokenKind::Return, "return")?;
729 if self.is_at_end() || self.check(&TokenKind::Newline) || self.check(&TokenKind::RBrace) {
730 return Ok(spanned(
731 Node::ReturnStmt { value: None },
732 Span::merge(start, self.prev_span()),
733 ));
734 }
735 let value = self.parse_expression()?;
736 Ok(spanned(
737 Node::ReturnStmt {
738 value: Some(Box::new(value)),
739 },
740 Span::merge(start, self.prev_span()),
741 ))
742 }
743
744 fn parse_throw(&mut self) -> Result<SNode, ParserError> {
745 let start = self.current_span();
746 self.consume(&TokenKind::Throw, "throw")?;
747 let value = self.parse_expression()?;
748 Ok(spanned(
749 Node::ThrowStmt {
750 value: Box::new(value),
751 },
752 Span::merge(start, self.prev_span()),
753 ))
754 }
755
756 fn parse_override(&mut self) -> Result<SNode, ParserError> {
757 let start = self.current_span();
758 self.consume(&TokenKind::Override, "override")?;
759 let name = self.consume_identifier("override name")?;
760 self.consume(&TokenKind::LParen, "(")?;
761 let params = self.parse_param_list()?;
762 self.consume(&TokenKind::RParen, ")")?;
763 self.consume(&TokenKind::LBrace, "{")?;
764 let body = self.parse_block()?;
765 self.consume(&TokenKind::RBrace, "}")?;
766 Ok(spanned(
767 Node::OverrideDecl { name, params, body },
768 Span::merge(start, self.prev_span()),
769 ))
770 }
771
772 fn parse_try_catch(&mut self) -> Result<SNode, ParserError> {
773 let start = self.current_span();
774 self.consume(&TokenKind::Try, "try")?;
775 self.consume(&TokenKind::LBrace, "{")?;
776 let body = self.parse_block()?;
777 self.consume(&TokenKind::RBrace, "}")?;
778 self.skip_newlines();
779
780 let has_catch = self.check(&TokenKind::Catch);
782 let (error_var, error_type, catch_body) = if has_catch {
783 self.advance();
784 let (ev, et) = if self.check(&TokenKind::LParen) {
785 self.advance();
787 let name = self.consume_identifier("error variable")?;
788 let ty = self.try_parse_type_annotation()?;
789 self.consume(&TokenKind::RParen, ")")?;
790 (Some(name), ty)
791 } else if matches!(
792 self.current().map(|t| &t.kind),
793 Some(TokenKind::Identifier(_))
794 ) {
795 let name = self.consume_identifier("error variable")?;
797 (Some(name), None)
798 } else {
799 (None, None)
800 };
801 self.consume(&TokenKind::LBrace, "{")?;
802 let cb = self.parse_block()?;
803 self.consume(&TokenKind::RBrace, "}")?;
804 (ev, et, cb)
805 } else {
806 (None, None, Vec::new())
807 };
808
809 self.skip_newlines();
810
811 let finally_body = if self.check(&TokenKind::Finally) {
813 self.advance();
814 self.consume(&TokenKind::LBrace, "{")?;
815 let fb = self.parse_block()?;
816 self.consume(&TokenKind::RBrace, "}")?;
817 Some(fb)
818 } else {
819 None
820 };
821
822 if !has_catch && finally_body.is_none() {
824 return Ok(spanned(
825 Node::TryExpr { body },
826 Span::merge(start, self.prev_span()),
827 ));
828 }
829
830 Ok(spanned(
831 Node::TryCatch {
832 body,
833 error_var,
834 error_type,
835 catch_body,
836 finally_body,
837 },
838 Span::merge(start, self.prev_span()),
839 ))
840 }
841
842 fn parse_select(&mut self) -> Result<SNode, ParserError> {
843 let start = self.current_span();
844 self.consume(&TokenKind::Select, "select")?;
845 self.consume(&TokenKind::LBrace, "{")?;
846 self.skip_newlines();
847
848 let mut cases = Vec::new();
849 let mut timeout = None;
850 let mut default_body = None;
851
852 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
853 self.skip_newlines();
854 if let Some(tok) = self.current() {
856 if let TokenKind::Identifier(ref id) = tok.kind {
857 if id == "timeout" {
858 self.advance();
859 let duration = self.parse_expression()?;
860 self.consume(&TokenKind::LBrace, "{")?;
861 let body = self.parse_block()?;
862 self.consume(&TokenKind::RBrace, "}")?;
863 timeout = Some((Box::new(duration), body));
864 self.skip_newlines();
865 continue;
866 }
867 if id == "default" {
868 self.advance();
869 self.consume(&TokenKind::LBrace, "{")?;
870 let body = self.parse_block()?;
871 self.consume(&TokenKind::RBrace, "}")?;
872 default_body = Some(body);
873 self.skip_newlines();
874 continue;
875 }
876 }
877 }
878 let variable = self.consume_identifier("select case variable")?;
880 self.consume(&TokenKind::From, "from")?;
881 let channel = self.parse_expression()?;
882 self.consume(&TokenKind::LBrace, "{")?;
883 let body = self.parse_block()?;
884 self.consume(&TokenKind::RBrace, "}")?;
885 cases.push(SelectCase {
886 variable,
887 channel: Box::new(channel),
888 body,
889 });
890 self.skip_newlines();
891 }
892
893 self.consume(&TokenKind::RBrace, "}")?;
894
895 if cases.is_empty() && timeout.is_none() && default_body.is_none() {
896 return Err(self.error("at least one select case"));
897 }
898 if timeout.is_some() && default_body.is_some() {
899 return Err(self.error("select cannot have both timeout and default"));
900 }
901
902 Ok(spanned(
903 Node::SelectExpr {
904 cases,
905 timeout,
906 default_body,
907 },
908 Span::merge(start, self.prev_span()),
909 ))
910 }
911
912 fn parse_fn_decl_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
913 let start = self.current_span();
914 self.consume(&TokenKind::Fn, "fn")?;
915 let name = self.consume_identifier("function name")?;
916
917 let type_params = if self.check(&TokenKind::Lt) {
919 self.advance(); self.parse_type_param_list()?
921 } else {
922 Vec::new()
923 };
924
925 self.consume(&TokenKind::LParen, "(")?;
926 let params = self.parse_typed_param_list()?;
927 self.consume(&TokenKind::RParen, ")")?;
928 let return_type = if self.check(&TokenKind::Arrow) {
930 self.advance();
931 Some(self.parse_type_expr()?)
932 } else {
933 None
934 };
935
936 let where_clauses = self.parse_where_clauses()?;
938
939 self.consume(&TokenKind::LBrace, "{")?;
940 let body = self.parse_block()?;
941 self.consume(&TokenKind::RBrace, "}")?;
942 Ok(spanned(
943 Node::FnDecl {
944 name,
945 type_params,
946 params,
947 return_type,
948 where_clauses,
949 body,
950 is_pub,
951 },
952 Span::merge(start, self.prev_span()),
953 ))
954 }
955
956 fn parse_tool_decl(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
957 let start = self.current_span();
958 self.consume(&TokenKind::Tool, "tool")?;
959 let name = self.consume_identifier("tool name")?;
960
961 self.consume(&TokenKind::LParen, "(")?;
962 let params = self.parse_typed_param_list()?;
963 self.consume(&TokenKind::RParen, ")")?;
964
965 let return_type = if self.check(&TokenKind::Arrow) {
967 self.advance();
968 Some(self.parse_type_expr()?)
969 } else {
970 None
971 };
972
973 self.consume(&TokenKind::LBrace, "{")?;
974
975 self.skip_newlines();
977 let mut description = None;
978 if let Some(TokenKind::Identifier(id)) = self.current_kind().cloned() {
979 if id == "description" {
980 let saved_pos = self.pos;
982 self.advance(); self.skip_newlines();
984 if let Some(TokenKind::StringLiteral(s)) = self.current_kind().cloned() {
985 description = Some(s);
986 self.advance(); } else {
988 self.pos = saved_pos;
990 }
991 }
992 }
993
994 let body = self.parse_block()?;
995 self.consume(&TokenKind::RBrace, "}")?;
996
997 Ok(spanned(
998 Node::ToolDecl {
999 name,
1000 description,
1001 params,
1002 return_type,
1003 body,
1004 is_pub,
1005 },
1006 Span::merge(start, self.prev_span()),
1007 ))
1008 }
1009
1010 fn parse_type_decl(&mut self) -> Result<SNode, ParserError> {
1011 let start = self.current_span();
1012 self.consume(&TokenKind::TypeKw, "type")?;
1013 let name = self.consume_identifier("type name")?;
1014 self.consume(&TokenKind::Assign, "=")?;
1015 let type_expr = self.parse_type_expr()?;
1016 Ok(spanned(
1017 Node::TypeDecl { name, type_expr },
1018 Span::merge(start, self.prev_span()),
1019 ))
1020 }
1021
1022 fn parse_enum_decl_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
1023 let start = self.current_span();
1024 self.consume(&TokenKind::Enum, "enum")?;
1025 let name = self.consume_identifier("enum name")?;
1026 let type_params = if self.check(&TokenKind::Lt) {
1027 self.advance();
1028 self.parse_type_param_list()?
1029 } else {
1030 Vec::new()
1031 };
1032 self.consume(&TokenKind::LBrace, "{")?;
1033 self.skip_newlines();
1034
1035 let mut variants = Vec::new();
1036 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1037 let variant_name = self.consume_identifier("variant name")?;
1038 let fields = if self.check(&TokenKind::LParen) {
1039 self.advance();
1040 let params = self.parse_typed_param_list()?;
1041 self.consume(&TokenKind::RParen, ")")?;
1042 params
1043 } else {
1044 Vec::new()
1045 };
1046 variants.push(EnumVariant {
1047 name: variant_name,
1048 fields,
1049 });
1050 self.skip_newlines();
1051 if self.check(&TokenKind::Comma) {
1052 self.advance();
1053 self.skip_newlines();
1054 }
1055 }
1056
1057 self.consume(&TokenKind::RBrace, "}")?;
1058 Ok(spanned(
1059 Node::EnumDecl {
1060 name,
1061 type_params,
1062 variants,
1063 is_pub,
1064 },
1065 Span::merge(start, self.prev_span()),
1066 ))
1067 }
1068
1069 fn parse_enum_decl(&mut self) -> Result<SNode, ParserError> {
1070 self.parse_enum_decl_with_pub(false)
1071 }
1072
1073 fn parse_struct_decl_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
1074 let start = self.current_span();
1075 self.consume(&TokenKind::Struct, "struct")?;
1076 let name = self.consume_identifier("struct name")?;
1077 self.struct_names.insert(name.clone());
1078 let type_params = if self.check(&TokenKind::Lt) {
1079 self.advance();
1080 self.parse_type_param_list()?
1081 } else {
1082 Vec::new()
1083 };
1084 self.consume(&TokenKind::LBrace, "{")?;
1085 self.skip_newlines();
1086
1087 let mut fields = Vec::new();
1088 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1089 let field_name = self.consume_identifier("field name")?;
1090 let optional = if self.check(&TokenKind::Question) {
1091 self.advance();
1092 true
1093 } else {
1094 false
1095 };
1096 let type_expr = self.try_parse_type_annotation()?;
1097 fields.push(StructField {
1098 name: field_name,
1099 type_expr,
1100 optional,
1101 });
1102 self.skip_newlines();
1103 if self.check(&TokenKind::Comma) {
1104 self.advance();
1105 self.skip_newlines();
1106 }
1107 }
1108
1109 self.consume(&TokenKind::RBrace, "}")?;
1110 Ok(spanned(
1111 Node::StructDecl {
1112 name,
1113 type_params,
1114 fields,
1115 is_pub,
1116 },
1117 Span::merge(start, self.prev_span()),
1118 ))
1119 }
1120
1121 fn parse_struct_decl(&mut self) -> Result<SNode, ParserError> {
1122 self.parse_struct_decl_with_pub(false)
1123 }
1124
1125 fn parse_interface_decl(&mut self) -> Result<SNode, ParserError> {
1126 let start = self.current_span();
1127 self.consume(&TokenKind::Interface, "interface")?;
1128 let name = self.consume_identifier("interface name")?;
1129 let type_params = if self.check(&TokenKind::Lt) {
1130 self.advance();
1131 self.parse_type_param_list()?
1132 } else {
1133 Vec::new()
1134 };
1135 self.consume(&TokenKind::LBrace, "{")?;
1136 self.skip_newlines();
1137
1138 let mut associated_types = Vec::new();
1139 let mut methods = Vec::new();
1140 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1141 if self.check(&TokenKind::TypeKw) {
1142 self.advance();
1143 let assoc_name = self.consume_identifier("associated type name")?;
1144 let assoc_type = if self.check(&TokenKind::Assign) {
1145 self.advance();
1146 Some(self.parse_type_expr()?)
1147 } else {
1148 None
1149 };
1150 associated_types.push((assoc_name, assoc_type));
1151 } else {
1152 self.consume(&TokenKind::Fn, "fn")?;
1153 let method_name = self.consume_identifier("method name")?;
1154 let method_type_params = if self.check(&TokenKind::Lt) {
1155 self.advance();
1156 self.parse_type_param_list()?
1157 } else {
1158 Vec::new()
1159 };
1160 self.consume(&TokenKind::LParen, "(")?;
1161 let params = self.parse_typed_param_list()?;
1162 self.consume(&TokenKind::RParen, ")")?;
1163 let return_type = if self.check(&TokenKind::Arrow) {
1164 self.advance();
1165 Some(self.parse_type_expr()?)
1166 } else {
1167 None
1168 };
1169 methods.push(InterfaceMethod {
1170 name: method_name,
1171 type_params: method_type_params,
1172 params,
1173 return_type,
1174 });
1175 }
1176 self.skip_newlines();
1177 }
1178
1179 self.consume(&TokenKind::RBrace, "}")?;
1180 Ok(spanned(
1181 Node::InterfaceDecl {
1182 name,
1183 type_params,
1184 associated_types,
1185 methods,
1186 },
1187 Span::merge(start, self.prev_span()),
1188 ))
1189 }
1190
1191 fn parse_impl_block(&mut self) -> Result<SNode, ParserError> {
1192 let start = self.current_span();
1193 self.consume(&TokenKind::Impl, "impl")?;
1194 let type_name = self.consume_identifier("type name")?;
1195 self.consume(&TokenKind::LBrace, "{")?;
1196 self.skip_newlines();
1197
1198 let mut methods = Vec::new();
1199 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1200 let is_pub = self.check(&TokenKind::Pub);
1201 if is_pub {
1202 self.advance();
1203 }
1204 let method = self.parse_fn_decl_with_pub(is_pub)?;
1205 methods.push(method);
1206 self.skip_newlines();
1207 }
1208
1209 self.consume(&TokenKind::RBrace, "}")?;
1210 Ok(spanned(
1211 Node::ImplBlock { type_name, methods },
1212 Span::merge(start, self.prev_span()),
1213 ))
1214 }
1215
1216 fn parse_guard(&mut self) -> Result<SNode, ParserError> {
1217 let start = self.current_span();
1218 self.consume(&TokenKind::Guard, "guard")?;
1219 let condition = self.parse_expression()?;
1220 self.consume(&TokenKind::Else, "else")?;
1222 self.consume(&TokenKind::LBrace, "{")?;
1223 let else_body = self.parse_block()?;
1224 self.consume(&TokenKind::RBrace, "}")?;
1225 Ok(spanned(
1226 Node::GuardStmt {
1227 condition: Box::new(condition),
1228 else_body,
1229 },
1230 Span::merge(start, self.prev_span()),
1231 ))
1232 }
1233
1234 fn parse_require(&mut self) -> Result<SNode, ParserError> {
1235 let start = self.current_span();
1236 self.consume(&TokenKind::Require, "require")?;
1237 let condition = self.parse_expression()?;
1238 let message = if self.check(&TokenKind::Comma) {
1239 self.advance();
1240 Some(Box::new(self.parse_expression()?))
1241 } else {
1242 None
1243 };
1244 Ok(spanned(
1245 Node::RequireStmt {
1246 condition: Box::new(condition),
1247 message,
1248 },
1249 Span::merge(start, self.prev_span()),
1250 ))
1251 }
1252
1253 fn parse_deadline(&mut self) -> Result<SNode, ParserError> {
1254 let start = self.current_span();
1255 self.consume(&TokenKind::Deadline, "deadline")?;
1256 let duration = self.parse_primary()?;
1257 self.consume(&TokenKind::LBrace, "{")?;
1258 let body = self.parse_block()?;
1259 self.consume(&TokenKind::RBrace, "}")?;
1260 Ok(spanned(
1261 Node::DeadlineBlock {
1262 duration: Box::new(duration),
1263 body,
1264 },
1265 Span::merge(start, self.prev_span()),
1266 ))
1267 }
1268
1269 fn parse_yield(&mut self) -> Result<SNode, ParserError> {
1270 let start = self.current_span();
1271 self.consume(&TokenKind::Yield, "yield")?;
1272 if self.is_at_end() || self.check(&TokenKind::Newline) || self.check(&TokenKind::RBrace) {
1273 return Ok(spanned(
1274 Node::YieldExpr { value: None },
1275 Span::merge(start, self.prev_span()),
1276 ));
1277 }
1278 let value = self.parse_expression()?;
1279 Ok(spanned(
1280 Node::YieldExpr {
1281 value: Some(Box::new(value)),
1282 },
1283 Span::merge(start, self.prev_span()),
1284 ))
1285 }
1286
1287 fn parse_mutex(&mut self) -> Result<SNode, ParserError> {
1288 let start = self.current_span();
1289 self.consume(&TokenKind::Mutex, "mutex")?;
1290 self.consume(&TokenKind::LBrace, "{")?;
1291 let body = self.parse_block()?;
1292 self.consume(&TokenKind::RBrace, "}")?;
1293 Ok(spanned(
1294 Node::MutexBlock { body },
1295 Span::merge(start, self.prev_span()),
1296 ))
1297 }
1298
1299 fn parse_defer(&mut self) -> Result<SNode, ParserError> {
1300 let start = self.current_span();
1301 self.consume(&TokenKind::Defer, "defer")?;
1302 self.consume(&TokenKind::LBrace, "{")?;
1303 let body = self.parse_block()?;
1304 self.consume(&TokenKind::RBrace, "}")?;
1305 Ok(spanned(
1306 Node::DeferStmt { body },
1307 Span::merge(start, self.prev_span()),
1308 ))
1309 }
1310
1311 fn parse_expression_statement(&mut self) -> Result<SNode, ParserError> {
1314 let start = self.current_span();
1315 let expr = self.parse_expression()?;
1316
1317 let is_assignable = matches!(
1320 expr.node,
1321 Node::Identifier(_) | Node::PropertyAccess { .. } | Node::SubscriptAccess { .. }
1322 );
1323 if is_assignable {
1324 if self.check(&TokenKind::Assign) {
1325 self.advance();
1326 let value = self.parse_expression()?;
1327 return Ok(spanned(
1328 Node::Assignment {
1329 target: Box::new(expr),
1330 value: Box::new(value),
1331 op: None,
1332 },
1333 Span::merge(start, self.prev_span()),
1334 ));
1335 }
1336 let compound_op = if self.check(&TokenKind::PlusAssign) {
1337 Some("+")
1338 } else if self.check(&TokenKind::MinusAssign) {
1339 Some("-")
1340 } else if self.check(&TokenKind::StarAssign) {
1341 Some("*")
1342 } else if self.check(&TokenKind::SlashAssign) {
1343 Some("/")
1344 } else if self.check(&TokenKind::PercentAssign) {
1345 Some("%")
1346 } else {
1347 None
1348 };
1349 if let Some(op) = compound_op {
1350 self.advance();
1351 let value = self.parse_expression()?;
1352 return Ok(spanned(
1353 Node::Assignment {
1354 target: Box::new(expr),
1355 value: Box::new(value),
1356 op: Some(op.into()),
1357 },
1358 Span::merge(start, self.prev_span()),
1359 ));
1360 }
1361 }
1362
1363 Ok(expr)
1364 }
1365
1366 fn parse_expression(&mut self) -> Result<SNode, ParserError> {
1367 self.skip_newlines();
1368 self.parse_pipe()
1369 }
1370
1371 fn parse_pipe(&mut self) -> Result<SNode, ParserError> {
1372 let mut left = self.parse_range()?;
1373 while self.check_skip_newlines(&TokenKind::Pipe) {
1374 let start = left.span;
1375 self.advance();
1376 let right = self.parse_range()?;
1377 left = spanned(
1378 Node::BinaryOp {
1379 op: "|>".into(),
1380 left: Box::new(left),
1381 right: Box::new(right),
1382 },
1383 Span::merge(start, self.prev_span()),
1384 );
1385 }
1386 Ok(left)
1387 }
1388
1389 fn parse_range(&mut self) -> Result<SNode, ParserError> {
1390 let left = self.parse_ternary()?;
1391 if self.check(&TokenKind::To) {
1392 let start = left.span;
1393 self.advance();
1394 let right = self.parse_ternary()?;
1395 let inclusive = if self.check(&TokenKind::Exclusive) {
1396 self.advance();
1397 false
1398 } else {
1399 true
1400 };
1401 return Ok(spanned(
1402 Node::RangeExpr {
1403 start: Box::new(left),
1404 end: Box::new(right),
1405 inclusive,
1406 },
1407 Span::merge(start, self.prev_span()),
1408 ));
1409 }
1410 Ok(left)
1411 }
1412
1413 fn parse_ternary(&mut self) -> Result<SNode, ParserError> {
1414 let condition = self.parse_logical_or()?;
1415 if !self.check(&TokenKind::Question) {
1416 return Ok(condition);
1417 }
1418 let start = condition.span;
1419 self.advance(); let true_val = self.parse_logical_or()?;
1421 self.consume(&TokenKind::Colon, ":")?;
1422 let false_val = self.parse_logical_or()?;
1423 Ok(spanned(
1424 Node::Ternary {
1425 condition: Box::new(condition),
1426 true_expr: Box::new(true_val),
1427 false_expr: Box::new(false_val),
1428 },
1429 Span::merge(start, self.prev_span()),
1430 ))
1431 }
1432
1433 fn parse_nil_coalescing(&mut self) -> Result<SNode, ParserError> {
1441 let mut left = self.parse_multiplicative()?;
1442 while self.check(&TokenKind::NilCoal) {
1443 let start = left.span;
1444 self.advance();
1445 let right = self.parse_multiplicative()?;
1446 left = spanned(
1447 Node::BinaryOp {
1448 op: "??".into(),
1449 left: Box::new(left),
1450 right: Box::new(right),
1451 },
1452 Span::merge(start, self.prev_span()),
1453 );
1454 }
1455 Ok(left)
1456 }
1457
1458 fn parse_logical_or(&mut self) -> Result<SNode, ParserError> {
1459 let mut left = self.parse_logical_and()?;
1460 while self.check_skip_newlines(&TokenKind::Or) {
1461 let start = left.span;
1462 self.advance();
1463 let right = self.parse_logical_and()?;
1464 left = spanned(
1465 Node::BinaryOp {
1466 op: "||".into(),
1467 left: Box::new(left),
1468 right: Box::new(right),
1469 },
1470 Span::merge(start, self.prev_span()),
1471 );
1472 }
1473 Ok(left)
1474 }
1475
1476 fn parse_logical_and(&mut self) -> Result<SNode, ParserError> {
1477 let mut left = self.parse_equality()?;
1478 while self.check_skip_newlines(&TokenKind::And) {
1479 let start = left.span;
1480 self.advance();
1481 let right = self.parse_equality()?;
1482 left = spanned(
1483 Node::BinaryOp {
1484 op: "&&".into(),
1485 left: Box::new(left),
1486 right: Box::new(right),
1487 },
1488 Span::merge(start, self.prev_span()),
1489 );
1490 }
1491 Ok(left)
1492 }
1493
1494 fn parse_equality(&mut self) -> Result<SNode, ParserError> {
1495 let mut left = self.parse_comparison()?;
1496 while self.check(&TokenKind::Eq) || self.check(&TokenKind::Neq) {
1497 let start = left.span;
1498 let op = if self.check(&TokenKind::Eq) {
1499 "=="
1500 } else {
1501 "!="
1502 };
1503 self.advance();
1504 let right = self.parse_comparison()?;
1505 left = spanned(
1506 Node::BinaryOp {
1507 op: op.into(),
1508 left: Box::new(left),
1509 right: Box::new(right),
1510 },
1511 Span::merge(start, self.prev_span()),
1512 );
1513 }
1514 Ok(left)
1515 }
1516
1517 fn parse_comparison(&mut self) -> Result<SNode, ParserError> {
1518 let mut left = self.parse_additive()?;
1519 loop {
1520 if self.check(&TokenKind::Lt)
1521 || self.check(&TokenKind::Gt)
1522 || self.check(&TokenKind::Lte)
1523 || self.check(&TokenKind::Gte)
1524 {
1525 let start = left.span;
1526 let op = match self.current().map(|t| &t.kind) {
1527 Some(TokenKind::Lt) => "<",
1528 Some(TokenKind::Gt) => ">",
1529 Some(TokenKind::Lte) => "<=",
1530 Some(TokenKind::Gte) => ">=",
1531 _ => "<",
1532 };
1533 self.advance();
1534 let right = self.parse_additive()?;
1535 left = spanned(
1536 Node::BinaryOp {
1537 op: op.into(),
1538 left: Box::new(left),
1539 right: Box::new(right),
1540 },
1541 Span::merge(start, self.prev_span()),
1542 );
1543 } else if self.check(&TokenKind::In) {
1544 let start = left.span;
1545 self.advance();
1546 let right = self.parse_additive()?;
1547 left = spanned(
1548 Node::BinaryOp {
1549 op: "in".into(),
1550 left: Box::new(left),
1551 right: Box::new(right),
1552 },
1553 Span::merge(start, self.prev_span()),
1554 );
1555 } else if self.check_identifier("not") {
1556 let saved = self.pos;
1558 self.advance(); if self.check(&TokenKind::In) {
1560 let start = left.span;
1561 self.advance(); let right = self.parse_additive()?;
1563 left = spanned(
1564 Node::BinaryOp {
1565 op: "not_in".into(),
1566 left: Box::new(left),
1567 right: Box::new(right),
1568 },
1569 Span::merge(start, self.prev_span()),
1570 );
1571 } else {
1572 self.pos = saved;
1573 break;
1574 }
1575 } else {
1576 break;
1577 }
1578 }
1579 Ok(left)
1580 }
1581
1582 fn parse_additive(&mut self) -> Result<SNode, ParserError> {
1583 let mut left = self.parse_nil_coalescing()?;
1584 while self.check_skip_newlines(&TokenKind::Plus) || self.check(&TokenKind::Minus) {
1585 let start = left.span;
1586 let op = if self.check(&TokenKind::Plus) {
1587 "+"
1588 } else {
1589 "-"
1590 };
1591 self.advance();
1592 let right = self.parse_nil_coalescing()?;
1593 left = spanned(
1594 Node::BinaryOp {
1595 op: op.into(),
1596 left: Box::new(left),
1597 right: Box::new(right),
1598 },
1599 Span::merge(start, self.prev_span()),
1600 );
1601 }
1602 Ok(left)
1603 }
1604
1605 fn parse_multiplicative(&mut self) -> Result<SNode, ParserError> {
1606 let mut left = self.parse_exponent()?;
1607 while self.check_skip_newlines(&TokenKind::Star)
1608 || self.check_skip_newlines(&TokenKind::Slash)
1609 || self.check_skip_newlines(&TokenKind::Percent)
1610 {
1611 let start = left.span;
1612 let op = if self.check(&TokenKind::Star) {
1613 "*"
1614 } else if self.check(&TokenKind::Slash) {
1615 "/"
1616 } else {
1617 "%"
1618 };
1619 self.advance();
1620 let right = self.parse_exponent()?;
1621 left = spanned(
1622 Node::BinaryOp {
1623 op: op.into(),
1624 left: Box::new(left),
1625 right: Box::new(right),
1626 },
1627 Span::merge(start, self.prev_span()),
1628 );
1629 }
1630 Ok(left)
1631 }
1632
1633 fn parse_exponent(&mut self) -> Result<SNode, ParserError> {
1634 let left = self.parse_unary()?;
1635 if !self.check_skip_newlines(&TokenKind::Pow) {
1636 return Ok(left);
1637 }
1638
1639 let start = left.span;
1640 self.advance();
1641 let right = self.parse_exponent()?;
1642 Ok(spanned(
1643 Node::BinaryOp {
1644 op: "**".into(),
1645 left: Box::new(left),
1646 right: Box::new(right),
1647 },
1648 Span::merge(start, self.prev_span()),
1649 ))
1650 }
1651
1652 fn parse_unary(&mut self) -> Result<SNode, ParserError> {
1653 if self.check(&TokenKind::Not) {
1654 let start = self.current_span();
1655 self.advance();
1656 let operand = self.parse_unary()?;
1657 return Ok(spanned(
1658 Node::UnaryOp {
1659 op: "!".into(),
1660 operand: Box::new(operand),
1661 },
1662 Span::merge(start, self.prev_span()),
1663 ));
1664 }
1665 if self.check(&TokenKind::Minus) {
1666 let start = self.current_span();
1667 self.advance();
1668 let operand = self.parse_unary()?;
1669 return Ok(spanned(
1670 Node::UnaryOp {
1671 op: "-".into(),
1672 operand: Box::new(operand),
1673 },
1674 Span::merge(start, self.prev_span()),
1675 ));
1676 }
1677 self.parse_postfix()
1678 }
1679
1680 fn parse_postfix(&mut self) -> Result<SNode, ParserError> {
1681 let mut expr = self.parse_primary()?;
1682
1683 loop {
1684 if self.check_skip_newlines(&TokenKind::Dot)
1685 || self.check_skip_newlines(&TokenKind::QuestionDot)
1686 {
1687 let optional = self.check(&TokenKind::QuestionDot);
1688 let start = expr.span;
1689 self.advance();
1690 let member = self.consume_identifier_or_keyword("member name")?;
1691 if self.check(&TokenKind::LParen) {
1692 self.advance();
1693 let args = self.parse_arg_list()?;
1694 self.consume(&TokenKind::RParen, ")")?;
1695 if optional {
1696 expr = spanned(
1697 Node::OptionalMethodCall {
1698 object: Box::new(expr),
1699 method: member,
1700 args,
1701 },
1702 Span::merge(start, self.prev_span()),
1703 );
1704 } else {
1705 expr = spanned(
1706 Node::MethodCall {
1707 object: Box::new(expr),
1708 method: member,
1709 args,
1710 },
1711 Span::merge(start, self.prev_span()),
1712 );
1713 }
1714 } else if optional {
1715 expr = spanned(
1716 Node::OptionalPropertyAccess {
1717 object: Box::new(expr),
1718 property: member,
1719 },
1720 Span::merge(start, self.prev_span()),
1721 );
1722 } else {
1723 expr = spanned(
1724 Node::PropertyAccess {
1725 object: Box::new(expr),
1726 property: member,
1727 },
1728 Span::merge(start, self.prev_span()),
1729 );
1730 }
1731 } else if self.check(&TokenKind::LBracket) {
1732 let start = expr.span;
1733 self.advance();
1734
1735 if self.check(&TokenKind::Colon) {
1740 self.advance(); let end_expr = if self.check(&TokenKind::RBracket) {
1743 None
1744 } else {
1745 Some(Box::new(self.parse_expression()?))
1746 };
1747 self.consume(&TokenKind::RBracket, "]")?;
1748 expr = spanned(
1749 Node::SliceAccess {
1750 object: Box::new(expr),
1751 start: None,
1752 end: end_expr,
1753 },
1754 Span::merge(start, self.prev_span()),
1755 );
1756 } else {
1757 let index = self.parse_expression()?;
1758 if self.check(&TokenKind::Colon) {
1759 self.advance(); let end_expr = if self.check(&TokenKind::RBracket) {
1762 None
1763 } else {
1764 Some(Box::new(self.parse_expression()?))
1765 };
1766 self.consume(&TokenKind::RBracket, "]")?;
1767 expr = spanned(
1768 Node::SliceAccess {
1769 object: Box::new(expr),
1770 start: Some(Box::new(index)),
1771 end: end_expr,
1772 },
1773 Span::merge(start, self.prev_span()),
1774 );
1775 } else {
1776 self.consume(&TokenKind::RBracket, "]")?;
1777 expr = spanned(
1778 Node::SubscriptAccess {
1779 object: Box::new(expr),
1780 index: Box::new(index),
1781 },
1782 Span::merge(start, self.prev_span()),
1783 );
1784 }
1785 }
1786 } else if self.check(&TokenKind::LBrace)
1787 && matches!(&expr.node, Node::Identifier(name) if self.struct_names.contains(name))
1788 {
1789 let start = expr.span;
1790 let struct_name = match expr.node {
1791 Node::Identifier(name) => name,
1792 _ => unreachable!("checked above"),
1793 };
1794 self.advance();
1795 let dict = self.parse_dict_literal(start)?;
1796 let fields = match dict.node {
1797 Node::DictLiteral(fields) => fields,
1798 _ => unreachable!("dict parser must return a dict literal"),
1799 };
1800 expr = spanned(
1801 Node::StructConstruct {
1802 struct_name,
1803 fields,
1804 },
1805 dict.span,
1806 );
1807 } else if self.check(&TokenKind::LParen) && matches!(expr.node, Node::Identifier(_)) {
1808 let start = expr.span;
1809 self.advance();
1810 let args = self.parse_arg_list()?;
1811 self.consume(&TokenKind::RParen, ")")?;
1812 if let Node::Identifier(name) = expr.node {
1813 expr = spanned(
1814 Node::FunctionCall { name, args },
1815 Span::merge(start, self.prev_span()),
1816 );
1817 }
1818 } else if self.check(&TokenKind::Question) {
1819 let next_pos = self.pos + 1;
1822 let is_ternary = self.tokens.get(next_pos).is_some_and(|t| {
1823 matches!(
1824 t.kind,
1825 TokenKind::Identifier(_)
1826 | TokenKind::IntLiteral(_)
1827 | TokenKind::FloatLiteral(_)
1828 | TokenKind::StringLiteral(_)
1829 | TokenKind::InterpolatedString(_)
1830 | TokenKind::True
1831 | TokenKind::False
1832 | TokenKind::Nil
1833 | TokenKind::LParen
1834 | TokenKind::LBracket
1835 | TokenKind::LBrace
1836 | TokenKind::Not
1837 | TokenKind::Minus
1838 | TokenKind::Fn
1839 )
1840 });
1841 if is_ternary {
1842 break;
1843 }
1844 let start = expr.span;
1845 self.advance(); expr = spanned(
1847 Node::TryOperator {
1848 operand: Box::new(expr),
1849 },
1850 Span::merge(start, self.prev_span()),
1851 );
1852 } else {
1853 break;
1854 }
1855 }
1856
1857 Ok(expr)
1858 }
1859
1860 fn parse_primary(&mut self) -> Result<SNode, ParserError> {
1861 let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
1862 expected: "expression".into(),
1863 span: self.prev_span(),
1864 })?;
1865 let start = self.current_span();
1866
1867 match &tok.kind {
1868 TokenKind::StringLiteral(s) => {
1869 let s = s.clone();
1870 self.advance();
1871 Ok(spanned(
1872 Node::StringLiteral(s),
1873 Span::merge(start, self.prev_span()),
1874 ))
1875 }
1876 TokenKind::RawStringLiteral(s) => {
1877 let s = s.clone();
1878 self.advance();
1879 Ok(spanned(
1880 Node::RawStringLiteral(s),
1881 Span::merge(start, self.prev_span()),
1882 ))
1883 }
1884 TokenKind::InterpolatedString(segments) => {
1885 let segments = segments.clone();
1886 self.advance();
1887 Ok(spanned(
1888 Node::InterpolatedString(segments),
1889 Span::merge(start, self.prev_span()),
1890 ))
1891 }
1892 TokenKind::IntLiteral(n) => {
1893 let n = *n;
1894 self.advance();
1895 Ok(spanned(
1896 Node::IntLiteral(n),
1897 Span::merge(start, self.prev_span()),
1898 ))
1899 }
1900 TokenKind::FloatLiteral(n) => {
1901 let n = *n;
1902 self.advance();
1903 Ok(spanned(
1904 Node::FloatLiteral(n),
1905 Span::merge(start, self.prev_span()),
1906 ))
1907 }
1908 TokenKind::True => {
1909 self.advance();
1910 Ok(spanned(
1911 Node::BoolLiteral(true),
1912 Span::merge(start, self.prev_span()),
1913 ))
1914 }
1915 TokenKind::False => {
1916 self.advance();
1917 Ok(spanned(
1918 Node::BoolLiteral(false),
1919 Span::merge(start, self.prev_span()),
1920 ))
1921 }
1922 TokenKind::Nil => {
1923 self.advance();
1924 Ok(spanned(
1925 Node::NilLiteral,
1926 Span::merge(start, self.prev_span()),
1927 ))
1928 }
1929 TokenKind::Identifier(name) => {
1930 let name = name.clone();
1931 self.advance();
1932 Ok(spanned(
1933 Node::Identifier(name),
1934 Span::merge(start, self.prev_span()),
1935 ))
1936 }
1937 TokenKind::LParen => {
1938 self.advance();
1939 let expr = self.parse_expression()?;
1940 self.consume(&TokenKind::RParen, ")")?;
1941 Ok(expr)
1942 }
1943 TokenKind::LBracket => self.parse_list_literal(),
1944 TokenKind::LBrace => self.parse_dict_or_closure(),
1945 TokenKind::Parallel => self.parse_parallel(),
1946 TokenKind::Retry => self.parse_retry(),
1947 TokenKind::If => self.parse_if_else(),
1948 TokenKind::Spawn => self.parse_spawn_expr(),
1949 TokenKind::DurationLiteral(ms) => {
1950 let ms = *ms;
1951 self.advance();
1952 Ok(spanned(
1953 Node::DurationLiteral(ms),
1954 Span::merge(start, self.prev_span()),
1955 ))
1956 }
1957 TokenKind::Deadline => self.parse_deadline(),
1958 TokenKind::Try => self.parse_try_catch(),
1959 TokenKind::Match => self.parse_match(),
1960 TokenKind::Fn => self.parse_fn_expr(),
1961 TokenKind::Lt
1966 if matches!(self.peek_kind(), Some(&TokenKind::Lt))
1967 && matches!(self.peek_kind_at(2), Some(TokenKind::Identifier(_))) =>
1968 {
1969 Err(ParserError::Unexpected {
1970 got: "`<<` heredoc-like syntax".to_string(),
1971 expected: "an expression — heredocs are only valid \
1972 inside LLM tool-call argument JSON; \
1973 for multiline strings in source code use \
1974 triple-quoted `\"\"\"...\"\"\"`"
1975 .to_string(),
1976 span: start,
1977 })
1978 }
1979 _ => Err(self.error("expression")),
1980 }
1981 }
1982
1983 fn parse_fn_expr(&mut self) -> Result<SNode, ParserError> {
1987 let start = self.current_span();
1988 self.consume(&TokenKind::Fn, "fn")?;
1989 self.consume(&TokenKind::LParen, "(")?;
1990 let params = self.parse_typed_param_list()?;
1991 self.consume(&TokenKind::RParen, ")")?;
1992 self.consume(&TokenKind::LBrace, "{")?;
1993 let body = self.parse_block()?;
1994 self.consume(&TokenKind::RBrace, "}")?;
1995 Ok(spanned(
1996 Node::Closure {
1997 params,
1998 body,
1999 fn_syntax: true,
2000 },
2001 Span::merge(start, self.prev_span()),
2002 ))
2003 }
2004
2005 fn parse_spawn_expr(&mut self) -> Result<SNode, ParserError> {
2006 let start = self.current_span();
2007 self.consume(&TokenKind::Spawn, "spawn")?;
2008 self.consume(&TokenKind::LBrace, "{")?;
2009 let body = self.parse_block()?;
2010 self.consume(&TokenKind::RBrace, "}")?;
2011 Ok(spanned(
2012 Node::SpawnExpr { body },
2013 Span::merge(start, self.prev_span()),
2014 ))
2015 }
2016
2017 fn parse_list_literal(&mut self) -> Result<SNode, ParserError> {
2018 let start = self.current_span();
2019 self.consume(&TokenKind::LBracket, "[")?;
2020 let mut elements = Vec::new();
2021 self.skip_newlines();
2022
2023 while !self.is_at_end() && !self.check(&TokenKind::RBracket) {
2024 if self.check(&TokenKind::Dot) {
2026 let saved_pos = self.pos;
2027 self.advance(); if self.check(&TokenKind::Dot) {
2029 self.advance(); self.consume(&TokenKind::Dot, ".")?; let spread_start = self.tokens[saved_pos].span;
2032 let expr = self.parse_expression()?;
2033 elements.push(spanned(
2034 Node::Spread(Box::new(expr)),
2035 Span::merge(spread_start, self.prev_span()),
2036 ));
2037 } else {
2038 self.pos = saved_pos;
2040 elements.push(self.parse_expression()?);
2041 }
2042 } else {
2043 elements.push(self.parse_expression()?);
2044 }
2045 self.skip_newlines();
2046 if self.check(&TokenKind::Comma) {
2047 self.advance();
2048 self.skip_newlines();
2049 }
2050 }
2051
2052 self.consume(&TokenKind::RBracket, "]")?;
2053 Ok(spanned(
2054 Node::ListLiteral(elements),
2055 Span::merge(start, self.prev_span()),
2056 ))
2057 }
2058
2059 fn parse_dict_or_closure(&mut self) -> Result<SNode, ParserError> {
2060 let start = self.current_span();
2061 self.consume(&TokenKind::LBrace, "{")?;
2062 self.skip_newlines();
2063
2064 if self.check(&TokenKind::RBrace) {
2066 self.advance();
2067 return Ok(spanned(
2068 Node::DictLiteral(Vec::new()),
2069 Span::merge(start, self.prev_span()),
2070 ));
2071 }
2072
2073 let saved = self.pos;
2075 if self.is_closure_lookahead() {
2076 self.pos = saved;
2077 return self.parse_closure_body(start);
2078 }
2079 self.pos = saved;
2080 self.parse_dict_literal(start)
2081 }
2082
2083 fn is_closure_lookahead(&mut self) -> bool {
2086 let mut depth = 0;
2087 while !self.is_at_end() {
2088 if let Some(tok) = self.current() {
2089 match &tok.kind {
2090 TokenKind::Arrow if depth == 0 => return true,
2091 TokenKind::LBrace | TokenKind::LParen | TokenKind::LBracket => depth += 1,
2092 TokenKind::RBrace if depth == 0 => return false,
2093 TokenKind::RBrace => depth -= 1,
2094 TokenKind::RParen | TokenKind::RBracket => {
2095 if depth > 0 {
2096 depth -= 1;
2097 }
2098 }
2099 _ => {}
2100 }
2101 self.advance();
2102 } else {
2103 return false;
2104 }
2105 }
2106 false
2107 }
2108
2109 fn parse_closure_body(&mut self, start: Span) -> Result<SNode, ParserError> {
2111 let params = self.parse_typed_param_list_until_arrow()?;
2112 self.consume(&TokenKind::Arrow, "->")?;
2113 let body = self.parse_block()?;
2114 self.consume(&TokenKind::RBrace, "}")?;
2115 Ok(spanned(
2116 Node::Closure {
2117 params,
2118 body,
2119 fn_syntax: false,
2120 },
2121 Span::merge(start, self.prev_span()),
2122 ))
2123 }
2124
2125 fn parse_typed_param_list_until_arrow(&mut self) -> Result<Vec<TypedParam>, ParserError> {
2127 self.parse_typed_params_until(|tok| tok == &TokenKind::Arrow)
2128 }
2129
2130 fn parse_dict_literal(&mut self, start: Span) -> Result<SNode, ParserError> {
2131 let entries = self.parse_dict_entries()?;
2132 Ok(spanned(
2133 Node::DictLiteral(entries),
2134 Span::merge(start, self.prev_span()),
2135 ))
2136 }
2137
2138 fn parse_dict_entries(&mut self) -> Result<Vec<DictEntry>, ParserError> {
2139 let mut entries = Vec::new();
2140 self.skip_newlines();
2141
2142 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
2143 if self.check(&TokenKind::Dot) {
2145 let saved_pos = self.pos;
2146 self.advance(); if self.check(&TokenKind::Dot) {
2148 self.advance(); if self.check(&TokenKind::Dot) {
2150 self.advance(); let spread_start = self.tokens[saved_pos].span;
2152 let expr = self.parse_expression()?;
2153 entries.push(DictEntry {
2154 key: spanned(Node::NilLiteral, spread_start),
2155 value: spanned(
2156 Node::Spread(Box::new(expr)),
2157 Span::merge(spread_start, self.prev_span()),
2158 ),
2159 });
2160 self.skip_newlines();
2161 if self.check(&TokenKind::Comma) {
2162 self.advance();
2163 self.skip_newlines();
2164 }
2165 continue;
2166 }
2167 self.pos = saved_pos;
2169 } else {
2170 self.pos = saved_pos;
2171 }
2172 }
2173 let key = if self.check(&TokenKind::LBracket) {
2174 self.advance();
2176 let k = self.parse_expression()?;
2177 self.consume(&TokenKind::RBracket, "]")?;
2178 k
2179 } else if matches!(
2180 self.current().map(|t| &t.kind),
2181 Some(TokenKind::StringLiteral(_))
2182 ) {
2183 let key_span = self.current_span();
2185 let name =
2186 if let Some(TokenKind::StringLiteral(s)) = self.current().map(|t| &t.kind) {
2187 s.clone()
2188 } else {
2189 unreachable!()
2190 };
2191 self.advance();
2192 spanned(Node::StringLiteral(name), key_span)
2193 } else {
2194 let key_span = self.current_span();
2196 let name = self.consume_identifier_or_keyword("dict key")?;
2197 spanned(Node::StringLiteral(name), key_span)
2198 };
2199 self.consume(&TokenKind::Colon, ":")?;
2200 let value = self.parse_expression()?;
2201 entries.push(DictEntry { key, value });
2202 self.skip_newlines();
2203 if self.check(&TokenKind::Comma) {
2204 self.advance();
2205 self.skip_newlines();
2206 }
2207 }
2208
2209 self.consume(&TokenKind::RBrace, "}")?;
2210 Ok(entries)
2211 }
2212
2213 fn parse_param_list(&mut self) -> Result<Vec<String>, ParserError> {
2217 let mut params = Vec::new();
2218 self.skip_newlines();
2219
2220 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2221 params.push(self.consume_identifier("parameter name")?);
2222 if self.check(&TokenKind::Comma) {
2223 self.advance();
2224 self.skip_newlines();
2225 }
2226 }
2227 Ok(params)
2228 }
2229
2230 fn parse_typed_param_list(&mut self) -> Result<Vec<TypedParam>, ParserError> {
2232 self.parse_typed_params_until(|tok| tok == &TokenKind::RParen)
2233 }
2234
2235 fn parse_typed_params_until(
2238 &mut self,
2239 is_terminator: impl Fn(&TokenKind) -> bool,
2240 ) -> Result<Vec<TypedParam>, ParserError> {
2241 let mut params = Vec::new();
2242 let mut seen_default = false;
2243 self.skip_newlines();
2244
2245 while !self.is_at_end() {
2246 if let Some(tok) = self.current() {
2247 if is_terminator(&tok.kind) {
2248 break;
2249 }
2250 } else {
2251 break;
2252 }
2253 let is_rest = if self.check(&TokenKind::Dot) {
2255 let p1 = self.pos + 1;
2257 let p2 = self.pos + 2;
2258 let is_ellipsis = p1 < self.tokens.len()
2259 && p2 < self.tokens.len()
2260 && self.tokens[p1].kind == TokenKind::Dot
2261 && self.tokens[p2].kind == TokenKind::Dot;
2262 if is_ellipsis {
2263 self.advance(); self.advance(); self.advance(); true
2267 } else {
2268 false
2269 }
2270 } else {
2271 false
2272 };
2273 let name = self.consume_identifier("parameter name")?;
2274 let type_expr = self.try_parse_type_annotation()?;
2275 let default_value = if self.check(&TokenKind::Assign) {
2276 self.advance();
2277 seen_default = true;
2278 Some(Box::new(self.parse_expression()?))
2279 } else {
2280 if seen_default && !is_rest {
2281 return Err(self.error(
2282 "Required parameter cannot follow a parameter with a default value",
2283 ));
2284 }
2285 None
2286 };
2287 if is_rest
2288 && !is_terminator(
2289 &self
2290 .current()
2291 .map(|t| t.kind.clone())
2292 .unwrap_or(TokenKind::Eof),
2293 )
2294 {
2295 return Err(self.error("Rest parameter must be the last parameter"));
2296 }
2297 params.push(TypedParam {
2298 name,
2299 type_expr,
2300 default_value,
2301 rest: is_rest,
2302 });
2303 if self.check(&TokenKind::Comma) {
2304 self.advance();
2305 self.skip_newlines();
2306 }
2307 }
2308 Ok(params)
2309 }
2310
2311 fn parse_type_param_list(&mut self) -> Result<Vec<TypeParam>, ParserError> {
2313 let mut params = Vec::new();
2314 self.skip_newlines();
2315 while !self.is_at_end() && !self.check(&TokenKind::Gt) {
2316 let name = self.consume_identifier("type parameter name")?;
2317 params.push(TypeParam { name });
2318 if self.check(&TokenKind::Comma) {
2319 self.advance();
2320 self.skip_newlines();
2321 }
2322 }
2323 self.consume(&TokenKind::Gt, ">")?;
2324 Ok(params)
2325 }
2326
2327 fn parse_where_clauses(&mut self) -> Result<Vec<WhereClause>, ParserError> {
2330 if let Some(tok) = self.current() {
2332 if let TokenKind::Identifier(ref id) = tok.kind {
2333 if id == "where" {
2334 self.advance(); let mut clauses = Vec::new();
2336 loop {
2337 self.skip_newlines();
2338 if self.check(&TokenKind::LBrace) || self.is_at_end() {
2340 break;
2341 }
2342 let type_name = self.consume_identifier("type parameter name")?;
2343 self.consume(&TokenKind::Colon, ":")?;
2344 let bound = self.consume_identifier("type bound")?;
2345 clauses.push(WhereClause { type_name, bound });
2346 if self.check(&TokenKind::Comma) {
2347 self.advance();
2348 } else {
2349 break;
2350 }
2351 }
2352 return Ok(clauses);
2353 }
2354 }
2355 }
2356 Ok(Vec::new())
2357 }
2358
2359 fn try_parse_type_annotation(&mut self) -> Result<Option<TypeExpr>, ParserError> {
2362 if !self.check(&TokenKind::Colon) {
2363 return Ok(None);
2364 }
2365 self.advance(); Ok(Some(self.parse_type_expr()?))
2367 }
2368
2369 fn parse_type_expr(&mut self) -> Result<TypeExpr, ParserError> {
2371 self.skip_newlines();
2372 let first = self.parse_type_primary()?;
2373
2374 if self.check(&TokenKind::Bar) {
2376 let mut types = vec![first];
2377 while self.check(&TokenKind::Bar) {
2378 self.advance(); types.push(self.parse_type_primary()?);
2380 }
2381 return Ok(TypeExpr::Union(types));
2382 }
2383
2384 Ok(first)
2385 }
2386
2387 fn parse_type_primary(&mut self) -> Result<TypeExpr, ParserError> {
2390 self.skip_newlines();
2391 if self.check(&TokenKind::LBrace) {
2392 return self.parse_shape_type();
2393 }
2394 if let Some(tok) = self.current() {
2396 let type_name = match &tok.kind {
2397 TokenKind::Nil => {
2398 self.advance();
2399 return Ok(TypeExpr::Named("nil".to_string()));
2400 }
2401 TokenKind::True | TokenKind::False => {
2402 self.advance();
2403 return Ok(TypeExpr::Named("bool".to_string()));
2404 }
2405 _ => None,
2406 };
2407 if let Some(name) = type_name {
2408 return Ok(TypeExpr::Named(name));
2409 }
2410 }
2411 if self.check(&TokenKind::Fn) {
2413 self.advance(); self.consume(&TokenKind::LParen, "(")?;
2415 let mut params = Vec::new();
2416 self.skip_newlines();
2417 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2418 params.push(self.parse_type_expr()?);
2419 self.skip_newlines();
2420 if self.check(&TokenKind::Comma) {
2421 self.advance();
2422 self.skip_newlines();
2423 }
2424 }
2425 self.consume(&TokenKind::RParen, ")")?;
2426 self.consume(&TokenKind::Arrow, "->")?;
2427 let return_type = self.parse_type_expr()?;
2428 return Ok(TypeExpr::FnType {
2429 params,
2430 return_type: Box::new(return_type),
2431 });
2432 }
2433 let name = self.consume_identifier("type name")?;
2434 if name == "never" {
2436 return Ok(TypeExpr::Never);
2437 }
2438 if self.check(&TokenKind::Lt) {
2440 self.advance(); let mut type_args = vec![self.parse_type_expr()?];
2442 while self.check(&TokenKind::Comma) {
2443 self.advance();
2444 type_args.push(self.parse_type_expr()?);
2445 }
2446 self.consume(&TokenKind::Gt, ">")?;
2447 if name == "list" && type_args.len() == 1 {
2448 return Ok(TypeExpr::List(Box::new(type_args.remove(0))));
2449 } else if name == "dict" && type_args.len() == 2 {
2450 return Ok(TypeExpr::DictType(
2451 Box::new(type_args.remove(0)),
2452 Box::new(type_args.remove(0)),
2453 ));
2454 } else if (name == "iter" || name == "Iter") && type_args.len() == 1 {
2455 return Ok(TypeExpr::Iter(Box::new(type_args.remove(0))));
2456 }
2457 return Ok(TypeExpr::Applied {
2458 name,
2459 args: type_args,
2460 });
2461 }
2462 Ok(TypeExpr::Named(name))
2463 }
2464
2465 fn parse_shape_type(&mut self) -> Result<TypeExpr, ParserError> {
2467 self.consume(&TokenKind::LBrace, "{")?;
2468 let mut fields = Vec::new();
2469 self.skip_newlines();
2470
2471 while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
2472 let name = self.consume_identifier("field name")?;
2473 let optional = if self.check(&TokenKind::Question) {
2474 self.advance();
2475 true
2476 } else {
2477 false
2478 };
2479 self.consume(&TokenKind::Colon, ":")?;
2480 let type_expr = self.parse_type_expr()?;
2481 fields.push(ShapeField {
2482 name,
2483 type_expr,
2484 optional,
2485 });
2486 self.skip_newlines();
2487 if self.check(&TokenKind::Comma) {
2488 self.advance();
2489 self.skip_newlines();
2490 }
2491 }
2492
2493 self.consume(&TokenKind::RBrace, "}")?;
2494 Ok(TypeExpr::Shape(fields))
2495 }
2496
2497 fn parse_arg_list(&mut self) -> Result<Vec<SNode>, ParserError> {
2498 let mut args = Vec::new();
2499 self.skip_newlines();
2500
2501 while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2502 if self.check(&TokenKind::Dot) {
2504 let saved_pos = self.pos;
2505 self.advance(); if self.check(&TokenKind::Dot) {
2507 self.advance(); self.consume(&TokenKind::Dot, ".")?; let spread_start = self.tokens[saved_pos].span;
2510 let expr = self.parse_expression()?;
2511 args.push(spanned(
2512 Node::Spread(Box::new(expr)),
2513 Span::merge(spread_start, self.prev_span()),
2514 ));
2515 } else {
2516 self.pos = saved_pos;
2518 args.push(self.parse_expression()?);
2519 }
2520 } else {
2521 args.push(self.parse_expression()?);
2522 }
2523 self.skip_newlines();
2524 if self.check(&TokenKind::Comma) {
2525 self.advance();
2526 self.skip_newlines();
2527 }
2528 }
2529 Ok(args)
2530 }
2531
2532 fn is_at_end(&self) -> bool {
2533 self.pos >= self.tokens.len()
2534 || matches!(self.tokens.get(self.pos), Some(t) if t.kind == TokenKind::Eof)
2535 }
2536
2537 fn current(&self) -> Option<&Token> {
2538 self.tokens.get(self.pos)
2539 }
2540
2541 fn peek_kind(&self) -> Option<&TokenKind> {
2542 self.tokens.get(self.pos + 1).map(|t| &t.kind)
2543 }
2544
2545 fn peek_kind_at(&self, offset: usize) -> Option<&TokenKind> {
2546 self.tokens.get(self.pos + offset).map(|t| &t.kind)
2547 }
2548
2549 fn check(&self, kind: &TokenKind) -> bool {
2550 self.current()
2551 .map(|t| std::mem::discriminant(&t.kind) == std::mem::discriminant(kind))
2552 .unwrap_or(false)
2553 }
2554
2555 fn check_skip_newlines(&mut self, kind: &TokenKind) -> bool {
2558 let saved = self.pos;
2559 self.skip_newlines();
2560 if self.check(kind) {
2561 true
2562 } else {
2563 self.pos = saved;
2564 false
2565 }
2566 }
2567
2568 fn check_identifier(&self, name: &str) -> bool {
2570 matches!(self.current().map(|t| &t.kind), Some(TokenKind::Identifier(s)) if s == name)
2571 }
2572
2573 fn advance(&mut self) {
2574 if self.pos < self.tokens.len() {
2575 self.pos += 1;
2576 }
2577 }
2578
2579 fn consume(&mut self, kind: &TokenKind, expected: &str) -> Result<Token, ParserError> {
2580 self.skip_newlines();
2581 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2582 if std::mem::discriminant(&tok.kind) != std::mem::discriminant(kind) {
2583 return Err(self.make_error(expected));
2584 }
2585 let tok = tok.clone();
2586 self.advance();
2587 Ok(tok)
2588 }
2589
2590 fn consume_identifier(&mut self, expected: &str) -> Result<String, ParserError> {
2591 self.skip_newlines();
2592 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2593 if let TokenKind::Identifier(name) = &tok.kind {
2594 let name = name.clone();
2595 self.advance();
2596 Ok(name)
2597 } else {
2598 let kw_name = harn_lexer::KEYWORDS
2601 .iter()
2602 .find(|&&kw| kw == tok.kind.to_string());
2603 if let Some(kw) = kw_name {
2604 Err(ParserError::Unexpected {
2605 got: format!("'{kw}' (reserved keyword)"),
2606 expected: expected.into(),
2607 span: tok.span,
2608 })
2609 } else {
2610 Err(self.make_error(expected))
2611 }
2612 }
2613 }
2614
2615 fn consume_identifier_or_keyword(&mut self, expected: &str) -> Result<String, ParserError> {
2619 self.skip_newlines();
2620 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2621 if let TokenKind::Identifier(name) = &tok.kind {
2622 let name = name.clone();
2623 self.advance();
2624 return Ok(name);
2625 }
2626 let name = match &tok.kind {
2628 TokenKind::Pipeline => "pipeline",
2629 TokenKind::Extends => "extends",
2630 TokenKind::Override => "override",
2631 TokenKind::Let => "let",
2632 TokenKind::Var => "var",
2633 TokenKind::If => "if",
2634 TokenKind::Else => "else",
2635 TokenKind::For => "for",
2636 TokenKind::In => "in",
2637 TokenKind::Match => "match",
2638 TokenKind::Retry => "retry",
2639 TokenKind::Parallel => "parallel",
2640 TokenKind::Return => "return",
2641 TokenKind::Import => "import",
2642 TokenKind::True => "true",
2643 TokenKind::False => "false",
2644 TokenKind::Nil => "nil",
2645 TokenKind::Try => "try",
2646 TokenKind::Catch => "catch",
2647 TokenKind::Throw => "throw",
2648 TokenKind::Fn => "fn",
2649 TokenKind::Spawn => "spawn",
2650 TokenKind::While => "while",
2651 TokenKind::TypeKw => "type",
2652 TokenKind::Enum => "enum",
2653 TokenKind::Struct => "struct",
2654 TokenKind::Interface => "interface",
2655 TokenKind::Pub => "pub",
2656 TokenKind::From => "from",
2657 TokenKind::To => "to",
2658 TokenKind::Tool => "tool",
2659 TokenKind::Exclusive => "exclusive",
2660 TokenKind::Guard => "guard",
2661 TokenKind::Deadline => "deadline",
2662 TokenKind::Defer => "defer",
2663 TokenKind::Yield => "yield",
2664 TokenKind::Mutex => "mutex",
2665 TokenKind::Break => "break",
2666 TokenKind::Continue => "continue",
2667 TokenKind::Impl => "impl",
2668 _ => return Err(self.make_error(expected)),
2669 };
2670 let name = name.to_string();
2671 self.advance();
2672 Ok(name)
2673 }
2674
2675 fn skip_newlines(&mut self) {
2676 while self.pos < self.tokens.len() && self.tokens[self.pos].kind == TokenKind::Newline {
2677 self.pos += 1;
2678 }
2679 }
2680
2681 fn make_error(&self, expected: &str) -> ParserError {
2682 if let Some(tok) = self.tokens.get(self.pos) {
2683 if tok.kind == TokenKind::Eof {
2684 return ParserError::UnexpectedEof {
2685 expected: expected.into(),
2686 span: tok.span,
2687 };
2688 }
2689 ParserError::Unexpected {
2690 got: tok.kind.to_string(),
2691 expected: expected.into(),
2692 span: tok.span,
2693 }
2694 } else {
2695 ParserError::UnexpectedEof {
2696 expected: expected.into(),
2697 span: self.prev_span(),
2698 }
2699 }
2700 }
2701
2702 fn error(&self, expected: &str) -> ParserError {
2703 self.make_error(expected)
2704 }
2705}
2706
2707#[cfg(test)]
2708mod tests {
2709 use super::*;
2710 use harn_lexer::Lexer;
2711
2712 fn parse_source(source: &str) -> Result<Vec<SNode>, ParserError> {
2713 let mut lexer = Lexer::new(source);
2714 let tokens = lexer.tokenize().unwrap();
2715 let mut parser = Parser::new(tokens);
2716 parser.parse()
2717 }
2718
2719 #[test]
2720 fn parses_match_expression_with_let_in_arm_body() {
2721 let source = r#"
2722pipeline p() {
2723 let x = match 1 {
2724 1 -> {
2725 let a = 1
2726 a
2727 }
2728 _ -> { 0 }
2729 }
2730}
2731"#;
2732
2733 assert!(parse_source(source).is_ok());
2734 }
2735
2736 #[test]
2737 fn parses_public_declarations_and_generic_interfaces() {
2738 let source = r#"
2739pub pipeline build(task) extends base {
2740 return
2741}
2742
2743pub enum Result {
2744 Ok(value: string),
2745 Err(message: string, code: int),
2746}
2747
2748pub struct Config {
2749 host: string
2750 port?: int
2751}
2752
2753interface Repository<T> {
2754 type Item
2755 fn get(id: string) -> T
2756 fn map<U>(value: T, f: fn(T) -> U) -> U
2757}
2758"#;
2759
2760 let program = parse_source(source).expect("should parse");
2761 assert!(matches!(
2762 &program[0].node,
2763 Node::Pipeline {
2764 is_pub: true,
2765 extends: Some(base),
2766 ..
2767 } if base == "base"
2768 ));
2769 assert!(matches!(
2770 &program[1].node,
2771 Node::EnumDecl {
2772 is_pub: true,
2773 type_params,
2774 ..
2775 } if type_params.is_empty()
2776 ));
2777 assert!(matches!(
2778 &program[2].node,
2779 Node::StructDecl {
2780 is_pub: true,
2781 type_params,
2782 ..
2783 } if type_params.is_empty()
2784 ));
2785 assert!(matches!(
2786 &program[3].node,
2787 Node::InterfaceDecl {
2788 type_params,
2789 associated_types,
2790 methods,
2791 ..
2792 }
2793 if type_params.len() == 1
2794 && associated_types.len() == 1
2795 && methods.len() == 2
2796 && methods[1].type_params.len() == 1
2797 ));
2798 }
2799
2800 #[test]
2801 fn parses_generic_structs_and_enums() {
2802 let source = r#"
2803struct Pair<A, B> {
2804 first: A
2805 second: B
2806}
2807
2808enum Option<T> {
2809 Some(value: T)
2810 None
2811}
2812"#;
2813
2814 let program = parse_source(source).expect("should parse");
2815 assert!(matches!(
2816 &program[0].node,
2817 Node::StructDecl { type_params, .. } if type_params.len() == 2
2818 ));
2819 assert!(matches!(
2820 &program[1].node,
2821 Node::EnumDecl { type_params, .. } if type_params.len() == 1
2822 ));
2823 }
2824
2825 #[test]
2826 fn parses_struct_literal_syntax_for_known_structs() {
2827 let source = r#"
2828struct Point {
2829 x: int
2830 y: int
2831}
2832
2833pipeline test(task) {
2834 let point = Point { x: 3, y: 4 }
2835}
2836"#;
2837
2838 let program = parse_source(source).expect("should parse");
2839 let pipeline = program
2840 .iter()
2841 .find(|node| matches!(node.node, Node::Pipeline { .. }))
2842 .expect("pipeline node");
2843 let body = match &pipeline.node {
2844 Node::Pipeline { body, .. } => body,
2845 _ => unreachable!(),
2846 };
2847 assert!(matches!(
2848 &body[0].node,
2849 Node::LetBinding { value, .. }
2850 if matches!(
2851 value.node,
2852 Node::StructConstruct { ref struct_name, ref fields }
2853 if struct_name == "Point" && fields.len() == 2
2854 )
2855 ));
2856 }
2857
2858 #[test]
2859 fn parses_exponentiation_as_right_associative() {
2860 let mut lexer = Lexer::new("a ** b ** c");
2861 let tokens = lexer.tokenize().expect("tokens");
2862 let mut parser = Parser::new(tokens);
2863 let expr = parser.parse_single_expression().expect("expression");
2864
2865 assert!(matches!(
2866 expr.node,
2867 Node::BinaryOp { ref op, ref left, ref right }
2868 if op == "**"
2869 && matches!(left.node, Node::Identifier(ref name) if name == "a")
2870 && matches!(
2871 right.node,
2872 Node::BinaryOp { ref op, ref left, ref right }
2873 if op == "**"
2874 && matches!(left.node, Node::Identifier(ref name) if name == "b")
2875 && matches!(right.node, Node::Identifier(ref name) if name == "c")
2876 )
2877 ));
2878 }
2879
2880 #[test]
2881 fn parses_exponentiation_tighter_than_multiplication() {
2882 let mut lexer = Lexer::new("a * b ** c");
2883 let tokens = lexer.tokenize().expect("tokens");
2884 let mut parser = Parser::new(tokens);
2885 let expr = parser.parse_single_expression().expect("expression");
2886
2887 assert!(matches!(
2888 expr.node,
2889 Node::BinaryOp { ref op, ref left, ref right }
2890 if op == "*"
2891 && matches!(left.node, Node::Identifier(ref name) if name == "a")
2892 && matches!(
2893 right.node,
2894 Node::BinaryOp { ref op, ref left, ref right }
2895 if op == "**"
2896 && matches!(left.node, Node::Identifier(ref name) if name == "b")
2897 && matches!(right.node, Node::Identifier(ref name) if name == "c")
2898 )
2899 ));
2900 }
2901}