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