Skip to main content

crisp_parser/
parser.rs

1use crisp_ast::{
2    Span,
3    expr::{
4        BinaryOp, Block, Expr, ExprKind, FieldInit, MatchArm, Ownership, Param, Stmt, StringPart,
5        StringParts, UnaryOp,
6    },
7    ident::Ident,
8    item::{
9        ConstDef, ExternBlock, ExternFn, FieldDef, FunctionDef, ImplBlock, Item, ShapeDef,
10        ShapeField, SourceFile, TestDef, TraitDef, TraitItem, TypeBody, TypeDef, UseDecl,
11        UseImport, VariantDef,
12    },
13    pat::{FieldPat, Pat, PatKind},
14    ty::{ErrorType, Type, TypeBound, TypeKind},
15};
16use crisp_lexer::{Kw, Token, TokenKind, lex};
17use thiserror::Error;
18
19#[derive(Debug, Error)]
20pub enum ParseError {
21    #[error("lex error: {0}")]
22    Lex(#[from] crisp_lexer::LexError),
23    #[error("{}", format_unexpected(.expected, .found, .pos, .help))]
24    Unexpected {
25        expected: &'static str,
26        found: TokenKind,
27        pos: u32,
28        help: Option<&'static str>,
29    },
30    #[error("unexpected end of file, expected {expected}")]
31    UnexpectedEof { expected: &'static str },
32    #[error("invalid pattern at byte {pos}")]
33    InvalidPat { pos: u32 },
34}
35
36fn format_unexpected(
37    expected: &&'static str,
38    found: &TokenKind,
39    pos: &u32,
40    help: &Option<&'static str>,
41) -> String {
42    let mut msg = format!("unexpected token {found:?} at byte {pos}, expected {expected}");
43    if let Some(h) = help {
44        msg.push_str("\nhelp: ");
45        msg.push_str(h);
46    }
47    msg
48}
49
50pub struct Parser {
51    tokens: Vec<Token>,
52    pos: usize,
53    /// When false, `Name { … }` is not parsed as a struct literal (Rust-style
54    /// restriction for `if`/`while`/`for` conditions so `{` can start the body).
55    allow_struct_lit: bool,
56}
57
58impl Parser {
59    pub fn new(source: &str) -> Result<Self, ParseError> {
60        Ok(Self {
61            tokens: lex(source)?,
62            pos: 0,
63            allow_struct_lit: true,
64        })
65    }
66
67    fn with_no_struct_lit<T>(
68        &mut self,
69        f: impl FnOnce(&mut Self) -> Result<T, ParseError>,
70    ) -> Result<T, ParseError> {
71        let prev = self.allow_struct_lit;
72        self.allow_struct_lit = false;
73        let result = f(self);
74        self.allow_struct_lit = prev;
75        result
76    }
77
78    pub fn parse_file(&mut self) -> Result<SourceFile, ParseError> {
79        let start = self.current_start();
80        let mut items = Vec::new();
81        while !self.check(TokenKind::Eof) {
82            items.push(self.parse_item()?);
83        }
84        let end = if items.is_empty() {
85            start
86        } else {
87            items.last().unwrap().span().end
88        };
89        Ok(SourceFile {
90            items,
91            span: Span::new(start, end),
92        })
93    }
94
95    pub fn parse_module(&mut self) -> Result<Vec<Item>, ParseError> {
96        Ok(self.parse_file()?.items)
97    }
98
99    // ── Items ─────────────────────────────────────────────────────────────
100
101    fn parse_item(&mut self) -> Result<Item, ParseError> {
102        let pub_span = if self.match_kw(Kw::Pub) {
103            Some(self.previous_span())
104        } else {
105            None
106        };
107        let is_pub = pub_span.is_some();
108
109        if self.match_kw(Kw::Type) {
110            return Ok(Item::TypeDef(self.parse_type_def(is_pub)?));
111        }
112        if self.match_kw(Kw::Trait) {
113            return Ok(Item::TraitDef(self.parse_trait_def()?));
114        }
115        if self.match_kw(Kw::Shape) {
116            return Ok(Item::ShapeDef(self.parse_shape_def()?));
117        }
118        if self.match_kw(Kw::Impl) {
119            return Ok(Item::Impl(self.parse_impl_block()?));
120        }
121        if self.match_kw(Kw::Use) {
122            return Ok(Item::Use(self.parse_use_decl(is_pub)?));
123        }
124        if self.match_kw(Kw::Extern) {
125            return Ok(Item::Extern(self.parse_extern_block()?));
126        }
127        if self.match_kw(Kw::TestCompileFail) {
128            return Ok(Item::TestCompileFail(self.parse_test_def()?));
129        }
130        if self.match_kw(Kw::Test) {
131            return Ok(Item::Test(self.parse_test_def()?));
132        }
133
134        let name = self.expect_ident()?;
135        if self.check(TokenKind::LParen) {
136            return Ok(Item::Function(
137                self.parse_function_after_name(is_pub, name)?,
138            ));
139        }
140        if self.check(TokenKind::Assign) {
141            self.advance();
142            let value = self.parse_expr()?;
143            let span = name.span.merge(value.span);
144            return Ok(Item::Const(ConstDef { name, value, span }));
145        }
146
147        Err(self.unexpected("item", self.peek_kind()))
148    }
149
150    fn parse_function_after_name(
151        &mut self,
152        is_pub: bool,
153        name: Ident,
154    ) -> Result<FunctionDef, ParseError> {
155        let start = name.span.start;
156        self.expect(TokenKind::LParen)?;
157        let params = self.parse_params()?;
158        self.expect(TokenKind::RParen)?;
159        let ret_type = if self.match_token(TokenKind::Arrow) {
160            Some(self.parse_type()?)
161        } else {
162            None
163        };
164        let error_type = if self.check(TokenKind::Bang) {
165            Some(self.parse_error_type()?)
166        } else {
167            None
168        };
169        self.expect(TokenKind::Assign)?;
170        let body = self.parse_expr()?;
171        let end = body.span.end;
172        Ok(FunctionDef {
173            is_pub,
174            name,
175            generics: vec![],
176            params,
177            ret_type,
178            error_type,
179            body,
180            span: Span::new(start, end),
181        })
182    }
183
184    fn parse_params(&mut self) -> Result<Vec<Param>, ParseError> {
185        let mut params = Vec::new();
186        if self.check(TokenKind::RParen) {
187            return Ok(params);
188        }
189        loop {
190            params.push(self.parse_param()?);
191            if !self.match_token(TokenKind::Comma) {
192                break;
193            }
194        }
195        Ok(params)
196    }
197
198    fn parse_param(&mut self) -> Result<Param, ParseError> {
199        let start = self.current_start();
200        let lifetime = if self.check_lifetime() {
201            Some(self.parse_lifetime_ident()?)
202        } else {
203            None
204        };
205        let ownership = if self.match_kw(Kw::Own) {
206            Some(Ownership::Own)
207        } else if self.match_token(TokenKind::AmpMut) {
208            Some(Ownership::RefMut)
209        } else if self.match_token(TokenKind::Amp) {
210            Some(Ownership::Ref)
211        } else {
212            None
213        };
214        let name = self.expect_ident()?;
215        let ty = if self.match_token(TokenKind::Colon) {
216            Some(self.parse_type()?)
217        } else {
218            None
219        };
220        Ok(Param {
221            lifetime,
222            ownership,
223            name,
224            ty,
225            span: Span::new(start, self.previous_end()),
226        })
227    }
228
229    fn parse_type_def(&mut self, is_pub: bool) -> Result<TypeDef, ParseError> {
230        let start = self.previous_start();
231        let name = self.expect_ident()?;
232        let generics = self.parse_optional_generics()?;
233        self.expect(TokenKind::Assign)?;
234        let (body, end) = if self.match_token(TokenKind::LBrace) {
235            let fields = self.parse_struct_fields()?;
236            self.expect(TokenKind::RBrace)?;
237            let end = self.previous_end();
238            (TypeBody::Struct(fields), end)
239        } else if self.match_token(TokenKind::Pipe) {
240            let variants = self.parse_enum_variants()?;
241            (TypeBody::Enum(variants), self.previous_end())
242        } else {
243            let ty = self.parse_type()?;
244            (TypeBody::Alias(ty.clone()), ty.span.end)
245        };
246        Ok(TypeDef {
247            is_pub,
248            name,
249            generics,
250            body,
251            span: Span::new(start, end),
252        })
253    }
254
255    fn parse_struct_fields(&mut self) -> Result<Vec<FieldDef>, ParseError> {
256        let mut fields = Vec::new();
257        while !self.check(TokenKind::RBrace) && !self.check(TokenKind::Eof) {
258            let start = self.current_start();
259            let name = self.expect_ident()?;
260            self.expect(TokenKind::Colon)?;
261            let ty = self.parse_type()?;
262            let default = if self.match_token(TokenKind::Assign) {
263                Some(self.parse_expr()?)
264            } else {
265                None
266            };
267            fields.push(FieldDef {
268                name,
269                ty,
270                default,
271                span: Span::new(start, self.previous_end()),
272            });
273        }
274        Ok(fields)
275    }
276
277    fn parse_enum_variants(&mut self) -> Result<Vec<VariantDef>, ParseError> {
278        let mut variants = Vec::new();
279        loop {
280            let start = self.current_start();
281            let name = self.expect_ident()?;
282            let fields = if self.match_token(TokenKind::LParen) {
283                let mut types = Vec::new();
284                while !self.check(TokenKind::RParen) {
285                    types.push(self.parse_type()?);
286                    if !self.match_token(TokenKind::Comma) {
287                        break;
288                    }
289                }
290                self.expect(TokenKind::RParen)?;
291                types
292            } else {
293                vec![]
294            };
295            variants.push(VariantDef {
296                name,
297                fields,
298                span: Span::new(start, self.previous_end()),
299            });
300            if !self.match_token(TokenKind::Pipe) {
301                break;
302            }
303        }
304        Ok(variants)
305    }
306
307    fn parse_trait_def(&mut self) -> Result<TraitDef, ParseError> {
308        let start = self.previous_start();
309        let name = self.expect_ident()?;
310        self.expect(TokenKind::Assign)?;
311        self.expect(TokenKind::LBrace)?;
312        let mut items = Vec::new();
313        while !self.check(TokenKind::RBrace) && !self.check(TokenKind::Eof) {
314            items.push(self.parse_trait_item()?);
315        }
316        self.expect(TokenKind::RBrace)?;
317        Ok(TraitDef {
318            name,
319            items,
320            span: Span::new(start, self.previous_end()),
321        })
322    }
323
324    fn parse_trait_item(&mut self) -> Result<TraitItem, ParseError> {
325        let start = self.current_start();
326        let name = self.expect_ident()?;
327        self.expect(TokenKind::LParen)?;
328        let params = self.parse_params()?;
329        self.expect(TokenKind::RParen)?;
330        let ret_type = if self.match_token(TokenKind::Arrow) {
331            Some(self.parse_type()?)
332        } else {
333            None
334        };
335        let default_body = if self.match_token(TokenKind::Assign) {
336            Some(self.parse_expr()?)
337        } else {
338            None
339        };
340        Ok(TraitItem {
341            name,
342            params,
343            ret_type,
344            default_body,
345            span: Span::new(start, self.previous_end()),
346        })
347    }
348
349    fn parse_shape_def(&mut self) -> Result<ShapeDef, ParseError> {
350        let start = self.previous_start();
351        let name = self.expect_ident()?;
352        self.expect(TokenKind::Assign)?;
353        self.expect(TokenKind::LBrace)?;
354        let mut fields = Vec::new();
355        while !self.check(TokenKind::RBrace) && !self.check(TokenKind::Eof) {
356            fields.push(self.parse_shape_field()?);
357        }
358        self.expect(TokenKind::RBrace)?;
359        Ok(ShapeDef {
360            name,
361            fields,
362            span: Span::new(start, self.previous_end()),
363        })
364    }
365
366    fn parse_shape_field(&mut self) -> Result<ShapeField, ParseError> {
367        let start = self.current_start();
368        let name = self.expect_ident()?;
369        if self.match_token(TokenKind::Colon) {
370            let ty = self.parse_type()?;
371            return Ok(ShapeField::Data {
372                name,
373                ty,
374                span: Span::new(start, self.previous_end()),
375            });
376        }
377        self.expect(TokenKind::LParen)?;
378        let params = self.parse_params()?;
379        self.expect(TokenKind::RParen)?;
380        self.expect(TokenKind::Arrow)?;
381        let ret_type = self.parse_type()?;
382        Ok(ShapeField::Method {
383            name,
384            params,
385            ret_type,
386            span: Span::new(start, self.previous_end()),
387        })
388    }
389
390    fn parse_impl_block(&mut self) -> Result<ImplBlock, ParseError> {
391        let start = self.previous_start();
392        let first = self.expect_ident()?;
393        let (trait_name, ty) = if self.match_kw(Kw::For) {
394            let ty = self.parse_type()?;
395            (Some(first), ty)
396        } else {
397            (
398                None,
399                Type {
400                    kind: TypeKind::Named(first.clone()),
401                    span: first.span,
402                },
403            )
404        };
405        let mut items = Vec::new();
406        if self.match_token(TokenKind::Assign) {
407            self.expect(TokenKind::LBrace)?;
408            while !self.check(TokenKind::RBrace) && !self.check(TokenKind::Eof) {
409                let is_pub = self.match_kw(Kw::Pub);
410                let name = self.expect_ident()?;
411                items.push(self.parse_function_after_name(is_pub, name)?);
412            }
413            self.expect(TokenKind::RBrace)?;
414        }
415        Ok(ImplBlock {
416            trait_name,
417            ty,
418            items,
419            span: Span::new(start, self.previous_end()),
420        })
421    }
422
423    fn parse_use_decl(&mut self, is_pub: bool) -> Result<UseDecl, ParseError> {
424        let start = self.previous_start();
425        let mut path = vec![self.expect_ident()?];
426        // Crisp module paths use `.`; spec §14.2 also writes `use rust::crate` — accept both.
427        while self.match_token(TokenKind::Dot) || self.match_colon_colon() {
428            path.push(self.expect_ident()?);
429        }
430        let imports = if self.match_token(TokenKind::LBrace) {
431            let mut list = Vec::new();
432            while !self.check(TokenKind::RBrace) {
433                let s = self.current_start();
434                let name = self.expect_ident()?;
435                let alias = if self.match_kw(Kw::As) {
436                    Some(self.expect_ident()?)
437                } else {
438                    None
439                };
440                list.push(UseImport {
441                    name,
442                    alias,
443                    span: Span::new(s, self.previous_end()),
444                });
445                if !self.match_token(TokenKind::Comma) {
446                    break;
447                }
448            }
449            self.expect(TokenKind::RBrace)?;
450            Some(list)
451        } else {
452            None
453        };
454        Ok(UseDecl {
455            is_pub,
456            path,
457            imports,
458            span: Span::new(start, self.previous_end()),
459        })
460    }
461
462    fn parse_extern_block(&mut self) -> Result<ExternBlock, ParseError> {
463        let start = self.previous_start();
464        let abi = self.expect_string_lit()?;
465        self.expect(TokenKind::LBrace)?;
466        let mut functions = Vec::new();
467        while !self.check(TokenKind::RBrace) && !self.check(TokenKind::Eof) {
468            let s = self.current_start();
469            let name = self.expect_ident()?;
470            self.expect(TokenKind::LParen)?;
471            let params = self.parse_params()?;
472            self.expect(TokenKind::RParen)?;
473            let ret_type = if self.match_token(TokenKind::Arrow) {
474                Some(self.parse_type()?)
475            } else {
476                None
477            };
478            functions.push(ExternFn {
479                name,
480                params,
481                ret_type,
482                span: Span::new(s, self.previous_end()),
483            });
484        }
485        self.expect(TokenKind::RBrace)?;
486        Ok(ExternBlock {
487            abi,
488            functions,
489            span: Span::new(start, self.previous_end()),
490        })
491    }
492
493    fn parse_test_def(&mut self) -> Result<TestDef, ParseError> {
494        let start = self.previous_start();
495        let name = self.expect_string_lit()?;
496        self.expect(TokenKind::Assign)?;
497        let body = self.parse_block()?;
498        let end = body.span.end;
499        Ok(TestDef {
500            name,
501            body,
502            span: Span::new(start, end),
503        })
504    }
505
506    // ── Types ─────────────────────────────────────────────────────────────
507
508    fn parse_type(&mut self) -> Result<Type, ParseError> {
509        let start = self.current_start();
510        if self.match_token(TokenKind::Question) {
511            let inner = self.parse_type()?;
512            return Ok(Type {
513                kind: TypeKind::Option(Box::new(inner)),
514                span: Span::new(start, self.previous_end()),
515            });
516        }
517        if self.match_token(TokenKind::AmpMut) {
518            let inner = self.parse_type()?;
519            return Ok(Type {
520                kind: TypeKind::Ref {
521                    mutable: true,
522                    inner: Box::new(inner),
523                },
524                span: Span::new(start, self.previous_end()),
525            });
526        }
527        if self.match_token(TokenKind::Amp) {
528            let inner = self.parse_type()?;
529            return Ok(Type {
530                kind: TypeKind::Ref {
531                    mutable: false,
532                    inner: Box::new(inner),
533                },
534                span: Span::new(start, self.previous_end()),
535            });
536        }
537        if self.match_token(TokenKind::LParen) {
538            if self.check(TokenKind::RParen) {
539                self.advance();
540                return Ok(Type {
541                    kind: TypeKind::Unit,
542                    span: Span::new(start, self.previous_end()),
543                });
544            }
545            let mut types = vec![self.parse_type()?];
546            while self.match_token(TokenKind::Comma) {
547                types.push(self.parse_type()?);
548            }
549            self.expect(TokenKind::RParen)?;
550            if types.len() == 1 && self.check(TokenKind::Arrow) {
551                self.advance();
552                let ret = self.parse_type()?;
553                return Ok(Type {
554                    kind: TypeKind::Fn {
555                        params: types,
556                        ret: Box::new(ret),
557                    },
558                    span: Span::new(start, self.previous_end()),
559                });
560            }
561            return Ok(Type {
562                kind: TypeKind::Tuple(types),
563                span: Span::new(start, self.previous_end()),
564            });
565        }
566        if self.match_token(TokenKind::LBracket) {
567            let elem = self.parse_type()?;
568            if self.match_token(TokenKind::Semi) && self.is_int() {
569                let TokenKind::Int(n) = self.advance().kind else {
570                    unreachable!();
571                };
572                self.expect(TokenKind::RBracket)?;
573                return Ok(Type {
574                    kind: TypeKind::Array {
575                        elem: Box::new(elem),
576                        len: n as u64,
577                    },
578                    span: Span::new(start, self.previous_end()),
579                });
580            }
581            self.expect(TokenKind::RBracket)?;
582            return Ok(Type {
583                kind: TypeKind::Slice(Box::new(elem)),
584                span: Span::new(start, self.previous_end()),
585            });
586        }
587
588        let base = self.parse_type_primary()?;
589        let mut ty = base;
590        if self.match_token(TokenKind::Lt) {
591            let mut args = vec![self.parse_type()?];
592            while self.match_token(TokenKind::Comma) {
593                args.push(self.parse_type()?);
594            }
595            self.expect(TokenKind::Gt)?;
596            ty = Type {
597                kind: TypeKind::Generic {
598                    base: Box::new(ty),
599                    args,
600                },
601                span: Span::new(start, self.previous_end()),
602            };
603        }
604        while self.match_token(TokenKind::Plus) {
605            let mut bounds = vec![self.parse_type_bound()?];
606            while self.match_token(TokenKind::Plus) {
607                bounds.push(self.parse_type_bound()?);
608            }
609            ty = Type {
610                kind: TypeKind::Constrained {
611                    inner: Box::new(ty),
612                    bounds,
613                },
614                span: Span::new(start, self.previous_end()),
615            };
616        }
617        Ok(ty)
618    }
619
620    fn parse_type_primary(&mut self) -> Result<Type, ParseError> {
621        let start = self.current_start();
622        if let Some(kw) = self.match_kw_opt() {
623            let name = match kw {
624                Kw::True | Kw::False => "bool",
625                _ => return Err(self.unexpected("type", TokenKind::Kw(kw))),
626            };
627            return Ok(Type {
628                kind: TypeKind::Named(Ident::new(name, Span::new(start, self.previous_end()))),
629                span: Span::new(start, self.previous_end()),
630            });
631        }
632        let name = self.expect_ident()?;
633        let kind = match name.name.as_str() {
634            "Never" => TypeKind::Never,
635            "()" => TypeKind::Unit,
636            _ => TypeKind::Named(name.clone()),
637        };
638        Ok(Type {
639            kind,
640            span: name.span,
641        })
642    }
643
644    fn parse_type_bound(&mut self) -> Result<TypeBound, ParseError> {
645        if self.match_kw(Kw::Shape) {
646            return Ok(TypeBound::Shape(self.expect_ident()?));
647        }
648        Ok(TypeBound::Trait(self.expect_ident()?))
649    }
650
651    fn parse_error_type(&mut self) -> Result<ErrorType, ParseError> {
652        let start = self.current_start();
653        self.expect(TokenKind::Bang)?;
654        if self.match_kw(Kw::False) {
655            // !never — use Never keyword path; accept `!never` as ident
656        }
657        let first = self.parse_type()?;
658        let mut variants = vec![first];
659        while self.match_token(TokenKind::Pipe) {
660            variants.push(self.parse_type()?);
661        }
662        Ok(ErrorType {
663            variants,
664            span: Span::new(start, self.previous_end()),
665        })
666    }
667
668    fn parse_optional_generics(&mut self) -> Result<Vec<Ident>, ParseError> {
669        if !self.match_token(TokenKind::Lt) {
670            return Ok(vec![]);
671        }
672        let mut names = vec![self.expect_ident()?];
673        while self.match_token(TokenKind::Comma) {
674            names.push(self.expect_ident()?);
675        }
676        self.expect(TokenKind::Gt)?;
677        Ok(names)
678    }
679
680    // ── Expressions ───────────────────────────────────────────────────────
681
682    fn parse_expr(&mut self) -> Result<Expr, ParseError> {
683        self.parse_pipe()
684    }
685
686    fn parse_pipe(&mut self) -> Result<Expr, ParseError> {
687        let mut left = self.parse_assign()?;
688        while self.match_token(TokenKind::PipeGt) {
689            let right = self.parse_assign()?;
690            let span = left.span.merge(right.span);
691            left = Expr {
692                kind: ExprKind::Pipe {
693                    left: Box::new(left),
694                    right: Box::new(right),
695                },
696                span,
697            };
698        }
699        left = self.parse_catch_suffix(left)?;
700        Ok(left)
701    }
702
703    fn parse_catch_suffix(&mut self, expr: Expr) -> Result<Expr, ParseError> {
704        let mut arms = Vec::new();
705        while self.match_kw(Kw::Catch) {
706            let start = self.previous_start();
707            let pat = self.parse_pat()?;
708            self.expect(TokenKind::Arrow)?;
709            let body = self.parse_pipe()?;
710            let body_end = body.span.end;
711            arms.push(crisp_ast::expr::CatchArm {
712                pat,
713                body,
714                span: Span::new(start, body_end),
715            });
716        }
717        if arms.is_empty() {
718            return Ok(expr);
719        }
720        let expr_start = expr.span.start;
721        let end = arms.last().map(|a| a.span.end).unwrap_or(expr.span.end);
722        Ok(Expr {
723            kind: ExprKind::Catch {
724                body: Box::new(expr),
725                arms,
726            },
727            span: Span::new(expr_start, end),
728        })
729    }
730
731    fn parse_assign(&mut self) -> Result<Expr, ParseError> {
732        let expr = self.parse_or()?;
733        if self.match_token(TokenKind::Assign) {
734            let (name, id_span) = match &expr.kind {
735                ExprKind::Ident(id) => (id.name.clone(), id.span),
736                _ => return Err(self.unexpected("assignable identifier", self.peek_kind())),
737            };
738            let value = self.parse_assign()?;
739            let span = id_span.merge(value.span);
740            return Ok(Expr {
741                kind: ExprKind::Assign {
742                    target: Ident::new(name, id_span),
743                    value: Box::new(value),
744                },
745                span,
746            });
747        }
748        Ok(expr)
749    }
750
751    fn parse_or(&mut self) -> Result<Expr, ParseError> {
752        self.parse_binary(Self::parse_and, TokenKind::Or, BinaryOp::Or)
753    }
754
755    fn parse_and(&mut self) -> Result<Expr, ParseError> {
756        self.parse_binary(Self::parse_equality, TokenKind::And, BinaryOp::And)
757    }
758
759    fn parse_equality(&mut self) -> Result<Expr, ParseError> {
760        let mut left = self.parse_comparison()?;
761        while matches!(self.peek_kind(), TokenKind::EqEq | TokenKind::Ne) {
762            let op = match self.advance().kind {
763                TokenKind::EqEq => BinaryOp::Eq,
764                TokenKind::Ne => BinaryOp::Ne,
765                _ => unreachable!(),
766            };
767            let right = self.parse_comparison()?;
768            let span = left.span.merge(right.span);
769            left = Expr {
770                kind: ExprKind::Binary {
771                    op,
772                    left: Box::new(left),
773                    right: Box::new(right),
774                },
775                span,
776            };
777        }
778        Ok(left)
779    }
780
781    fn parse_comparison(&mut self) -> Result<Expr, ParseError> {
782        let mut left = self.parse_concat()?;
783        while matches!(
784            self.peek_kind(),
785            TokenKind::Lt | TokenKind::Le | TokenKind::Gt | TokenKind::Ge
786        ) {
787            let op = match self.advance().kind {
788                TokenKind::Lt => BinaryOp::Lt,
789                TokenKind::Le => BinaryOp::Le,
790                TokenKind::Gt => BinaryOp::Gt,
791                TokenKind::Ge => BinaryOp::Ge,
792                _ => unreachable!(),
793            };
794            let right = self.parse_concat()?;
795            let span = left.span.merge(right.span);
796            left = Expr {
797                kind: ExprKind::Binary {
798                    op,
799                    left: Box::new(left),
800                    right: Box::new(right),
801                },
802                span,
803            };
804        }
805        Ok(left)
806    }
807
808    fn parse_concat(&mut self) -> Result<Expr, ParseError> {
809        self.parse_binary(Self::parse_additive, TokenKind::PlusPlus, BinaryOp::Concat)
810    }
811
812    fn parse_additive(&mut self) -> Result<Expr, ParseError> {
813        let mut left = self.parse_multiplicative()?;
814        loop {
815            let op = match self.peek_kind() {
816                TokenKind::Plus => BinaryOp::Add,
817                TokenKind::Minus => BinaryOp::Sub,
818                _ => break,
819            };
820            self.advance();
821            let right = self.parse_multiplicative()?;
822            let span = left.span.merge(right.span);
823            left = Expr {
824                kind: ExprKind::Binary {
825                    op,
826                    left: Box::new(left),
827                    right: Box::new(right),
828                },
829                span,
830            };
831        }
832        Ok(left)
833    }
834
835    fn parse_multiplicative(&mut self) -> Result<Expr, ParseError> {
836        let mut left = self.parse_power()?;
837        loop {
838            let op = match self.peek_kind() {
839                TokenKind::Star => BinaryOp::Mul,
840                TokenKind::Slash => BinaryOp::Div,
841                TokenKind::Percent => BinaryOp::Mod,
842                _ => break,
843            };
844            self.advance();
845            let right = self.parse_power()?;
846            let span = left.span.merge(right.span);
847            left = Expr {
848                kind: ExprKind::Binary {
849                    op,
850                    left: Box::new(left),
851                    right: Box::new(right),
852                },
853                span,
854            };
855        }
856        Ok(left)
857    }
858
859    fn parse_power(&mut self) -> Result<Expr, ParseError> {
860        let mut left = self.parse_unary()?;
861        if self.match_token(TokenKind::StarStar) {
862            let right = self.parse_power()?;
863            let span = left.span.merge(right.span);
864            left = Expr {
865                kind: ExprKind::Binary {
866                    op: BinaryOp::Pow,
867                    left: Box::new(left),
868                    right: Box::new(right),
869                },
870                span,
871            };
872        }
873        Ok(left)
874    }
875
876    fn parse_unary(&mut self) -> Result<Expr, ParseError> {
877        let start = self.current_start();
878        if self.match_token(TokenKind::Bang) {
879            let expr = self.parse_unary()?;
880            let end = expr.span.end;
881            return Ok(Expr {
882                kind: ExprKind::Unary {
883                    op: UnaryOp::Not,
884                    expr: Box::new(expr),
885                },
886                span: Span::new(start, end),
887            });
888        }
889        if self.match_token(TokenKind::Minus) {
890            let expr = self.parse_unary()?;
891            let end = expr.span.end;
892            return Ok(Expr {
893                kind: ExprKind::Unary {
894                    op: UnaryOp::Neg,
895                    expr: Box::new(expr),
896                },
897                span: Span::new(start, end),
898            });
899        }
900        if self.match_kw(Kw::Async) {
901            let body = self.parse_unary()?;
902            let end = body.span.end;
903            return Ok(Expr {
904                kind: ExprKind::Async(Box::new(body)),
905                span: Span::new(start, end),
906            });
907        }
908        if self.match_kw(Kw::Await) {
909            let body = self.parse_unary()?;
910            let end = body.span.end;
911            return Ok(Expr {
912                kind: ExprKind::Await(Box::new(body)),
913                span: Span::new(start, end),
914            });
915        }
916        if self.match_kw(Kw::Spawn) {
917            let body = self.parse_unary()?;
918            let end = body.span.end;
919            return Ok(Expr {
920                kind: ExprKind::Spawn(Box::new(body)),
921                span: Span::new(start, end),
922            });
923        }
924        if self.match_kw(Kw::Unsafe) {
925            let body = self.parse_unary()?;
926            let end = body.span.end;
927            return Ok(Expr {
928                kind: ExprKind::Unsafe(Box::new(body)),
929                span: Span::new(start, end),
930            });
931        }
932        if self.match_kw(Kw::Return) {
933            let value = if self.check_expr_start() {
934                Some(Box::new(self.parse_expr()?))
935            } else {
936                None
937            };
938            let end = value
939                .as_ref()
940                .map(|v| v.span.end)
941                .unwrap_or(self.previous_end());
942            return Ok(Expr {
943                kind: ExprKind::Return(value),
944                span: Span::new(start, end),
945            });
946        }
947        if self.match_kw(Kw::Break) {
948            let value = if self.check_expr_start() {
949                Some(Box::new(self.parse_expr()?))
950            } else {
951                None
952            };
953            let end = value
954                .as_ref()
955                .map(|v| v.span.end)
956                .unwrap_or(self.previous_end());
957            return Ok(Expr {
958                kind: ExprKind::Break(value),
959                span: Span::new(start, end),
960            });
961        }
962        if self.match_kw(Kw::Continue) {
963            return Ok(Expr {
964                kind: ExprKind::Continue,
965                span: Span::new(start, self.previous_end()),
966            });
967        }
968        if self.match_kw(Kw::Throw) {
969            let expr = self.parse_unary()?;
970            let end = expr.span.end;
971            return Ok(Expr {
972                kind: ExprKind::Throw(Box::new(expr)),
973                span: Span::new(start, end),
974            });
975        }
976        self.parse_postfix()
977    }
978
979    fn parse_postfix(&mut self) -> Result<Expr, ParseError> {
980        let mut expr = self.parse_primary()?;
981        loop {
982            match self.peek_kind() {
983                TokenKind::LParen => {
984                    self.advance();
985                    let args = self.parse_args()?;
986                    self.expect(TokenKind::RParen)?;
987                    let span = expr
988                        .span
989                        .merge(Span::new(self.previous_start(), self.previous_end()));
990                    expr = Expr {
991                        kind: ExprKind::Call {
992                            func: Box::new(expr),
993                            args,
994                        },
995                        span,
996                    };
997                }
998                TokenKind::Dot => {
999                    self.advance();
1000                    let field = self.expect_ident()?;
1001                    let span = expr.span.merge(field.span);
1002                    expr = Expr {
1003                        kind: ExprKind::Field {
1004                            base: Box::new(expr),
1005                            field,
1006                        },
1007                        span,
1008                    };
1009                }
1010                TokenKind::LBracket => {
1011                    self.advance();
1012                    let index = self.parse_expr()?;
1013                    self.expect(TokenKind::RBracket)?;
1014                    let span = expr.span.merge(index.span);
1015                    expr = Expr {
1016                        kind: ExprKind::Index {
1017                            base: Box::new(expr),
1018                            index: Box::new(index),
1019                        },
1020                        span,
1021                    };
1022                }
1023                TokenKind::Question => {
1024                    self.advance();
1025                    let span = expr
1026                        .span
1027                        .merge(Span::new(self.previous_start(), self.previous_end()));
1028                    expr = Expr {
1029                        kind: ExprKind::Try(Box::new(expr)),
1030                        span,
1031                    };
1032                }
1033                _ => break,
1034            }
1035        }
1036        Ok(expr)
1037    }
1038
1039    fn parse_primary(&mut self) -> Result<Expr, ParseError> {
1040        let start = self.current_start();
1041        match self.peek_kind() {
1042            TokenKind::Int(n) => {
1043                self.advance();
1044                Ok(Expr {
1045                    kind: ExprKind::Int(n),
1046                    span: Span::new(start, self.previous_end()),
1047                })
1048            }
1049            TokenKind::Float(f) => {
1050                self.advance();
1051                Ok(Expr {
1052                    kind: ExprKind::Float(f),
1053                    span: Span::new(start, self.previous_end()),
1054                })
1055            }
1056            TokenKind::String(ref s) => {
1057                self.advance();
1058                Ok(Expr {
1059                    kind: ExprKind::Str(self.parse_string_parts(s, start)?),
1060                    span: Span::new(start, self.previous_end()),
1061                })
1062            }
1063            TokenKind::Char(c) => {
1064                self.advance();
1065                Ok(Expr {
1066                    kind: ExprKind::Char(c),
1067                    span: Span::new(start, self.previous_end()),
1068                })
1069            }
1070            TokenKind::Kw(Kw::True) => {
1071                self.advance();
1072                Ok(Expr {
1073                    kind: ExprKind::Bool(true),
1074                    span: Span::new(start, self.previous_end()),
1075                })
1076            }
1077            TokenKind::Kw(Kw::False) => {
1078                self.advance();
1079                Ok(Expr {
1080                    kind: ExprKind::Bool(false),
1081                    span: Span::new(start, self.previous_end()),
1082                })
1083            }
1084            TokenKind::Kw(Kw::None) => {
1085                self.advance();
1086                Ok(self.parse_none_some_call(false, start)?)
1087            }
1088            TokenKind::Kw(Kw::Some) => {
1089                self.advance();
1090                Ok(self.parse_none_some_call(true, start)?)
1091            }
1092            TokenKind::Ident(_) | TokenKind::Kw(_) => {
1093                if self.match_kw(Kw::If) {
1094                    return self.parse_if_expr(start);
1095                }
1096                if self.match_kw(Kw::Match) {
1097                    return self.parse_match_expr(start);
1098                }
1099                if self.match_kw(Kw::For) {
1100                    return self.parse_for_expr(start);
1101                }
1102                if self.match_kw(Kw::While) {
1103                    return self.parse_while_expr(start);
1104                }
1105                if self.match_kw(Kw::Loop) {
1106                    return self.parse_loop_expr(start);
1107                }
1108                let id = self.expect_ident_or_kw_as_ident()?;
1109                let span = id.span;
1110                // struct literal: Name { ... } (disabled in if/while/for heads)
1111                if self.allow_struct_lit && self.check(TokenKind::LBrace) {
1112                    return self.parse_struct_lit(id);
1113                }
1114                Ok(Expr {
1115                    kind: ExprKind::Ident(id),
1116                    span,
1117                })
1118            }
1119            TokenKind::LBrace => Ok(Expr {
1120                kind: ExprKind::Block(self.parse_block()?),
1121                span: Span::new(start, self.previous_end()),
1122            }),
1123            TokenKind::LParen => {
1124                self.advance();
1125                if self.check(TokenKind::RParen) {
1126                    self.advance();
1127                    return Ok(Expr {
1128                        kind: ExprKind::Unit,
1129                        span: Span::new(start, self.previous_end()),
1130                    });
1131                }
1132                if self.check(TokenKind::Pipe)
1133                    || (self.is_ident() && self.peek_kind_at(1) == TokenKind::Pipe)
1134                {
1135                    return self.parse_lambda(start);
1136                }
1137                let expr = self.parse_expr()?;
1138                self.expect(TokenKind::RParen)?;
1139                Ok(expr)
1140            }
1141            TokenKind::Pipe => self.parse_lambda(start),
1142            _ => Err(self.unexpected("expression", self.peek_kind())),
1143        }
1144    }
1145
1146    fn parse_none_some_call(&mut self, some: bool, start: u32) -> Result<Expr, ParseError> {
1147        if self.match_token(TokenKind::LParen) {
1148            let inner = self.parse_expr()?;
1149            self.expect(TokenKind::RParen)?;
1150            let name = if some { "some" } else { "none" };
1151            return Ok(Expr {
1152                kind: ExprKind::Call {
1153                    func: Box::new(Expr {
1154                        kind: ExprKind::Ident(Ident::new(name, Span::new(start, start))),
1155                        span: Span::new(start, start),
1156                    }),
1157                    args: if some { vec![inner] } else { vec![] },
1158                },
1159                span: Span::new(start, self.previous_end()),
1160            });
1161        }
1162        let name = if some { "some" } else { "none" };
1163        Ok(Expr {
1164            kind: ExprKind::Ident(Ident::new(name, Span::new(start, self.previous_end()))),
1165            span: Span::new(start, self.previous_end()),
1166        })
1167    }
1168
1169    fn parse_lambda(&mut self, start: u32) -> Result<Expr, ParseError> {
1170        self.expect(TokenKind::Pipe)?;
1171        let params = self.parse_params()?;
1172        self.expect(TokenKind::Pipe)?;
1173        let body = self.parse_expr()?;
1174        let end = body.span.end;
1175        Ok(Expr {
1176            kind: ExprKind::Lambda {
1177                params,
1178                body: Box::new(body),
1179            },
1180            span: Span::new(start, end),
1181        })
1182    }
1183
1184    fn parse_if_expr(&mut self, start: u32) -> Result<Expr, ParseError> {
1185        let cond = self.with_no_struct_lit(|p| p.parse_expr())?;
1186        let then_branch = if self.match_kw(Kw::Then) {
1187            Box::new(self.parse_expr()?)
1188        } else {
1189            Box::new(Expr {
1190                kind: ExprKind::Block(self.parse_block()?),
1191                span: Span::new(self.current_start(), self.previous_end()),
1192            })
1193        };
1194        let else_branch = if self.match_kw(Kw::Else) {
1195            if self.check(TokenKind::Kw(Kw::If)) {
1196                Some(Box::new(self.parse_if_expr(self.current_start())?))
1197            } else if self.check(TokenKind::LBrace) {
1198                Some(Box::new(Expr {
1199                    kind: ExprKind::Block(self.parse_block()?),
1200                    span: Span::new(self.current_start(), self.previous_end()),
1201                }))
1202            } else {
1203                Some(Box::new(self.parse_expr()?))
1204            }
1205        } else {
1206            None
1207        };
1208        let end = else_branch
1209            .as_ref()
1210            .map(|e| e.span.end)
1211            .unwrap_or(then_branch.span.end);
1212        Ok(Expr {
1213            kind: ExprKind::If {
1214                cond: Box::new(cond),
1215                then_branch,
1216                else_branch,
1217            },
1218            span: Span::new(start, end),
1219        })
1220    }
1221
1222    fn parse_match_expr(&mut self, start: u32) -> Result<Expr, ParseError> {
1223        let scrutinee = self.parse_match_scrutinee()?;
1224        self.expect(TokenKind::LBrace)?;
1225        let mut arms = Vec::new();
1226        while !self.check(TokenKind::RBrace) {
1227            arms.push(self.parse_match_arm()?);
1228        }
1229        self.expect(TokenKind::RBrace)?;
1230        Ok(Expr {
1231            kind: ExprKind::Match {
1232                scrutinee: Box::new(scrutinee),
1233                arms,
1234            },
1235            span: Span::new(start, self.previous_end()),
1236        })
1237    }
1238
1239    /// Scrutinee parsing that does not treat `name {` as a struct literal.
1240    /// `match color { … }` would otherwise consume `color { … }` as `StructLit`.
1241    fn parse_match_scrutinee(&mut self) -> Result<Expr, ParseError> {
1242        if matches!(self.peek_kind(), TokenKind::Ident(_))
1243            && matches!(self.peek_kind_at(1), TokenKind::LBrace)
1244        {
1245            let id = self.expect_ident()?;
1246            return Ok(Expr {
1247                kind: ExprKind::Ident(id.clone()),
1248                span: id.span,
1249            });
1250        }
1251        self.parse_expr()
1252    }
1253
1254    fn parse_match_arm(&mut self) -> Result<MatchArm, ParseError> {
1255        let start = self.current_start();
1256        let pat = self.parse_pat()?;
1257        let guard = if self.match_kw(Kw::If) {
1258            Some(self.parse_expr()?)
1259        } else {
1260            None
1261        };
1262        if !self.match_token(TokenKind::Arrow) {
1263            return Err(ParseError::Unexpected {
1264                expected: "`->`",
1265                found: self.peek_kind(),
1266                pos: self.current_start(),
1267                help: Some(
1268                    "if the match scrutinee is a struct literal, wrap it in parentheses: \
1269match (Name { field: value }) { ... }",
1270                ),
1271            });
1272        }
1273        let body = self.parse_expr()?;
1274        let end = body.span.end;
1275        Ok(MatchArm {
1276            pat,
1277            guard,
1278            body,
1279            span: Span::new(start, end),
1280        })
1281    }
1282
1283    fn parse_for_expr(&mut self, start: u32) -> Result<Expr, ParseError> {
1284        let pat = self.parse_pat()?;
1285        self.expect_kw(Kw::In)?;
1286        let iter = self.with_no_struct_lit(|p| p.parse_expr())?;
1287        let body = Expr {
1288            kind: ExprKind::Block(self.parse_block()?),
1289            span: Span::new(self.current_start(), self.previous_end()),
1290        };
1291        let end = body.span.end;
1292        Ok(Expr {
1293            kind: ExprKind::For {
1294                pat,
1295                iter: Box::new(iter),
1296                body: Box::new(body),
1297            },
1298            span: Span::new(start, end),
1299        })
1300    }
1301
1302    fn parse_while_expr(&mut self, start: u32) -> Result<Expr, ParseError> {
1303        let cond = self.with_no_struct_lit(|p| p.parse_expr())?;
1304        let body = Expr {
1305            kind: ExprKind::Block(self.parse_block()?),
1306            span: Span::new(self.current_start(), self.previous_end()),
1307        };
1308        let end = body.span.end;
1309        Ok(Expr {
1310            kind: ExprKind::While {
1311                cond: Box::new(cond),
1312                body: Box::new(body),
1313            },
1314            span: Span::new(start, end),
1315        })
1316    }
1317
1318    fn parse_loop_expr(&mut self, start: u32) -> Result<Expr, ParseError> {
1319        let body = Expr {
1320            kind: ExprKind::Block(self.parse_block()?),
1321            span: Span::new(self.current_start(), self.previous_end()),
1322        };
1323        let end = body.span.end;
1324        Ok(Expr {
1325            kind: ExprKind::Loop(Box::new(body)),
1326            span: Span::new(start, end),
1327        })
1328    }
1329
1330    fn parse_struct_lit(&mut self, name: Ident) -> Result<Expr, ParseError> {
1331        let start = name.span.start;
1332        self.expect(TokenKind::LBrace)?;
1333        let mut fields = Vec::new();
1334        while !self.check(TokenKind::RBrace) {
1335            let s = self.current_start();
1336            let fname = self.expect_ident()?;
1337            self.expect(TokenKind::Colon)?;
1338            let value = self.parse_expr()?;
1339            fields.push(FieldInit {
1340                name: fname,
1341                value,
1342                span: Span::new(s, self.previous_end()),
1343            });
1344        }
1345        self.expect(TokenKind::RBrace)?;
1346        Ok(Expr {
1347            kind: ExprKind::StructLit { name, fields },
1348            span: Span::new(start, self.previous_end()),
1349        })
1350    }
1351
1352    fn parse_block(&mut self) -> Result<Block, ParseError> {
1353        let start = self.current_start();
1354        self.expect(TokenKind::LBrace)?;
1355        let mut stmts = Vec::new();
1356        let mut tail = None;
1357        while !self.check(TokenKind::RBrace) && !self.check(TokenKind::Eof) {
1358            let saved = self.pos;
1359            if let Ok(stmt) = self.try_parse_binding_stmt() {
1360                stmts.push(stmt);
1361                continue;
1362            }
1363            self.pos = saved;
1364
1365            if self.is_ident() && self.peek_kind_at(1) == TokenKind::Assign {
1366                let target = self.expect_ident()?;
1367                self.advance();
1368                let value = self.parse_expr()?;
1369                stmts.push(Stmt::Assign { target, value });
1370                continue;
1371            }
1372
1373            let expr = self.parse_expr()?;
1374            if self.check(TokenKind::RBrace) {
1375                tail = Some(Box::new(expr));
1376                break;
1377            }
1378            stmts.push(Stmt::Expr(expr));
1379        }
1380        self.expect(TokenKind::RBrace)?;
1381        Ok(Block {
1382            stmts,
1383            tail,
1384            span: Span::new(start, self.previous_end()),
1385        })
1386    }
1387
1388    fn try_parse_binding_stmt(&mut self) -> Result<Stmt, ParseError> {
1389        let pat = self.parse_pat()?;
1390        let mutable = if self.match_token(TokenKind::MutColonEq) {
1391            true
1392        } else if self.match_token(TokenKind::ColonEq) {
1393            false
1394        } else {
1395            return Err(ParseError::Unexpected {
1396                expected: "`:=` or `mut:`=",
1397                found: self.peek_kind(),
1398                pos: self.current_start(),
1399                help: None,
1400            });
1401        };
1402        let value = self.parse_expr()?;
1403        Ok(Stmt::Bind {
1404            pat,
1405            mutable,
1406            value,
1407        })
1408    }
1409
1410    // ── Patterns ──────────────────────────────────────────────────────────
1411
1412    fn parse_pat(&mut self) -> Result<Pat, ParseError> {
1413        let start = self.current_start();
1414        if let TokenKind::Ident(name) = self.peek_kind()
1415            && name == "_"
1416        {
1417            self.advance();
1418            return Ok(Pat {
1419                kind: PatKind::Wildcard,
1420                span: Span::new(start, self.previous_end()),
1421            });
1422        }
1423        if self.is_int() || self.is_string() {
1424            let expr = self.parse_primary()?;
1425            return Ok(Pat {
1426                kind: PatKind::Literal(Box::new(expr)),
1427                span: Span::new(start, self.previous_end()),
1428            });
1429        }
1430        if self.match_token(TokenKind::LParen) {
1431            if self.check(TokenKind::RParen) {
1432                self.advance();
1433                return Ok(Pat {
1434                    kind: PatKind::Literal(Box::new(Expr {
1435                        kind: ExprKind::Unit,
1436                        span: Span::new(start, self.previous_end()),
1437                    })),
1438                    span: Span::new(start, self.previous_end()),
1439                });
1440            }
1441            let mut pats = vec![self.parse_pat()?];
1442            while self.match_token(TokenKind::Comma) {
1443                pats.push(self.parse_pat()?);
1444            }
1445            self.expect(TokenKind::RParen)?;
1446            return Ok(Pat {
1447                kind: PatKind::Tuple(pats),
1448                span: Span::new(start, self.previous_end()),
1449            });
1450        }
1451        if self.match_token(TokenKind::LBrace) {
1452            let name = self.expect_ident()?;
1453            let mut fields = Vec::new();
1454            let mut rest = None;
1455            while !self.check(TokenKind::RBrace) {
1456                if self.match_token(TokenKind::DotDot) {
1457                    rest = Some(self.expect_ident()?);
1458                    break;
1459                }
1460                let fname = self.expect_ident()?;
1461                let pat = if self.match_token(TokenKind::Colon) {
1462                    Some(self.parse_pat()?)
1463                } else {
1464                    None
1465                };
1466                fields.push(FieldPat {
1467                    name: fname,
1468                    pat,
1469                    span: Span::new(start, self.previous_end()),
1470                });
1471            }
1472            self.expect(TokenKind::RBrace)?;
1473            return Ok(Pat {
1474                kind: PatKind::Struct { name, fields, rest },
1475                span: Span::new(start, self.previous_end()),
1476            });
1477        }
1478        let name = self.expect_ident()?;
1479        // Qualified enum pattern: Color.Red / Color.Custom(r, g, b)
1480        if self.match_token(TokenKind::Dot) {
1481            let variant = self.expect_ident()?;
1482            let args = if self.match_token(TokenKind::LParen) {
1483                let mut args = Vec::new();
1484                while !self.check(TokenKind::RParen) {
1485                    args.push(self.parse_pat()?);
1486                    if !self.match_token(TokenKind::Comma) {
1487                        break;
1488                    }
1489                }
1490                self.expect(TokenKind::RParen)?;
1491                args
1492            } else {
1493                vec![]
1494            };
1495            return Ok(Pat {
1496                kind: PatKind::Enum {
1497                    name,
1498                    variant,
1499                    args,
1500                },
1501                span: Span::new(start, self.previous_end()),
1502            });
1503        }
1504        // Unqualified ctor pattern: Custom(r, g, b) — variant name equals type slot
1505        if self.match_token(TokenKind::LParen) {
1506            let mut args = Vec::new();
1507            while !self.check(TokenKind::RParen) {
1508                args.push(self.parse_pat()?);
1509                if !self.match_token(TokenKind::Comma) {
1510                    break;
1511                }
1512            }
1513            self.expect(TokenKind::RParen)?;
1514            return Ok(Pat {
1515                kind: PatKind::Enum {
1516                    name: name.clone(),
1517                    variant: name,
1518                    args,
1519                },
1520                span: Span::new(start, self.previous_end()),
1521            });
1522        }
1523        Ok(Pat {
1524            kind: PatKind::Ident(name),
1525            span: Span::new(start, self.previous_end()),
1526        })
1527    }
1528
1529    // ── Helpers ───────────────────────────────────────────────────────────
1530
1531    fn parse_binary<F>(
1532        &mut self,
1533        mut next: F,
1534        tok: TokenKind,
1535        op: BinaryOp,
1536    ) -> Result<Expr, ParseError>
1537    where
1538        F: FnMut(&mut Self) -> Result<Expr, ParseError>,
1539    {
1540        let mut left = next(self)?;
1541        while self.check(tok.clone()) {
1542            self.advance();
1543            let right = next(self)?;
1544            let span = left.span.merge(right.span);
1545            left = Expr {
1546                kind: ExprKind::Binary {
1547                    op,
1548                    left: Box::new(left),
1549                    right: Box::new(right),
1550                },
1551                span,
1552            };
1553        }
1554        Ok(left)
1555    }
1556
1557    #[allow(clippy::while_let_on_iterator)]
1558    fn parse_string_parts(&mut self, s: &str, start: u32) -> Result<StringParts, ParseError> {
1559        let mut parts = Vec::new();
1560        let mut lit = String::new();
1561        let mut chars = s.chars().peekable();
1562        let iter = chars.by_ref();
1563        while let Some(c) = iter.next() {
1564            if c == '{' {
1565                if !lit.is_empty() {
1566                    parts.push(StringPart::Lit(std::mem::take(&mut lit)));
1567                }
1568                let mut depth = 1i32;
1569                let mut expr_text = String::new();
1570                while let Some(ch) = iter.next() {
1571                    if ch == '{' {
1572                        depth += 1;
1573                    }
1574                    if ch == '}' {
1575                        depth -= 1;
1576                        if depth == 0 {
1577                            break;
1578                        }
1579                    }
1580                    expr_text.push(ch);
1581                }
1582                let mut sub = Parser::new(&expr_text)?;
1583                let expr = sub.parse_expr()?;
1584                parts.push(StringPart::Expr(Box::new(expr)));
1585            } else {
1586                lit.push(c);
1587            }
1588        }
1589        if !lit.is_empty() {
1590            parts.push(StringPart::Lit(lit));
1591        }
1592        if parts.is_empty() {
1593            parts.push(StringPart::Lit(String::new()));
1594        }
1595        let _ = start;
1596        Ok(StringParts(parts))
1597    }
1598
1599    fn parse_args(&mut self) -> Result<Vec<Expr>, ParseError> {
1600        let mut args = Vec::new();
1601        if self.check(TokenKind::RParen) {
1602            return Ok(args);
1603        }
1604        loop {
1605            args.push(self.parse_expr()?);
1606            if !self.match_token(TokenKind::Comma) {
1607                break;
1608            }
1609        }
1610        Ok(args)
1611    }
1612
1613    fn is_ident(&self) -> bool {
1614        matches!(self.peek_kind(), TokenKind::Ident(_))
1615    }
1616
1617    fn is_int(&self) -> bool {
1618        matches!(self.peek_kind(), TokenKind::Int(_))
1619    }
1620
1621    fn is_string(&self) -> bool {
1622        matches!(self.peek_kind(), TokenKind::String(_))
1623    }
1624
1625    fn check_expr_start(&self) -> bool {
1626        !matches!(
1627            self.peek_kind(),
1628            TokenKind::RBrace | TokenKind::Eof | TokenKind::RParen
1629        )
1630    }
1631
1632    fn check_lifetime(&self) -> bool {
1633        matches!(self.peek_kind(), TokenKind::Lifetime(_))
1634    }
1635
1636    fn parse_lifetime_ident(&mut self) -> Result<Ident, ParseError> {
1637        let t = self.advance();
1638        let TokenKind::Lifetime(name) = t.kind else {
1639            return Err(self.unexpected("lifetime", t.kind));
1640        };
1641        Ok(Ident::new(name, Span::new(t.start, t.end)))
1642    }
1643
1644    fn expect_ident(&mut self) -> Result<Ident, ParseError> {
1645        let t = self.advance();
1646        match t.kind {
1647            TokenKind::Ident(name) => Ok(Ident::new(name, Span::new(t.start, t.end))),
1648            other => Err(ParseError::Unexpected {
1649                expected: "identifier",
1650                found: other,
1651                pos: t.start,
1652                help: None,
1653            }),
1654        }
1655    }
1656
1657    fn expect_ident_or_kw_as_ident(&mut self) -> Result<Ident, ParseError> {
1658        self.expect_ident()
1659    }
1660
1661    fn expect_string_lit(&mut self) -> Result<String, ParseError> {
1662        let t = self.advance();
1663        match t.kind {
1664            TokenKind::String(s) => Ok(s),
1665            other => Err(ParseError::Unexpected {
1666                expected: "string literal",
1667                found: other,
1668                pos: t.start,
1669                help: None,
1670            }),
1671        }
1672    }
1673
1674    fn expect_kw(&mut self, kw: Kw) -> Result<(), ParseError> {
1675        if self.match_kw(kw) {
1676            Ok(())
1677        } else {
1678            Err(self.unexpected(
1679                std::str::from_utf8(kw_bytes(kw)).unwrap_or("keyword"),
1680                self.peek_kind(),
1681            ))
1682        }
1683    }
1684
1685    fn expect(&mut self, kind: TokenKind) -> Result<(), ParseError> {
1686        if self.match_token(kind.clone()) {
1687            Ok(())
1688        } else {
1689            Err(self.unexpected("token", self.peek_kind()))
1690        }
1691    }
1692
1693    fn match_kw(&mut self, kw: Kw) -> bool {
1694        if matches!(self.peek_kind(), TokenKind::Kw(k) if k == kw) {
1695            self.advance();
1696            true
1697        } else {
1698            false
1699        }
1700    }
1701
1702    fn match_kw_opt(&mut self) -> Option<Kw> {
1703        if let TokenKind::Kw(kw) = self.peek_kind() {
1704            let k = kw;
1705            self.advance();
1706            Some(k)
1707        } else {
1708            None
1709        }
1710    }
1711
1712    fn match_token(&mut self, kind: TokenKind) -> bool {
1713        if self.check(kind.clone()) {
1714            self.advance();
1715            true
1716        } else {
1717            false
1718        }
1719    }
1720
1721    /// Path separator `::` (two `Colon` tokens), for `use rust::serde_json { … }`.
1722    fn match_colon_colon(&mut self) -> bool {
1723        if self.check(TokenKind::Colon) && self.peek_kind_at(1) == TokenKind::Colon {
1724            self.advance();
1725            self.advance();
1726            true
1727        } else {
1728            false
1729        }
1730    }
1731
1732    fn check(&self, kind: TokenKind) -> bool {
1733        self.peek_kind() == kind
1734    }
1735
1736    fn peek_kind(&self) -> TokenKind {
1737        self.tokens
1738            .get(self.pos)
1739            .map(|t| t.kind.clone())
1740            .unwrap_or(TokenKind::Eof)
1741    }
1742
1743    fn peek_kind_at(&self, offset: usize) -> TokenKind {
1744        self.tokens
1745            .get(self.pos + offset)
1746            .map(|t| t.kind.clone())
1747            .unwrap_or(TokenKind::Eof)
1748    }
1749
1750    fn advance(&mut self) -> Token {
1751        let t = self.tokens[self.pos].clone();
1752        if !matches!(t.kind, TokenKind::Eof) {
1753            self.pos += 1;
1754        }
1755        t
1756    }
1757
1758    fn current_start(&self) -> u32 {
1759        self.tokens.get(self.pos).map(|t| t.start).unwrap_or(0)
1760    }
1761
1762    fn previous_start(&self) -> u32 {
1763        if self.pos == 0 {
1764            0
1765        } else {
1766            self.tokens[self.pos - 1].start
1767        }
1768    }
1769
1770    fn previous_end(&self) -> u32 {
1771        if self.pos == 0 {
1772            0
1773        } else {
1774            self.tokens[self.pos - 1].end
1775        }
1776    }
1777
1778    fn previous_span(&self) -> Span {
1779        Span::new(self.previous_start(), self.previous_end())
1780    }
1781
1782    fn unexpected(&self, expected: &'static str, found: TokenKind) -> ParseError {
1783        ParseError::Unexpected {
1784            expected,
1785            found,
1786            pos: self.current_start(),
1787            help: None,
1788        }
1789    }
1790}
1791
1792fn kw_bytes(_kw: Kw) -> &'static [u8] {
1793    b"keyword"
1794}
1795
1796trait ItemSpan {
1797    fn span(&self) -> Span;
1798}
1799
1800impl ItemSpan for Item {
1801    fn span(&self) -> Span {
1802        match self {
1803            Item::Function(f) => f.span,
1804            Item::TypeDef(t) => t.span,
1805            Item::TraitDef(t) => t.span,
1806            Item::ShapeDef(s) => s.span,
1807            Item::Impl(i) => i.span,
1808            Item::Use(u) => u.span,
1809            Item::Const(c) => c.span,
1810            Item::Extern(e) => e.span,
1811            Item::Test(t) => t.span,
1812            Item::TestCompileFail(t) => t.span,
1813        }
1814    }
1815}