Skip to main content

harn_parser/
parser.rs

1use crate::ast::*;
2use harn_lexer::{Span, Token, TokenKind};
3use std::fmt;
4
5/// Parser errors.
6#[derive(Debug, Clone, PartialEq)]
7pub enum ParserError {
8    Unexpected {
9        got: String,
10        expected: String,
11        span: Span,
12    },
13    UnexpectedEof {
14        expected: String,
15    },
16}
17
18impl fmt::Display for ParserError {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        match self {
21            ParserError::Unexpected {
22                got,
23                expected,
24                span,
25            } => write!(
26                f,
27                "Expected {expected}, got {got} at {}:{}",
28                span.line, span.column
29            ),
30            ParserError::UnexpectedEof { expected } => {
31                write!(f, "Unexpected end of file, expected {expected}")
32            }
33        }
34    }
35}
36
37impl std::error::Error for ParserError {}
38
39/// Recursive descent parser for Harn.
40pub struct Parser {
41    tokens: Vec<Token>,
42    pos: usize,
43    errors: Vec<ParserError>,
44}
45
46impl Parser {
47    pub fn new(tokens: Vec<Token>) -> Self {
48        Self {
49            tokens,
50            pos: 0,
51            errors: Vec::new(),
52        }
53    }
54
55    fn current_span(&self) -> Span {
56        self.tokens
57            .get(self.pos)
58            .map(|t| t.span)
59            .unwrap_or(Span::dummy())
60    }
61
62    fn current_kind(&self) -> Option<&TokenKind> {
63        self.tokens.get(self.pos).map(|t| &t.kind)
64    }
65
66    fn prev_span(&self) -> Span {
67        if self.pos > 0 {
68            self.tokens[self.pos - 1].span
69        } else {
70            Span::dummy()
71        }
72    }
73
74    /// Parse a complete .harn file. Reports multiple errors via recovery.
75    pub fn parse(&mut self) -> Result<Vec<SNode>, ParserError> {
76        let mut nodes = Vec::new();
77        self.skip_newlines();
78
79        while !self.is_at_end() {
80            // Skip any stray closing braces at top level (after recovery)
81            if self.check(&TokenKind::RBrace) {
82                self.advance();
83                self.skip_newlines();
84                continue;
85            }
86
87            let result = if self.check(&TokenKind::Import) {
88                self.parse_import()
89            } else if self.check(&TokenKind::Pipeline) {
90                self.parse_pipeline()
91            } else {
92                self.parse_statement()
93            };
94
95            match result {
96                Ok(node) => nodes.push(node),
97                Err(err) => {
98                    self.errors.push(err);
99                    self.synchronize();
100                }
101            }
102            self.skip_newlines();
103        }
104
105        if let Some(first) = self.errors.first() {
106            return Err(first.clone());
107        }
108        Ok(nodes)
109    }
110
111    /// Return all accumulated parser errors (after `parse()` returns).
112    pub fn all_errors(&self) -> &[ParserError] {
113        &self.errors
114    }
115
116    /// Check if the current token is one that starts a statement.
117    fn is_statement_start(&self) -> bool {
118        matches!(
119            self.current_kind(),
120            Some(
121                TokenKind::Let
122                    | TokenKind::Var
123                    | TokenKind::If
124                    | TokenKind::For
125                    | TokenKind::While
126                    | TokenKind::Match
127                    | TokenKind::Retry
128                    | TokenKind::Return
129                    | TokenKind::Throw
130                    | TokenKind::Fn
131                    | TokenKind::Pub
132                    | TokenKind::Try
133                    | TokenKind::Select
134                    | TokenKind::Pipeline
135                    | TokenKind::Import
136                    | TokenKind::Parallel
137                    | TokenKind::ParallelMap
138                    | TokenKind::Enum
139                    | TokenKind::Struct
140                    | TokenKind::Interface
141                    | TokenKind::Guard
142                    | TokenKind::Deadline
143                    | TokenKind::Yield
144                    | TokenKind::Mutex
145            )
146        )
147    }
148
149    /// Advance past tokens until we reach a likely statement boundary.
150    fn synchronize(&mut self) {
151        while !self.is_at_end() {
152            if self.check(&TokenKind::Newline) {
153                self.advance();
154                if self.is_at_end() || self.is_statement_start() {
155                    return;
156                }
157                continue;
158            }
159            if self.check(&TokenKind::RBrace) {
160                return;
161            }
162            self.advance();
163        }
164    }
165
166    /// Parse a single expression (for string interpolation).
167    pub fn parse_single_expression(&mut self) -> Result<SNode, ParserError> {
168        self.skip_newlines();
169        self.parse_expression()
170    }
171
172    // --- Declarations ---
173
174    fn parse_pipeline(&mut self) -> Result<SNode, ParserError> {
175        let start = self.current_span();
176        self.consume(&TokenKind::Pipeline, "pipeline")?;
177        let name = self.consume_identifier("pipeline name")?;
178
179        self.consume(&TokenKind::LParen, "(")?;
180        let params = self.parse_param_list()?;
181        self.consume(&TokenKind::RParen, ")")?;
182
183        let extends = if self.check(&TokenKind::Extends) {
184            self.advance();
185            Some(self.consume_identifier("parent pipeline name")?)
186        } else {
187            None
188        };
189
190        self.consume(&TokenKind::LBrace, "{")?;
191        let body = self.parse_block()?;
192        self.consume(&TokenKind::RBrace, "}")?;
193
194        Ok(spanned(
195            Node::Pipeline {
196                name,
197                params,
198                body,
199                extends,
200            },
201            Span::merge(start, self.prev_span()),
202        ))
203    }
204
205    fn parse_import(&mut self) -> Result<SNode, ParserError> {
206        let start = self.current_span();
207        self.consume(&TokenKind::Import, "import")?;
208
209        // Check for selective import: import { foo, bar } from "module"
210        if self.check(&TokenKind::LBrace) {
211            self.advance(); // skip {
212            let mut names = Vec::new();
213            while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
214                let name = self.consume_identifier("import name")?;
215                names.push(name);
216                if self.check(&TokenKind::Comma) {
217                    self.advance();
218                }
219            }
220            self.consume(&TokenKind::RBrace, "}")?;
221            self.consume(&TokenKind::From, "from")?;
222            if let Some(tok) = self.current() {
223                if let TokenKind::StringLiteral(path) = &tok.kind {
224                    let path = path.clone();
225                    self.advance();
226                    return Ok(spanned(
227                        Node::SelectiveImport { names, path },
228                        Span::merge(start, self.prev_span()),
229                    ));
230                }
231            }
232            return Err(self.error("import path string"));
233        }
234
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::ImportDecl { path },
241                    Span::merge(start, self.prev_span()),
242                ));
243            }
244        }
245        Err(self.error("import path string"))
246    }
247
248    // --- Statements ---
249
250    fn parse_block(&mut self) -> Result<Vec<SNode>, ParserError> {
251        let mut stmts = Vec::new();
252        self.skip_newlines();
253
254        while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
255            stmts.push(self.parse_statement()?);
256            self.skip_newlines();
257        }
258        Ok(stmts)
259    }
260
261    fn parse_statement(&mut self) -> Result<SNode, ParserError> {
262        self.skip_newlines();
263
264        let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
265            expected: "statement".into(),
266        })?;
267
268        match &tok.kind {
269            TokenKind::Let => self.parse_let_binding(),
270            TokenKind::Var => self.parse_var_binding(),
271            TokenKind::If => self.parse_if_else(),
272            TokenKind::For => self.parse_for_in(),
273            TokenKind::Match => self.parse_match(),
274            TokenKind::Retry => self.parse_retry(),
275            TokenKind::While => self.parse_while_loop(),
276            TokenKind::Parallel => self.parse_parallel(),
277            TokenKind::ParallelMap => self.parse_parallel_map(),
278            TokenKind::Return => self.parse_return(),
279            TokenKind::Throw => self.parse_throw(),
280            TokenKind::Override => self.parse_override(),
281            TokenKind::Try => self.parse_try_catch(),
282            TokenKind::Select => self.parse_select(),
283            TokenKind::Fn => self.parse_fn_decl_with_pub(false),
284            TokenKind::Pub => {
285                self.advance(); // consume 'pub'
286                let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
287                    expected: "fn, struct, enum, or pipeline after pub".into(),
288                })?;
289                match &tok.kind {
290                    TokenKind::Fn => self.parse_fn_decl_with_pub(true),
291                    _ => Err(self.error("fn, struct, enum, or pipeline after pub")),
292                }
293            }
294            TokenKind::TypeKw => self.parse_type_decl(),
295            TokenKind::Enum => self.parse_enum_decl(),
296            TokenKind::Struct => self.parse_struct_decl(),
297            TokenKind::Interface => self.parse_interface_decl(),
298            TokenKind::Impl => self.parse_impl_block(),
299            TokenKind::Guard => self.parse_guard(),
300            TokenKind::Deadline => self.parse_deadline(),
301            TokenKind::Yield => self.parse_yield(),
302            TokenKind::Mutex => self.parse_mutex(),
303            TokenKind::Break => {
304                let span = self.current_span();
305                self.advance();
306                Ok(spanned(Node::BreakStmt, span))
307            }
308            TokenKind::Continue => {
309                let span = self.current_span();
310                self.advance();
311                Ok(spanned(Node::ContinueStmt, span))
312            }
313            _ => self.parse_expression_statement(),
314        }
315    }
316
317    fn parse_let_binding(&mut self) -> Result<SNode, ParserError> {
318        let start = self.current_span();
319        self.consume(&TokenKind::Let, "let")?;
320        let pattern = self.parse_binding_pattern()?;
321        let type_ann = if matches!(pattern, BindingPattern::Identifier(_)) {
322            self.try_parse_type_annotation()?
323        } else {
324            None
325        };
326        self.consume(&TokenKind::Assign, "=")?;
327        let value = self.parse_expression()?;
328        Ok(spanned(
329            Node::LetBinding {
330                pattern,
331                type_ann,
332                value: Box::new(value),
333            },
334            Span::merge(start, self.prev_span()),
335        ))
336    }
337
338    fn parse_var_binding(&mut self) -> Result<SNode, ParserError> {
339        let start = self.current_span();
340        self.consume(&TokenKind::Var, "var")?;
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::VarBinding {
351                pattern,
352                type_ann,
353                value: Box::new(value),
354            },
355            Span::merge(start, self.prev_span()),
356        ))
357    }
358
359    fn parse_if_else(&mut self) -> Result<SNode, ParserError> {
360        let start = self.current_span();
361        self.consume(&TokenKind::If, "if")?;
362        let condition = self.parse_expression()?;
363        self.consume(&TokenKind::LBrace, "{")?;
364        let then_body = self.parse_block()?;
365        self.consume(&TokenKind::RBrace, "}")?;
366        self.skip_newlines();
367
368        let else_body = if self.check(&TokenKind::Else) {
369            self.advance();
370            if self.check(&TokenKind::If) {
371                Some(vec![self.parse_if_else()?])
372            } else {
373                self.consume(&TokenKind::LBrace, "{")?;
374                let body = self.parse_block()?;
375                self.consume(&TokenKind::RBrace, "}")?;
376                Some(body)
377            }
378        } else {
379            None
380        };
381
382        Ok(spanned(
383            Node::IfElse {
384                condition: Box::new(condition),
385                then_body,
386                else_body,
387            },
388            Span::merge(start, self.prev_span()),
389        ))
390    }
391
392    fn parse_for_in(&mut self) -> Result<SNode, ParserError> {
393        let start = self.current_span();
394        self.consume(&TokenKind::For, "for")?;
395        let pattern = self.parse_binding_pattern()?;
396        self.consume(&TokenKind::In, "in")?;
397        let iterable = self.parse_expression()?;
398        self.consume(&TokenKind::LBrace, "{")?;
399        let body = self.parse_block()?;
400        self.consume(&TokenKind::RBrace, "}")?;
401        Ok(spanned(
402            Node::ForIn {
403                pattern,
404                iterable: Box::new(iterable),
405                body,
406            },
407            Span::merge(start, self.prev_span()),
408        ))
409    }
410
411    /// Parse a binding pattern for let/var/for-in:
412    ///   identifier | { fields } | [ elements ]
413    fn parse_binding_pattern(&mut self) -> Result<BindingPattern, ParserError> {
414        self.skip_newlines();
415        if self.check(&TokenKind::LBrace) {
416            // Dict destructuring: { key, key: alias, ...rest }
417            self.advance(); // consume {
418            let mut fields = Vec::new();
419            while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
420                // Check for rest pattern: ...ident
421                if self.check(&TokenKind::Dot) {
422                    // Consume three dots
423                    self.advance(); // .
424                    self.consume(&TokenKind::Dot, ".")?;
425                    self.consume(&TokenKind::Dot, ".")?;
426                    let name = self.consume_identifier("rest variable name")?;
427                    fields.push(DictPatternField {
428                        key: name,
429                        alias: None,
430                        is_rest: true,
431                    });
432                    // Rest must be last
433                    break;
434                }
435                let key = self.consume_identifier("field name")?;
436                let alias = if self.check(&TokenKind::Colon) {
437                    self.advance(); // consume :
438                    Some(self.consume_identifier("alias name")?)
439                } else {
440                    None
441                };
442                fields.push(DictPatternField {
443                    key,
444                    alias,
445                    is_rest: false,
446                });
447                if self.check(&TokenKind::Comma) {
448                    self.advance();
449                }
450            }
451            self.consume(&TokenKind::RBrace, "}")?;
452            Ok(BindingPattern::Dict(fields))
453        } else if self.check(&TokenKind::LBracket) {
454            // List destructuring: [ name, name, ...rest ]
455            self.advance(); // consume [
456            let mut elements = Vec::new();
457            while !self.is_at_end() && !self.check(&TokenKind::RBracket) {
458                // Check for rest pattern: ...ident
459                if self.check(&TokenKind::Dot) {
460                    self.advance(); // .
461                    self.consume(&TokenKind::Dot, ".")?;
462                    self.consume(&TokenKind::Dot, ".")?;
463                    let name = self.consume_identifier("rest variable name")?;
464                    elements.push(ListPatternElement {
465                        name,
466                        is_rest: true,
467                    });
468                    // Rest must be last
469                    break;
470                }
471                let name = self.consume_identifier("element name")?;
472                elements.push(ListPatternElement {
473                    name,
474                    is_rest: false,
475                });
476                if self.check(&TokenKind::Comma) {
477                    self.advance();
478                }
479            }
480            self.consume(&TokenKind::RBracket, "]")?;
481            Ok(BindingPattern::List(elements))
482        } else {
483            // Simple identifier
484            let name = self.consume_identifier("variable name or destructuring pattern")?;
485            Ok(BindingPattern::Identifier(name))
486        }
487    }
488
489    fn parse_match(&mut self) -> Result<SNode, ParserError> {
490        let start = self.current_span();
491        self.consume(&TokenKind::Match, "match")?;
492        let value = self.parse_expression()?;
493        self.consume(&TokenKind::LBrace, "{")?;
494        self.skip_newlines();
495
496        let mut arms = Vec::new();
497        while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
498            let pattern = self.parse_expression()?;
499            self.consume(&TokenKind::Arrow, "->")?;
500            self.consume(&TokenKind::LBrace, "{")?;
501            let body = self.parse_block()?;
502            self.consume(&TokenKind::RBrace, "}")?;
503            arms.push(MatchArm { pattern, body });
504            self.skip_newlines();
505        }
506
507        self.consume(&TokenKind::RBrace, "}")?;
508        Ok(spanned(
509            Node::MatchExpr {
510                value: Box::new(value),
511                arms,
512            },
513            Span::merge(start, self.prev_span()),
514        ))
515    }
516
517    fn parse_while_loop(&mut self) -> Result<SNode, ParserError> {
518        let start = self.current_span();
519        self.consume(&TokenKind::While, "while")?;
520        let condition = if self.check(&TokenKind::LParen) {
521            self.advance();
522            let c = self.parse_expression()?;
523            self.consume(&TokenKind::RParen, ")")?;
524            c
525        } else {
526            self.parse_expression()?
527        };
528        self.consume(&TokenKind::LBrace, "{")?;
529        let body = self.parse_block()?;
530        self.consume(&TokenKind::RBrace, "}")?;
531        Ok(spanned(
532            Node::WhileLoop {
533                condition: Box::new(condition),
534                body,
535            },
536            Span::merge(start, self.prev_span()),
537        ))
538    }
539
540    fn parse_retry(&mut self) -> Result<SNode, ParserError> {
541        let start = self.current_span();
542        self.consume(&TokenKind::Retry, "retry")?;
543        let count = if self.check(&TokenKind::LParen) {
544            self.advance();
545            let c = self.parse_expression()?;
546            self.consume(&TokenKind::RParen, ")")?;
547            c
548        } else {
549            self.parse_primary()?
550        };
551        self.consume(&TokenKind::LBrace, "{")?;
552        let body = self.parse_block()?;
553        self.consume(&TokenKind::RBrace, "}")?;
554        Ok(spanned(
555            Node::Retry {
556                count: Box::new(count),
557                body,
558            },
559            Span::merge(start, self.prev_span()),
560        ))
561    }
562
563    fn parse_parallel(&mut self) -> Result<SNode, ParserError> {
564        let start = self.current_span();
565        self.consume(&TokenKind::Parallel, "parallel")?;
566        self.consume(&TokenKind::LParen, "(")?;
567        let count = self.parse_expression()?;
568        self.consume(&TokenKind::RParen, ")")?;
569        self.consume(&TokenKind::LBrace, "{")?;
570
571        // Optional closure parameter: { i ->
572        let mut variable = None;
573        self.skip_newlines();
574        if let Some(tok) = self.current() {
575            if let TokenKind::Identifier(name) = &tok.kind {
576                if self.peek_kind() == Some(&TokenKind::Arrow) {
577                    let name = name.clone();
578                    self.advance(); // skip identifier
579                    self.advance(); // skip ->
580                    variable = Some(name);
581                }
582            }
583        }
584
585        let body = self.parse_block()?;
586        self.consume(&TokenKind::RBrace, "}")?;
587        Ok(spanned(
588            Node::Parallel {
589                count: Box::new(count),
590                variable,
591                body,
592            },
593            Span::merge(start, self.prev_span()),
594        ))
595    }
596
597    fn parse_parallel_map(&mut self) -> Result<SNode, ParserError> {
598        let start = self.current_span();
599        self.consume(&TokenKind::ParallelMap, "parallel_map")?;
600        self.consume(&TokenKind::LParen, "(")?;
601        let list = self.parse_expression()?;
602        self.consume(&TokenKind::RParen, ")")?;
603        self.consume(&TokenKind::LBrace, "{")?;
604
605        self.skip_newlines();
606        let variable = self.consume_identifier("map variable")?;
607        self.consume(&TokenKind::Arrow, "->")?;
608
609        let body = self.parse_block()?;
610        self.consume(&TokenKind::RBrace, "}")?;
611        Ok(spanned(
612            Node::ParallelMap {
613                list: Box::new(list),
614                variable,
615                body,
616            },
617            Span::merge(start, self.prev_span()),
618        ))
619    }
620
621    fn parse_return(&mut self) -> Result<SNode, ParserError> {
622        let start = self.current_span();
623        self.consume(&TokenKind::Return, "return")?;
624        if self.is_at_end() || self.check(&TokenKind::Newline) || self.check(&TokenKind::RBrace) {
625            return Ok(spanned(
626                Node::ReturnStmt { value: None },
627                Span::merge(start, self.prev_span()),
628            ));
629        }
630        let value = self.parse_expression()?;
631        Ok(spanned(
632            Node::ReturnStmt {
633                value: Some(Box::new(value)),
634            },
635            Span::merge(start, self.prev_span()),
636        ))
637    }
638
639    fn parse_throw(&mut self) -> Result<SNode, ParserError> {
640        let start = self.current_span();
641        self.consume(&TokenKind::Throw, "throw")?;
642        let value = self.parse_expression()?;
643        Ok(spanned(
644            Node::ThrowStmt {
645                value: Box::new(value),
646            },
647            Span::merge(start, self.prev_span()),
648        ))
649    }
650
651    fn parse_override(&mut self) -> Result<SNode, ParserError> {
652        let start = self.current_span();
653        self.consume(&TokenKind::Override, "override")?;
654        let name = self.consume_identifier("override name")?;
655        self.consume(&TokenKind::LParen, "(")?;
656        let params = self.parse_param_list()?;
657        self.consume(&TokenKind::RParen, ")")?;
658        self.consume(&TokenKind::LBrace, "{")?;
659        let body = self.parse_block()?;
660        self.consume(&TokenKind::RBrace, "}")?;
661        Ok(spanned(
662            Node::OverrideDecl { name, params, body },
663            Span::merge(start, self.prev_span()),
664        ))
665    }
666
667    fn parse_try_catch(&mut self) -> Result<SNode, ParserError> {
668        let start = self.current_span();
669        self.consume(&TokenKind::Try, "try")?;
670        self.consume(&TokenKind::LBrace, "{")?;
671        let body = self.parse_block()?;
672        self.consume(&TokenKind::RBrace, "}")?;
673        self.skip_newlines();
674
675        // Parse optional catch block
676        let has_catch = self.check(&TokenKind::Catch);
677        let (error_var, error_type, catch_body) = if has_catch {
678            self.advance();
679            let (ev, et) = if self.check(&TokenKind::LParen) {
680                self.advance();
681                let name = self.consume_identifier("error variable")?;
682                let ty = self.try_parse_type_annotation()?;
683                self.consume(&TokenKind::RParen, ")")?;
684                (Some(name), ty)
685            } else {
686                (None, None)
687            };
688            self.consume(&TokenKind::LBrace, "{")?;
689            let cb = self.parse_block()?;
690            self.consume(&TokenKind::RBrace, "}")?;
691            (ev, et, cb)
692        } else {
693            (None, None, Vec::new())
694        };
695
696        self.skip_newlines();
697
698        // Parse optional finally block
699        let finally_body = if self.check(&TokenKind::Finally) {
700            self.advance();
701            self.consume(&TokenKind::LBrace, "{")?;
702            let fb = self.parse_block()?;
703            self.consume(&TokenKind::RBrace, "}")?;
704            Some(fb)
705        } else {
706            None
707        };
708
709        // Must have at least catch or finally
710        if !has_catch && finally_body.is_none() {
711            return Err(self.error("catch or finally block after try"));
712        }
713
714        Ok(spanned(
715            Node::TryCatch {
716                body,
717                error_var,
718                error_type,
719                catch_body,
720                finally_body,
721            },
722            Span::merge(start, self.prev_span()),
723        ))
724    }
725
726    fn parse_select(&mut self) -> Result<SNode, ParserError> {
727        let start = self.current_span();
728        self.consume(&TokenKind::Select, "select")?;
729        self.consume(&TokenKind::LBrace, "{")?;
730        self.skip_newlines();
731
732        let mut cases = Vec::new();
733        let mut timeout = None;
734        let mut default_body = None;
735
736        while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
737            self.skip_newlines();
738            // Check for "timeout" (contextual keyword)
739            if let Some(tok) = self.current() {
740                if let TokenKind::Identifier(ref id) = tok.kind {
741                    if id == "timeout" {
742                        self.advance();
743                        let duration = self.parse_expression()?;
744                        self.consume(&TokenKind::LBrace, "{")?;
745                        let body = self.parse_block()?;
746                        self.consume(&TokenKind::RBrace, "}")?;
747                        timeout = Some((Box::new(duration), body));
748                        self.skip_newlines();
749                        continue;
750                    }
751                    if id == "default" {
752                        self.advance();
753                        self.consume(&TokenKind::LBrace, "{")?;
754                        let body = self.parse_block()?;
755                        self.consume(&TokenKind::RBrace, "}")?;
756                        default_body = Some(body);
757                        self.skip_newlines();
758                        continue;
759                    }
760                }
761            }
762            // Regular case: variable from channel { body }
763            let variable = self.consume_identifier("select case variable")?;
764            self.consume(&TokenKind::From, "from")?;
765            let channel = self.parse_expression()?;
766            self.consume(&TokenKind::LBrace, "{")?;
767            let body = self.parse_block()?;
768            self.consume(&TokenKind::RBrace, "}")?;
769            cases.push(SelectCase {
770                variable,
771                channel: Box::new(channel),
772                body,
773            });
774            self.skip_newlines();
775        }
776
777        self.consume(&TokenKind::RBrace, "}")?;
778
779        if cases.is_empty() && timeout.is_none() && default_body.is_none() {
780            return Err(self.error("at least one select case"));
781        }
782        if timeout.is_some() && default_body.is_some() {
783            return Err(self.error("select cannot have both timeout and default"));
784        }
785
786        Ok(spanned(
787            Node::SelectExpr {
788                cases,
789                timeout,
790                default_body,
791            },
792            Span::merge(start, self.prev_span()),
793        ))
794    }
795
796    fn parse_fn_decl_with_pub(&mut self, is_pub: bool) -> Result<SNode, ParserError> {
797        let start = self.current_span();
798        self.consume(&TokenKind::Fn, "fn")?;
799        let name = self.consume_identifier("function name")?;
800
801        // Optional generic type parameters: fn name<T, U>(...)
802        let type_params = if self.check(&TokenKind::Lt) {
803            self.advance(); // skip <
804            self.parse_type_param_list()?
805        } else {
806            Vec::new()
807        };
808
809        self.consume(&TokenKind::LParen, "(")?;
810        let params = self.parse_typed_param_list()?;
811        self.consume(&TokenKind::RParen, ")")?;
812        // Optional return type: -> type
813        let return_type = if self.check(&TokenKind::Arrow) {
814            self.advance();
815            Some(self.parse_type_expr()?)
816        } else {
817            None
818        };
819
820        // Optional where clause: where T: bound, U: bound
821        let where_clauses = self.parse_where_clauses()?;
822
823        self.consume(&TokenKind::LBrace, "{")?;
824        let body = self.parse_block()?;
825        self.consume(&TokenKind::RBrace, "}")?;
826        Ok(spanned(
827            Node::FnDecl {
828                name,
829                type_params,
830                params,
831                return_type,
832                where_clauses,
833                body,
834                is_pub,
835            },
836            Span::merge(start, self.prev_span()),
837        ))
838    }
839
840    fn parse_type_decl(&mut self) -> Result<SNode, ParserError> {
841        let start = self.current_span();
842        self.consume(&TokenKind::TypeKw, "type")?;
843        let name = self.consume_identifier("type name")?;
844        self.consume(&TokenKind::Assign, "=")?;
845        let type_expr = self.parse_type_expr()?;
846        Ok(spanned(
847            Node::TypeDecl { name, type_expr },
848            Span::merge(start, self.prev_span()),
849        ))
850    }
851
852    fn parse_enum_decl(&mut self) -> Result<SNode, ParserError> {
853        let start = self.current_span();
854        self.consume(&TokenKind::Enum, "enum")?;
855        let name = self.consume_identifier("enum name")?;
856        self.consume(&TokenKind::LBrace, "{")?;
857        self.skip_newlines();
858
859        let mut variants = Vec::new();
860        while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
861            let variant_name = self.consume_identifier("variant name")?;
862            let fields = if self.check(&TokenKind::LParen) {
863                self.advance();
864                let params = self.parse_typed_param_list()?;
865                self.consume(&TokenKind::RParen, ")")?;
866                params
867            } else {
868                Vec::new()
869            };
870            variants.push(EnumVariant {
871                name: variant_name,
872                fields,
873            });
874            self.skip_newlines();
875            if self.check(&TokenKind::Comma) {
876                self.advance();
877                self.skip_newlines();
878            }
879        }
880
881        self.consume(&TokenKind::RBrace, "}")?;
882        Ok(spanned(
883            Node::EnumDecl { name, variants },
884            Span::merge(start, self.prev_span()),
885        ))
886    }
887
888    fn parse_struct_decl(&mut self) -> Result<SNode, ParserError> {
889        let start = self.current_span();
890        self.consume(&TokenKind::Struct, "struct")?;
891        let name = self.consume_identifier("struct name")?;
892        self.consume(&TokenKind::LBrace, "{")?;
893        self.skip_newlines();
894
895        let mut fields = Vec::new();
896        while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
897            let field_name = self.consume_identifier("field name")?;
898            let optional = if self.check(&TokenKind::Question) {
899                self.advance();
900                true
901            } else {
902                false
903            };
904            let type_expr = self.try_parse_type_annotation()?;
905            fields.push(StructField {
906                name: field_name,
907                type_expr,
908                optional,
909            });
910            self.skip_newlines();
911            if self.check(&TokenKind::Comma) {
912                self.advance();
913                self.skip_newlines();
914            }
915        }
916
917        self.consume(&TokenKind::RBrace, "}")?;
918        Ok(spanned(
919            Node::StructDecl { name, fields },
920            Span::merge(start, self.prev_span()),
921        ))
922    }
923
924    fn parse_interface_decl(&mut self) -> Result<SNode, ParserError> {
925        let start = self.current_span();
926        self.consume(&TokenKind::Interface, "interface")?;
927        let name = self.consume_identifier("interface name")?;
928        self.consume(&TokenKind::LBrace, "{")?;
929        self.skip_newlines();
930
931        let mut methods = Vec::new();
932        while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
933            self.consume(&TokenKind::Fn, "fn")?;
934            let method_name = self.consume_identifier("method name")?;
935            self.consume(&TokenKind::LParen, "(")?;
936            let params = self.parse_typed_param_list()?;
937            self.consume(&TokenKind::RParen, ")")?;
938            // Optional return type: -> type
939            let return_type = if self.check(&TokenKind::Arrow) {
940                self.advance();
941                Some(self.parse_type_expr()?)
942            } else {
943                None
944            };
945            methods.push(InterfaceMethod {
946                name: method_name,
947                params,
948                return_type,
949            });
950            self.skip_newlines();
951        }
952
953        self.consume(&TokenKind::RBrace, "}")?;
954        Ok(spanned(
955            Node::InterfaceDecl { name, methods },
956            Span::merge(start, self.prev_span()),
957        ))
958    }
959
960    fn parse_impl_block(&mut self) -> Result<SNode, ParserError> {
961        let start = self.current_span();
962        self.consume(&TokenKind::Impl, "impl")?;
963        let type_name = self.consume_identifier("type name")?;
964        self.consume(&TokenKind::LBrace, "{")?;
965        self.skip_newlines();
966
967        let mut methods = Vec::new();
968        while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
969            let is_pub = self.check(&TokenKind::Pub);
970            if is_pub {
971                self.advance();
972            }
973            let method = self.parse_fn_decl_with_pub(is_pub)?;
974            methods.push(method);
975            self.skip_newlines();
976        }
977
978        self.consume(&TokenKind::RBrace, "}")?;
979        Ok(spanned(
980            Node::ImplBlock { type_name, methods },
981            Span::merge(start, self.prev_span()),
982        ))
983    }
984
985    fn parse_guard(&mut self) -> Result<SNode, ParserError> {
986        let start = self.current_span();
987        self.consume(&TokenKind::Guard, "guard")?;
988        let condition = self.parse_expression()?;
989        // Consume "else" — we reuse the Else keyword
990        self.consume(&TokenKind::Else, "else")?;
991        self.consume(&TokenKind::LBrace, "{")?;
992        let else_body = self.parse_block()?;
993        self.consume(&TokenKind::RBrace, "}")?;
994        Ok(spanned(
995            Node::GuardStmt {
996                condition: Box::new(condition),
997                else_body,
998            },
999            Span::merge(start, self.prev_span()),
1000        ))
1001    }
1002
1003    fn parse_deadline(&mut self) -> Result<SNode, ParserError> {
1004        let start = self.current_span();
1005        self.consume(&TokenKind::Deadline, "deadline")?;
1006        let duration = self.parse_primary()?;
1007        self.consume(&TokenKind::LBrace, "{")?;
1008        let body = self.parse_block()?;
1009        self.consume(&TokenKind::RBrace, "}")?;
1010        Ok(spanned(
1011            Node::DeadlineBlock {
1012                duration: Box::new(duration),
1013                body,
1014            },
1015            Span::merge(start, self.prev_span()),
1016        ))
1017    }
1018
1019    fn parse_yield(&mut self) -> Result<SNode, ParserError> {
1020        let start = self.current_span();
1021        self.consume(&TokenKind::Yield, "yield")?;
1022        if self.is_at_end() || self.check(&TokenKind::Newline) || self.check(&TokenKind::RBrace) {
1023            return Ok(spanned(
1024                Node::YieldExpr { value: None },
1025                Span::merge(start, self.prev_span()),
1026            ));
1027        }
1028        let value = self.parse_expression()?;
1029        Ok(spanned(
1030            Node::YieldExpr {
1031                value: Some(Box::new(value)),
1032            },
1033            Span::merge(start, self.prev_span()),
1034        ))
1035    }
1036
1037    fn parse_mutex(&mut self) -> Result<SNode, ParserError> {
1038        let start = self.current_span();
1039        self.consume(&TokenKind::Mutex, "mutex")?;
1040        self.consume(&TokenKind::LBrace, "{")?;
1041        let body = self.parse_block()?;
1042        self.consume(&TokenKind::RBrace, "}")?;
1043        Ok(spanned(
1044            Node::MutexBlock { body },
1045            Span::merge(start, self.prev_span()),
1046        ))
1047    }
1048
1049    fn parse_ask_expr(&mut self) -> Result<SNode, ParserError> {
1050        let start = self.current_span();
1051        self.consume(&TokenKind::Ask, "ask")?;
1052        self.consume(&TokenKind::LBrace, "{")?;
1053        // Parse as dict entries
1054        let mut entries = Vec::new();
1055        self.skip_newlines();
1056        while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1057            let key_span = self.current_span();
1058            let name = self.consume_identifier("ask field")?;
1059            let key = spanned(Node::StringLiteral(name), key_span);
1060            self.consume(&TokenKind::Colon, ":")?;
1061            let value = self.parse_expression()?;
1062            entries.push(DictEntry { key, value });
1063            self.skip_newlines();
1064            if self.check(&TokenKind::Comma) {
1065                self.advance();
1066                self.skip_newlines();
1067            }
1068        }
1069        self.consume(&TokenKind::RBrace, "}")?;
1070        Ok(spanned(
1071            Node::AskExpr { fields: entries },
1072            Span::merge(start, self.prev_span()),
1073        ))
1074    }
1075
1076    // --- Expressions (precedence climbing) ---
1077
1078    fn parse_expression_statement(&mut self) -> Result<SNode, ParserError> {
1079        let start = self.current_span();
1080        let expr = self.parse_expression()?;
1081
1082        // Check for assignment or compound assignment on valid targets:
1083        // identifier, property access (obj.field), subscript access (obj[key])
1084        let is_assignable = matches!(
1085            expr.node,
1086            Node::Identifier(_) | Node::PropertyAccess { .. } | Node::SubscriptAccess { .. }
1087        );
1088        if is_assignable {
1089            if self.check(&TokenKind::Assign) {
1090                self.advance();
1091                let value = self.parse_expression()?;
1092                return Ok(spanned(
1093                    Node::Assignment {
1094                        target: Box::new(expr),
1095                        value: Box::new(value),
1096                        op: None,
1097                    },
1098                    Span::merge(start, self.prev_span()),
1099                ));
1100            }
1101            let compound_op = if self.check(&TokenKind::PlusAssign) {
1102                Some("+")
1103            } else if self.check(&TokenKind::MinusAssign) {
1104                Some("-")
1105            } else if self.check(&TokenKind::StarAssign) {
1106                Some("*")
1107            } else if self.check(&TokenKind::SlashAssign) {
1108                Some("/")
1109            } else if self.check(&TokenKind::PercentAssign) {
1110                Some("%")
1111            } else {
1112                None
1113            };
1114            if let Some(op) = compound_op {
1115                self.advance();
1116                let value = self.parse_expression()?;
1117                return Ok(spanned(
1118                    Node::Assignment {
1119                        target: Box::new(expr),
1120                        value: Box::new(value),
1121                        op: Some(op.into()),
1122                    },
1123                    Span::merge(start, self.prev_span()),
1124                ));
1125            }
1126        }
1127
1128        Ok(expr)
1129    }
1130
1131    fn parse_expression(&mut self) -> Result<SNode, ParserError> {
1132        self.skip_newlines();
1133        self.parse_pipe()
1134    }
1135
1136    fn parse_pipe(&mut self) -> Result<SNode, ParserError> {
1137        let mut left = self.parse_range()?;
1138        while self.check_skip_newlines(&TokenKind::Pipe) {
1139            let start = left.span;
1140            self.advance();
1141            let right = self.parse_range()?;
1142            left = spanned(
1143                Node::BinaryOp {
1144                    op: "|>".into(),
1145                    left: Box::new(left),
1146                    right: Box::new(right),
1147                },
1148                Span::merge(start, self.prev_span()),
1149            );
1150        }
1151        Ok(left)
1152    }
1153
1154    fn parse_range(&mut self) -> Result<SNode, ParserError> {
1155        let left = self.parse_ternary()?;
1156        if self.check(&TokenKind::Thru) {
1157            let start = left.span;
1158            self.advance();
1159            let right = self.parse_ternary()?;
1160            return Ok(spanned(
1161                Node::RangeExpr {
1162                    start: Box::new(left),
1163                    end: Box::new(right),
1164                    inclusive: true,
1165                },
1166                Span::merge(start, self.prev_span()),
1167            ));
1168        }
1169        if self.check(&TokenKind::Upto) {
1170            let start = left.span;
1171            self.advance();
1172            let right = self.parse_ternary()?;
1173            return Ok(spanned(
1174                Node::RangeExpr {
1175                    start: Box::new(left),
1176                    end: Box::new(right),
1177                    inclusive: false,
1178                },
1179                Span::merge(start, self.prev_span()),
1180            ));
1181        }
1182        Ok(left)
1183    }
1184
1185    fn parse_ternary(&mut self) -> Result<SNode, ParserError> {
1186        let condition = self.parse_nil_coalescing()?;
1187        if !self.check(&TokenKind::Question) {
1188            return Ok(condition);
1189        }
1190        let start = condition.span;
1191        self.advance(); // skip ?
1192        let true_val = self.parse_nil_coalescing()?;
1193        self.consume(&TokenKind::Colon, ":")?;
1194        let false_val = self.parse_nil_coalescing()?;
1195        Ok(spanned(
1196            Node::Ternary {
1197                condition: Box::new(condition),
1198                true_expr: Box::new(true_val),
1199                false_expr: Box::new(false_val),
1200            },
1201            Span::merge(start, self.prev_span()),
1202        ))
1203    }
1204
1205    fn parse_nil_coalescing(&mut self) -> Result<SNode, ParserError> {
1206        let mut left = self.parse_logical_or()?;
1207        while self.check(&TokenKind::NilCoal) {
1208            let start = left.span;
1209            self.advance();
1210            let right = self.parse_logical_or()?;
1211            left = spanned(
1212                Node::BinaryOp {
1213                    op: "??".into(),
1214                    left: Box::new(left),
1215                    right: Box::new(right),
1216                },
1217                Span::merge(start, self.prev_span()),
1218            );
1219        }
1220        Ok(left)
1221    }
1222
1223    fn parse_logical_or(&mut self) -> Result<SNode, ParserError> {
1224        let mut left = self.parse_logical_and()?;
1225        while self.check_skip_newlines(&TokenKind::Or) {
1226            let start = left.span;
1227            self.advance();
1228            let right = self.parse_logical_and()?;
1229            left = spanned(
1230                Node::BinaryOp {
1231                    op: "||".into(),
1232                    left: Box::new(left),
1233                    right: Box::new(right),
1234                },
1235                Span::merge(start, self.prev_span()),
1236            );
1237        }
1238        Ok(left)
1239    }
1240
1241    fn parse_logical_and(&mut self) -> Result<SNode, ParserError> {
1242        let mut left = self.parse_equality()?;
1243        while self.check_skip_newlines(&TokenKind::And) {
1244            let start = left.span;
1245            self.advance();
1246            let right = self.parse_equality()?;
1247            left = spanned(
1248                Node::BinaryOp {
1249                    op: "&&".into(),
1250                    left: Box::new(left),
1251                    right: Box::new(right),
1252                },
1253                Span::merge(start, self.prev_span()),
1254            );
1255        }
1256        Ok(left)
1257    }
1258
1259    fn parse_equality(&mut self) -> Result<SNode, ParserError> {
1260        let mut left = self.parse_comparison()?;
1261        while self.check(&TokenKind::Eq) || self.check(&TokenKind::Neq) {
1262            let start = left.span;
1263            let op = if self.check(&TokenKind::Eq) {
1264                "=="
1265            } else {
1266                "!="
1267            };
1268            self.advance();
1269            let right = self.parse_comparison()?;
1270            left = spanned(
1271                Node::BinaryOp {
1272                    op: op.into(),
1273                    left: Box::new(left),
1274                    right: Box::new(right),
1275                },
1276                Span::merge(start, self.prev_span()),
1277            );
1278        }
1279        Ok(left)
1280    }
1281
1282    fn parse_comparison(&mut self) -> Result<SNode, ParserError> {
1283        let mut left = self.parse_additive()?;
1284        while self.check(&TokenKind::Lt)
1285            || self.check(&TokenKind::Gt)
1286            || self.check(&TokenKind::Lte)
1287            || self.check(&TokenKind::Gte)
1288        {
1289            let start = left.span;
1290            let op = match self.current().map(|t| &t.kind) {
1291                Some(TokenKind::Lt) => "<",
1292                Some(TokenKind::Gt) => ">",
1293                Some(TokenKind::Lte) => "<=",
1294                Some(TokenKind::Gte) => ">=",
1295                _ => "<",
1296            };
1297            self.advance();
1298            let right = self.parse_additive()?;
1299            left = spanned(
1300                Node::BinaryOp {
1301                    op: op.into(),
1302                    left: Box::new(left),
1303                    right: Box::new(right),
1304                },
1305                Span::merge(start, self.prev_span()),
1306            );
1307        }
1308        Ok(left)
1309    }
1310
1311    fn parse_additive(&mut self) -> Result<SNode, ParserError> {
1312        let mut left = self.parse_multiplicative()?;
1313        while self.check_skip_newlines(&TokenKind::Plus) || self.check(&TokenKind::Minus) {
1314            let start = left.span;
1315            let op = if self.check(&TokenKind::Plus) {
1316                "+"
1317            } else {
1318                "-"
1319            };
1320            self.advance();
1321            let right = self.parse_multiplicative()?;
1322            left = spanned(
1323                Node::BinaryOp {
1324                    op: op.into(),
1325                    left: Box::new(left),
1326                    right: Box::new(right),
1327                },
1328                Span::merge(start, self.prev_span()),
1329            );
1330        }
1331        Ok(left)
1332    }
1333
1334    fn parse_multiplicative(&mut self) -> Result<SNode, ParserError> {
1335        let mut left = self.parse_unary()?;
1336        while self.check_skip_newlines(&TokenKind::Star)
1337            || self.check_skip_newlines(&TokenKind::Slash)
1338            || self.check_skip_newlines(&TokenKind::Percent)
1339        {
1340            let start = left.span;
1341            let op = if self.check(&TokenKind::Star) {
1342                "*"
1343            } else if self.check(&TokenKind::Slash) {
1344                "/"
1345            } else {
1346                "%"
1347            };
1348            self.advance();
1349            let right = self.parse_unary()?;
1350            left = spanned(
1351                Node::BinaryOp {
1352                    op: op.into(),
1353                    left: Box::new(left),
1354                    right: Box::new(right),
1355                },
1356                Span::merge(start, self.prev_span()),
1357            );
1358        }
1359        Ok(left)
1360    }
1361
1362    fn parse_unary(&mut self) -> Result<SNode, ParserError> {
1363        if self.check(&TokenKind::Not) {
1364            let start = self.current_span();
1365            self.advance();
1366            let operand = self.parse_unary()?;
1367            return Ok(spanned(
1368                Node::UnaryOp {
1369                    op: "!".into(),
1370                    operand: Box::new(operand),
1371                },
1372                Span::merge(start, self.prev_span()),
1373            ));
1374        }
1375        if self.check(&TokenKind::Minus) {
1376            let start = self.current_span();
1377            self.advance();
1378            let operand = self.parse_unary()?;
1379            return Ok(spanned(
1380                Node::UnaryOp {
1381                    op: "-".into(),
1382                    operand: Box::new(operand),
1383                },
1384                Span::merge(start, self.prev_span()),
1385            ));
1386        }
1387        self.parse_postfix()
1388    }
1389
1390    fn parse_postfix(&mut self) -> Result<SNode, ParserError> {
1391        let mut expr = self.parse_primary()?;
1392
1393        loop {
1394            if self.check_skip_newlines(&TokenKind::Dot)
1395                || self.check_skip_newlines(&TokenKind::QuestionDot)
1396            {
1397                let optional = self.check(&TokenKind::QuestionDot);
1398                let start = expr.span;
1399                self.advance();
1400                let member = self.consume_identifier_or_keyword("member name")?;
1401                if self.check(&TokenKind::LParen) {
1402                    self.advance();
1403                    let args = self.parse_arg_list()?;
1404                    self.consume(&TokenKind::RParen, ")")?;
1405                    if optional {
1406                        expr = spanned(
1407                            Node::OptionalMethodCall {
1408                                object: Box::new(expr),
1409                                method: member,
1410                                args,
1411                            },
1412                            Span::merge(start, self.prev_span()),
1413                        );
1414                    } else {
1415                        expr = spanned(
1416                            Node::MethodCall {
1417                                object: Box::new(expr),
1418                                method: member,
1419                                args,
1420                            },
1421                            Span::merge(start, self.prev_span()),
1422                        );
1423                    }
1424                } else if optional {
1425                    expr = spanned(
1426                        Node::OptionalPropertyAccess {
1427                            object: Box::new(expr),
1428                            property: member,
1429                        },
1430                        Span::merge(start, self.prev_span()),
1431                    );
1432                } else {
1433                    expr = spanned(
1434                        Node::PropertyAccess {
1435                            object: Box::new(expr),
1436                            property: member,
1437                        },
1438                        Span::merge(start, self.prev_span()),
1439                    );
1440                }
1441            } else if self.check(&TokenKind::LBracket) {
1442                let start = expr.span;
1443                self.advance();
1444
1445                // Check for slice vs subscript:
1446                // [:end] — slice with no start
1447                // [start:end] or [start:] — slice with start
1448                // [index] — normal subscript
1449                if self.check(&TokenKind::Colon) {
1450                    // [:end] or [:]
1451                    self.advance(); // consume ':'
1452                    let end_expr = if self.check(&TokenKind::RBracket) {
1453                        None
1454                    } else {
1455                        Some(Box::new(self.parse_expression()?))
1456                    };
1457                    self.consume(&TokenKind::RBracket, "]")?;
1458                    expr = spanned(
1459                        Node::SliceAccess {
1460                            object: Box::new(expr),
1461                            start: None,
1462                            end: end_expr,
1463                        },
1464                        Span::merge(start, self.prev_span()),
1465                    );
1466                } else {
1467                    let index = self.parse_expression()?;
1468                    if self.check(&TokenKind::Colon) {
1469                        // [start:end] or [start:]
1470                        self.advance(); // consume ':'
1471                        let end_expr = if self.check(&TokenKind::RBracket) {
1472                            None
1473                        } else {
1474                            Some(Box::new(self.parse_expression()?))
1475                        };
1476                        self.consume(&TokenKind::RBracket, "]")?;
1477                        expr = spanned(
1478                            Node::SliceAccess {
1479                                object: Box::new(expr),
1480                                start: Some(Box::new(index)),
1481                                end: end_expr,
1482                            },
1483                            Span::merge(start, self.prev_span()),
1484                        );
1485                    } else {
1486                        self.consume(&TokenKind::RBracket, "]")?;
1487                        expr = spanned(
1488                            Node::SubscriptAccess {
1489                                object: Box::new(expr),
1490                                index: Box::new(index),
1491                            },
1492                            Span::merge(start, self.prev_span()),
1493                        );
1494                    }
1495                }
1496            } else if self.check(&TokenKind::LParen) && matches!(expr.node, Node::Identifier(_)) {
1497                let start = expr.span;
1498                self.advance();
1499                let args = self.parse_arg_list()?;
1500                self.consume(&TokenKind::RParen, ")")?;
1501                if let Node::Identifier(name) = expr.node {
1502                    expr = spanned(
1503                        Node::FunctionCall { name, args },
1504                        Span::merge(start, self.prev_span()),
1505                    );
1506                }
1507            } else if self.check(&TokenKind::Question) {
1508                // Distinguish postfix try operator (expr?) from ternary (expr ? a : b).
1509                // If the token after ? could start a ternary branch, leave it for parse_ternary.
1510                let next_pos = self.pos + 1;
1511                let is_ternary = self.tokens.get(next_pos).is_some_and(|t| {
1512                    matches!(
1513                        t.kind,
1514                        TokenKind::Identifier(_)
1515                            | TokenKind::IntLiteral(_)
1516                            | TokenKind::FloatLiteral(_)
1517                            | TokenKind::StringLiteral(_)
1518                            | TokenKind::InterpolatedString(_)
1519                            | TokenKind::True
1520                            | TokenKind::False
1521                            | TokenKind::Nil
1522                            | TokenKind::LParen
1523                            | TokenKind::LBracket
1524                            | TokenKind::LBrace
1525                            | TokenKind::Not
1526                            | TokenKind::Minus
1527                            | TokenKind::Fn
1528                    )
1529                });
1530                if is_ternary {
1531                    break;
1532                }
1533                let start = expr.span;
1534                self.advance(); // consume ?
1535                expr = spanned(
1536                    Node::TryOperator {
1537                        operand: Box::new(expr),
1538                    },
1539                    Span::merge(start, self.prev_span()),
1540                );
1541            } else {
1542                break;
1543            }
1544        }
1545
1546        Ok(expr)
1547    }
1548
1549    fn parse_primary(&mut self) -> Result<SNode, ParserError> {
1550        let tok = self.current().ok_or_else(|| ParserError::UnexpectedEof {
1551            expected: "expression".into(),
1552        })?;
1553        let start = self.current_span();
1554
1555        match &tok.kind {
1556            TokenKind::StringLiteral(s) => {
1557                let s = s.clone();
1558                self.advance();
1559                Ok(spanned(
1560                    Node::StringLiteral(s),
1561                    Span::merge(start, self.prev_span()),
1562                ))
1563            }
1564            TokenKind::InterpolatedString(segments) => {
1565                let segments = segments.clone();
1566                self.advance();
1567                Ok(spanned(
1568                    Node::InterpolatedString(segments),
1569                    Span::merge(start, self.prev_span()),
1570                ))
1571            }
1572            TokenKind::IntLiteral(n) => {
1573                let n = *n;
1574                self.advance();
1575                Ok(spanned(
1576                    Node::IntLiteral(n),
1577                    Span::merge(start, self.prev_span()),
1578                ))
1579            }
1580            TokenKind::FloatLiteral(n) => {
1581                let n = *n;
1582                self.advance();
1583                Ok(spanned(
1584                    Node::FloatLiteral(n),
1585                    Span::merge(start, self.prev_span()),
1586                ))
1587            }
1588            TokenKind::True => {
1589                self.advance();
1590                Ok(spanned(
1591                    Node::BoolLiteral(true),
1592                    Span::merge(start, self.prev_span()),
1593                ))
1594            }
1595            TokenKind::False => {
1596                self.advance();
1597                Ok(spanned(
1598                    Node::BoolLiteral(false),
1599                    Span::merge(start, self.prev_span()),
1600                ))
1601            }
1602            TokenKind::Nil => {
1603                self.advance();
1604                Ok(spanned(
1605                    Node::NilLiteral,
1606                    Span::merge(start, self.prev_span()),
1607                ))
1608            }
1609            TokenKind::Identifier(name) => {
1610                let name = name.clone();
1611                self.advance();
1612                Ok(spanned(
1613                    Node::Identifier(name),
1614                    Span::merge(start, self.prev_span()),
1615                ))
1616            }
1617            TokenKind::LParen => {
1618                self.advance();
1619                let expr = self.parse_expression()?;
1620                self.consume(&TokenKind::RParen, ")")?;
1621                Ok(expr)
1622            }
1623            TokenKind::LBracket => self.parse_list_literal(),
1624            TokenKind::LBrace => self.parse_dict_or_closure(),
1625            TokenKind::Parallel => self.parse_parallel(),
1626            TokenKind::ParallelMap => self.parse_parallel_map(),
1627            TokenKind::Retry => self.parse_retry(),
1628            TokenKind::If => self.parse_if_else(),
1629            TokenKind::Spawn => self.parse_spawn_expr(),
1630            TokenKind::DurationLiteral(ms) => {
1631                let ms = *ms;
1632                self.advance();
1633                Ok(spanned(
1634                    Node::DurationLiteral(ms),
1635                    Span::merge(start, self.prev_span()),
1636                ))
1637            }
1638            TokenKind::Ask => self.parse_ask_expr(),
1639            TokenKind::Deadline => self.parse_deadline(),
1640            _ => Err(self.error("expression")),
1641        }
1642    }
1643
1644    fn parse_spawn_expr(&mut self) -> Result<SNode, ParserError> {
1645        let start = self.current_span();
1646        self.consume(&TokenKind::Spawn, "spawn")?;
1647        self.consume(&TokenKind::LBrace, "{")?;
1648        let body = self.parse_block()?;
1649        self.consume(&TokenKind::RBrace, "}")?;
1650        Ok(spanned(
1651            Node::SpawnExpr { body },
1652            Span::merge(start, self.prev_span()),
1653        ))
1654    }
1655
1656    fn parse_list_literal(&mut self) -> Result<SNode, ParserError> {
1657        let start = self.current_span();
1658        self.consume(&TokenKind::LBracket, "[")?;
1659        let mut elements = Vec::new();
1660        self.skip_newlines();
1661
1662        while !self.is_at_end() && !self.check(&TokenKind::RBracket) {
1663            // Check for spread: ...expr
1664            if self.check(&TokenKind::Dot) {
1665                let saved_pos = self.pos;
1666                self.advance(); // first .
1667                if self.check(&TokenKind::Dot) {
1668                    self.advance(); // second .
1669                    self.consume(&TokenKind::Dot, ".")?; // third .
1670                    let spread_start = self.tokens[saved_pos].span;
1671                    let expr = self.parse_expression()?;
1672                    elements.push(spanned(
1673                        Node::Spread(Box::new(expr)),
1674                        Span::merge(spread_start, self.prev_span()),
1675                    ));
1676                } else {
1677                    // Not a spread, restore and parse as expression
1678                    self.pos = saved_pos;
1679                    elements.push(self.parse_expression()?);
1680                }
1681            } else {
1682                elements.push(self.parse_expression()?);
1683            }
1684            self.skip_newlines();
1685            if self.check(&TokenKind::Comma) {
1686                self.advance();
1687                self.skip_newlines();
1688            }
1689        }
1690
1691        self.consume(&TokenKind::RBracket, "]")?;
1692        Ok(spanned(
1693            Node::ListLiteral(elements),
1694            Span::merge(start, self.prev_span()),
1695        ))
1696    }
1697
1698    fn parse_dict_or_closure(&mut self) -> Result<SNode, ParserError> {
1699        let start = self.current_span();
1700        self.consume(&TokenKind::LBrace, "{")?;
1701        self.skip_newlines();
1702
1703        // Empty dict
1704        if self.check(&TokenKind::RBrace) {
1705            self.advance();
1706            return Ok(spanned(
1707                Node::DictLiteral(Vec::new()),
1708                Span::merge(start, self.prev_span()),
1709            ));
1710        }
1711
1712        // Lookahead: scan for -> before } to disambiguate closure from dict.
1713        let saved = self.pos;
1714        if self.is_closure_lookahead() {
1715            self.pos = saved;
1716            return self.parse_closure_body(start);
1717        }
1718        self.pos = saved;
1719        self.parse_dict_literal(start)
1720    }
1721
1722    /// Scan forward to determine if this is a closure (has -> before matching }).
1723    /// Does not consume tokens (caller saves/restores pos).
1724    fn is_closure_lookahead(&mut self) -> bool {
1725        let mut depth = 0;
1726        while !self.is_at_end() {
1727            if let Some(tok) = self.current() {
1728                match &tok.kind {
1729                    TokenKind::Arrow if depth == 0 => return true,
1730                    TokenKind::LBrace | TokenKind::LParen | TokenKind::LBracket => depth += 1,
1731                    TokenKind::RBrace if depth == 0 => return false,
1732                    TokenKind::RBrace => depth -= 1,
1733                    TokenKind::RParen | TokenKind::RBracket => {
1734                        if depth > 0 {
1735                            depth -= 1;
1736                        }
1737                    }
1738                    _ => {}
1739                }
1740                self.advance();
1741            } else {
1742                return false;
1743            }
1744        }
1745        false
1746    }
1747
1748    /// Parse closure params and body (after opening { has been consumed).
1749    fn parse_closure_body(&mut self, start: Span) -> Result<SNode, ParserError> {
1750        let params = self.parse_typed_param_list_until_arrow()?;
1751        self.consume(&TokenKind::Arrow, "->")?;
1752        let body = self.parse_block()?;
1753        self.consume(&TokenKind::RBrace, "}")?;
1754        Ok(spanned(
1755            Node::Closure { params, body },
1756            Span::merge(start, self.prev_span()),
1757        ))
1758    }
1759
1760    /// Parse typed params until we see ->. Handles: `x`, `x: int`, `x, y`, `x: int, y: string`.
1761    fn parse_typed_param_list_until_arrow(&mut self) -> Result<Vec<TypedParam>, ParserError> {
1762        self.parse_typed_params_until(|tok| tok == &TokenKind::Arrow)
1763    }
1764
1765    fn parse_dict_literal(&mut self, start: Span) -> Result<SNode, ParserError> {
1766        let mut entries = Vec::new();
1767        self.skip_newlines();
1768
1769        while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
1770            // Check for spread: ...expr
1771            if self.check(&TokenKind::Dot) {
1772                let saved_pos = self.pos;
1773                self.advance(); // first .
1774                if self.check(&TokenKind::Dot) {
1775                    self.advance(); // second .
1776                    if self.check(&TokenKind::Dot) {
1777                        self.advance(); // third .
1778                        let spread_start = self.tokens[saved_pos].span;
1779                        let expr = self.parse_expression()?;
1780                        entries.push(DictEntry {
1781                            key: spanned(Node::NilLiteral, spread_start),
1782                            value: spanned(
1783                                Node::Spread(Box::new(expr)),
1784                                Span::merge(spread_start, self.prev_span()),
1785                            ),
1786                        });
1787                        self.skip_newlines();
1788                        if self.check(&TokenKind::Comma) {
1789                            self.advance();
1790                            self.skip_newlines();
1791                        }
1792                        continue;
1793                    }
1794                    // Not three dots — restore
1795                    self.pos = saved_pos;
1796                } else {
1797                    self.pos = saved_pos;
1798                }
1799            }
1800            let key = if self.check(&TokenKind::LBracket) {
1801                // Computed key: [expression]
1802                self.advance();
1803                let k = self.parse_expression()?;
1804                self.consume(&TokenKind::RBracket, "]")?;
1805                k
1806            } else if matches!(
1807                self.current().map(|t| &t.kind),
1808                Some(TokenKind::StringLiteral(_))
1809            ) {
1810                // Quoted string key: {"key": value}
1811                let key_span = self.current_span();
1812                let name =
1813                    if let Some(TokenKind::StringLiteral(s)) = self.current().map(|t| &t.kind) {
1814                        s.clone()
1815                    } else {
1816                        unreachable!()
1817                    };
1818                self.advance();
1819                spanned(Node::StringLiteral(name), key_span)
1820            } else {
1821                // Static key: identifier or keyword -> string literal
1822                let key_span = self.current_span();
1823                let name = self.consume_identifier_or_keyword("dict key")?;
1824                spanned(Node::StringLiteral(name), key_span)
1825            };
1826            self.consume(&TokenKind::Colon, ":")?;
1827            let value = self.parse_expression()?;
1828            entries.push(DictEntry { key, value });
1829            self.skip_newlines();
1830            if self.check(&TokenKind::Comma) {
1831                self.advance();
1832                self.skip_newlines();
1833            }
1834        }
1835
1836        self.consume(&TokenKind::RBrace, "}")?;
1837        Ok(spanned(
1838            Node::DictLiteral(entries),
1839            Span::merge(start, self.prev_span()),
1840        ))
1841    }
1842
1843    // --- Helpers ---
1844
1845    /// Parse untyped parameter list (for pipelines, overrides).
1846    fn parse_param_list(&mut self) -> Result<Vec<String>, ParserError> {
1847        let mut params = Vec::new();
1848        self.skip_newlines();
1849
1850        while !self.is_at_end() && !self.check(&TokenKind::RParen) {
1851            params.push(self.consume_identifier("parameter name")?);
1852            if self.check(&TokenKind::Comma) {
1853                self.advance();
1854                self.skip_newlines();
1855            }
1856        }
1857        Ok(params)
1858    }
1859
1860    /// Parse typed parameter list (for fn declarations).
1861    fn parse_typed_param_list(&mut self) -> Result<Vec<TypedParam>, ParserError> {
1862        self.parse_typed_params_until(|tok| tok == &TokenKind::RParen)
1863    }
1864
1865    /// Shared implementation: parse typed params with optional defaults until
1866    /// a terminator token is reached.
1867    fn parse_typed_params_until(
1868        &mut self,
1869        is_terminator: impl Fn(&TokenKind) -> bool,
1870    ) -> Result<Vec<TypedParam>, ParserError> {
1871        let mut params = Vec::new();
1872        let mut seen_default = false;
1873        self.skip_newlines();
1874
1875        while !self.is_at_end() {
1876            if let Some(tok) = self.current() {
1877                if is_terminator(&tok.kind) {
1878                    break;
1879                }
1880            } else {
1881                break;
1882            }
1883            let name = self.consume_identifier("parameter name")?;
1884            let type_expr = self.try_parse_type_annotation()?;
1885            let default_value = if self.check(&TokenKind::Assign) {
1886                self.advance();
1887                seen_default = true;
1888                Some(Box::new(self.parse_expression()?))
1889            } else {
1890                if seen_default {
1891                    return Err(self.error(
1892                        "Required parameter cannot follow a parameter with a default value",
1893                    ));
1894                }
1895                None
1896            };
1897            params.push(TypedParam {
1898                name,
1899                type_expr,
1900                default_value,
1901            });
1902            if self.check(&TokenKind::Comma) {
1903                self.advance();
1904                self.skip_newlines();
1905            }
1906        }
1907        Ok(params)
1908    }
1909
1910    /// Parse a comma-separated list of type parameter names until `>`.
1911    fn parse_type_param_list(&mut self) -> Result<Vec<TypeParam>, ParserError> {
1912        let mut params = Vec::new();
1913        self.skip_newlines();
1914        while !self.is_at_end() && !self.check(&TokenKind::Gt) {
1915            let name = self.consume_identifier("type parameter name")?;
1916            params.push(TypeParam { name });
1917            if self.check(&TokenKind::Comma) {
1918                self.advance();
1919                self.skip_newlines();
1920            }
1921        }
1922        self.consume(&TokenKind::Gt, ">")?;
1923        Ok(params)
1924    }
1925
1926    /// Parse an optional `where T: bound, U: bound` clause.
1927    /// Looks for an identifier "where" before `{`.
1928    fn parse_where_clauses(&mut self) -> Result<Vec<WhereClause>, ParserError> {
1929        // Check if the next identifier is "where"
1930        if let Some(tok) = self.current() {
1931            if let TokenKind::Identifier(ref id) = tok.kind {
1932                if id == "where" {
1933                    self.advance(); // skip "where"
1934                    let mut clauses = Vec::new();
1935                    loop {
1936                        self.skip_newlines();
1937                        // Stop if we hit `{` or EOF
1938                        if self.check(&TokenKind::LBrace) || self.is_at_end() {
1939                            break;
1940                        }
1941                        let type_name = self.consume_identifier("type parameter name")?;
1942                        self.consume(&TokenKind::Colon, ":")?;
1943                        let bound = self.consume_identifier("type bound")?;
1944                        clauses.push(WhereClause { type_name, bound });
1945                        if self.check(&TokenKind::Comma) {
1946                            self.advance();
1947                        } else {
1948                            break;
1949                        }
1950                    }
1951                    return Ok(clauses);
1952                }
1953            }
1954        }
1955        Ok(Vec::new())
1956    }
1957
1958    /// Try to parse an optional type annotation (`: type`).
1959    /// Returns None if no colon follows.
1960    fn try_parse_type_annotation(&mut self) -> Result<Option<TypeExpr>, ParserError> {
1961        if !self.check(&TokenKind::Colon) {
1962            return Ok(None);
1963        }
1964        self.advance(); // skip :
1965        Ok(Some(self.parse_type_expr()?))
1966    }
1967
1968    /// Parse a type expression: `int`, `string | nil`, `{name: string, age?: int}`.
1969    fn parse_type_expr(&mut self) -> Result<TypeExpr, ParserError> {
1970        self.skip_newlines();
1971        let first = self.parse_type_primary()?;
1972
1973        // Check for union: type | type | ...
1974        if self.check(&TokenKind::Bar) {
1975            let mut types = vec![first];
1976            while self.check(&TokenKind::Bar) {
1977                self.advance(); // skip |
1978                types.push(self.parse_type_primary()?);
1979            }
1980            return Ok(TypeExpr::Union(types));
1981        }
1982
1983        Ok(first)
1984    }
1985
1986    /// Parse a primary type: named type or shape type.
1987    /// Accepts identifiers and certain keywords (nil, bool, etc.) as type names.
1988    fn parse_type_primary(&mut self) -> Result<TypeExpr, ParserError> {
1989        self.skip_newlines();
1990        if self.check(&TokenKind::LBrace) {
1991            return self.parse_shape_type();
1992        }
1993        // Accept keyword type names: nil, true, false map to their type names
1994        if let Some(tok) = self.current() {
1995            let type_name = match &tok.kind {
1996                TokenKind::Nil => {
1997                    self.advance();
1998                    return Ok(TypeExpr::Named("nil".to_string()));
1999                }
2000                TokenKind::True | TokenKind::False => {
2001                    self.advance();
2002                    return Ok(TypeExpr::Named("bool".to_string()));
2003                }
2004                _ => None,
2005            };
2006            if let Some(name) = type_name {
2007                return Ok(TypeExpr::Named(name));
2008            }
2009        }
2010        // Function type: fn(T, U) -> R
2011        if self.check(&TokenKind::Fn) {
2012            self.advance(); // skip `fn`
2013            self.consume(&TokenKind::LParen, "(")?;
2014            let mut params = Vec::new();
2015            self.skip_newlines();
2016            while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2017                params.push(self.parse_type_expr()?);
2018                self.skip_newlines();
2019                if self.check(&TokenKind::Comma) {
2020                    self.advance();
2021                    self.skip_newlines();
2022                }
2023            }
2024            self.consume(&TokenKind::RParen, ")")?;
2025            self.consume(&TokenKind::Arrow, "->")?;
2026            let return_type = self.parse_type_expr()?;
2027            return Ok(TypeExpr::FnType {
2028                params,
2029                return_type: Box::new(return_type),
2030            });
2031        }
2032        let name = self.consume_identifier("type name")?;
2033        // Check for generic type parameters: list<int>, dict<string, int>
2034        if self.check(&TokenKind::Lt) {
2035            self.advance(); // skip <
2036            let first_param = self.parse_type_expr()?;
2037            if name == "list" {
2038                self.consume(&TokenKind::Gt, ">")?;
2039                return Ok(TypeExpr::List(Box::new(first_param)));
2040            } else if name == "dict" {
2041                self.consume(&TokenKind::Comma, ",")?;
2042                let second_param = self.parse_type_expr()?;
2043                self.consume(&TokenKind::Gt, ">")?;
2044                return Ok(TypeExpr::DictType(
2045                    Box::new(first_param),
2046                    Box::new(second_param),
2047                ));
2048            }
2049            // Unknown generic — just consume > and treat as Named
2050            self.consume(&TokenKind::Gt, ">")?;
2051        }
2052        Ok(TypeExpr::Named(name))
2053    }
2054
2055    /// Parse a shape type: `{ name: string, age: int, active?: bool }`.
2056    fn parse_shape_type(&mut self) -> Result<TypeExpr, ParserError> {
2057        self.consume(&TokenKind::LBrace, "{")?;
2058        let mut fields = Vec::new();
2059        self.skip_newlines();
2060
2061        while !self.is_at_end() && !self.check(&TokenKind::RBrace) {
2062            let name = self.consume_identifier("field name")?;
2063            let optional = if self.check(&TokenKind::Question) {
2064                self.advance();
2065                true
2066            } else {
2067                false
2068            };
2069            self.consume(&TokenKind::Colon, ":")?;
2070            let type_expr = self.parse_type_expr()?;
2071            fields.push(ShapeField {
2072                name,
2073                type_expr,
2074                optional,
2075            });
2076            self.skip_newlines();
2077            if self.check(&TokenKind::Comma) {
2078                self.advance();
2079                self.skip_newlines();
2080            }
2081        }
2082
2083        self.consume(&TokenKind::RBrace, "}")?;
2084        Ok(TypeExpr::Shape(fields))
2085    }
2086
2087    fn parse_arg_list(&mut self) -> Result<Vec<SNode>, ParserError> {
2088        let mut args = Vec::new();
2089        self.skip_newlines();
2090
2091        while !self.is_at_end() && !self.check(&TokenKind::RParen) {
2092            args.push(self.parse_expression()?);
2093            self.skip_newlines();
2094            if self.check(&TokenKind::Comma) {
2095                self.advance();
2096                self.skip_newlines();
2097            }
2098        }
2099        Ok(args)
2100    }
2101
2102    fn is_at_end(&self) -> bool {
2103        self.pos >= self.tokens.len()
2104            || matches!(self.tokens.get(self.pos), Some(t) if t.kind == TokenKind::Eof)
2105    }
2106
2107    fn current(&self) -> Option<&Token> {
2108        self.tokens.get(self.pos)
2109    }
2110
2111    fn peek_kind(&self) -> Option<&TokenKind> {
2112        self.tokens.get(self.pos + 1).map(|t| &t.kind)
2113    }
2114
2115    fn check(&self, kind: &TokenKind) -> bool {
2116        self.current()
2117            .map(|t| std::mem::discriminant(&t.kind) == std::mem::discriminant(kind))
2118            .unwrap_or(false)
2119    }
2120
2121    /// Check for a token kind, skipping past any newlines first.
2122    /// Used for binary operators like `||` and `&&` that can span lines.
2123    fn check_skip_newlines(&mut self, kind: &TokenKind) -> bool {
2124        let saved = self.pos;
2125        self.skip_newlines();
2126        if self.check(kind) {
2127            true
2128        } else {
2129            self.pos = saved;
2130            false
2131        }
2132    }
2133
2134    fn advance(&mut self) {
2135        if self.pos < self.tokens.len() {
2136            self.pos += 1;
2137        }
2138    }
2139
2140    fn consume(&mut self, kind: &TokenKind, expected: &str) -> Result<Token, ParserError> {
2141        self.skip_newlines();
2142        let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2143        if std::mem::discriminant(&tok.kind) != std::mem::discriminant(kind) {
2144            return Err(self.make_error(expected));
2145        }
2146        let tok = tok.clone();
2147        self.advance();
2148        Ok(tok)
2149    }
2150
2151    fn consume_identifier(&mut self, expected: &str) -> Result<String, ParserError> {
2152        self.skip_newlines();
2153        let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2154        if let TokenKind::Identifier(name) = &tok.kind {
2155            let name = name.clone();
2156            self.advance();
2157            Ok(name)
2158        } else {
2159            Err(self.make_error(expected))
2160        }
2161    }
2162
2163    /// Like `consume_identifier`, but also accepts keywords as identifiers.
2164    /// Used for property access (e.g., `obj.type`) and dict keys where
2165    /// keywords are valid member names.
2166    fn consume_identifier_or_keyword(&mut self, expected: &str) -> Result<String, ParserError> {
2167        self.skip_newlines();
2168        let tok = self.current().ok_or_else(|| self.make_error(expected))?;
2169        if let TokenKind::Identifier(name) = &tok.kind {
2170            let name = name.clone();
2171            self.advance();
2172            return Ok(name);
2173        }
2174        // Accept any keyword token as an identifier
2175        let name = match &tok.kind {
2176            TokenKind::Pipeline => "pipeline",
2177            TokenKind::Extends => "extends",
2178            TokenKind::Override => "override",
2179            TokenKind::Let => "let",
2180            TokenKind::Var => "var",
2181            TokenKind::If => "if",
2182            TokenKind::Else => "else",
2183            TokenKind::For => "for",
2184            TokenKind::In => "in",
2185            TokenKind::Match => "match",
2186            TokenKind::Retry => "retry",
2187            TokenKind::Parallel => "parallel",
2188            TokenKind::ParallelMap => "parallel_map",
2189            TokenKind::Return => "return",
2190            TokenKind::Import => "import",
2191            TokenKind::True => "true",
2192            TokenKind::False => "false",
2193            TokenKind::Nil => "nil",
2194            TokenKind::Try => "try",
2195            TokenKind::Catch => "catch",
2196            TokenKind::Throw => "throw",
2197            TokenKind::Fn => "fn",
2198            TokenKind::Spawn => "spawn",
2199            TokenKind::While => "while",
2200            TokenKind::TypeKw => "type",
2201            TokenKind::Enum => "enum",
2202            TokenKind::Struct => "struct",
2203            TokenKind::Interface => "interface",
2204            TokenKind::Pub => "pub",
2205            TokenKind::From => "from",
2206            TokenKind::Thru => "thru",
2207            TokenKind::Upto => "upto",
2208            TokenKind::Guard => "guard",
2209            TokenKind::Ask => "ask",
2210            TokenKind::Deadline => "deadline",
2211            TokenKind::Yield => "yield",
2212            TokenKind::Mutex => "mutex",
2213            TokenKind::Break => "break",
2214            TokenKind::Continue => "continue",
2215            TokenKind::Impl => "impl",
2216            _ => return Err(self.make_error(expected)),
2217        };
2218        let name = name.to_string();
2219        self.advance();
2220        Ok(name)
2221    }
2222
2223    fn skip_newlines(&mut self) {
2224        while self.pos < self.tokens.len() && self.tokens[self.pos].kind == TokenKind::Newline {
2225            self.pos += 1;
2226        }
2227    }
2228
2229    fn make_error(&self, expected: &str) -> ParserError {
2230        if let Some(tok) = self.tokens.get(self.pos) {
2231            if tok.kind == TokenKind::Eof {
2232                return ParserError::UnexpectedEof {
2233                    expected: expected.into(),
2234                };
2235            }
2236            ParserError::Unexpected {
2237                got: tok.kind.to_string(),
2238                expected: expected.into(),
2239                span: tok.span,
2240            }
2241        } else {
2242            ParserError::UnexpectedEof {
2243                expected: expected.into(),
2244            }
2245        }
2246    }
2247
2248    fn error(&self, expected: &str) -> ParserError {
2249        self.make_error(expected)
2250    }
2251}