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