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