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