Skip to main content

ling/parser/
mod.rs

1// src/parser/mod.rs
2pub mod ast;
3pub mod grammar;
4
5use crate::lexer::Token;
6use ast::*;
7
8pub fn parse(source: &str) -> Result<Program, String> {
9    let mut lex = crate::lexer::Lexer::new(source);
10    let mut tokens = Vec::new();
11    while let Some(tok) = lex.next_token() {
12        tokens.push(tok);
13    }
14    tokens.push(Token::Eof);
15    parse_tokens(tokens)
16}
17
18pub fn parse_tokens(tokens: Vec<Token>) -> Result<Program, String> {
19    Parser::new(tokens).parse_program()
20}
21
22// ─── Parser ──────────────────────────────────────────────────────────────────
23
24struct Parser {
25    tokens: Vec<Token>,
26    pos: usize,
27}
28
29impl Parser {
30    fn new(tokens: Vec<Token>) -> Self {
31        Self { tokens, pos: 0 }
32    }
33
34    fn peek(&self) -> &Token {
35        self.tokens.get(self.pos).unwrap_or(&Token::Eof)
36    }
37
38    #[allow(dead_code)]
39    fn peek2(&self) -> &Token {
40        self.tokens.get(self.pos + 1).unwrap_or(&Token::Eof)
41    }
42
43    fn advance(&mut self) -> Token {
44        let tok = self.tokens.get(self.pos).cloned().unwrap_or(Token::Eof);
45        if self.pos < self.tokens.len() {
46            self.pos += 1;
47        }
48        tok
49    }
50
51    fn expect(&mut self, expected: &Token) -> Result<(), String> {
52        let tok = self.advance();
53        if &tok == expected {
54            Ok(())
55        } else {
56            Err(format!("expected {:?}, got {:?}", expected, tok))
57        }
58    }
59
60    /// Parse a name that can be a keyword used as an identifier.
61    fn parse_name(&mut self) -> Result<String, String> {
62        match self.advance() {
63            Token::Ident(s) => Ok(s),
64            // Allow all keywords to serve as bind names (contextual)
65            tok => Ok(token_to_name(&tok)
66                .ok_or_else(|| format!("expected identifier, got {:?}", tok))?
67                .to_string()),
68        }
69    }
70
71    // ─── Top-level ───────────────────────────────────────────────────────────
72
73    fn parse_program(&mut self) -> Result<Program, String> {
74        let mut items = Vec::new();
75        while !matches!(self.peek(), Token::Eof) {
76            items.push(self.parse_item()?);
77        }
78        Ok(Program { items })
79    }
80
81    fn parse_item(&mut self) -> Result<Item, String> {
82        let is_async = if matches!(self.peek(), Token::Async) {
83            self.advance();
84            true
85        } else {
86            false
87        };
88
89        match self.peek().clone() {
90            Token::Bind => {
91                self.advance();
92                let name = self.parse_name()?;
93                self.expect(&Token::Eq)?;
94                let expr = self.parse_expr()?;
95                Ok(Item::Bind(name, expr))
96            },
97            Token::Fn => self.parse_fn_item(is_async),
98            Token::Mod => {
99                self.advance();
100                let name = self.parse_name()?;
101                self.expect(&Token::LBrace)?;
102                let mut body = Vec::new();
103                while !matches!(self.peek(), Token::RBrace | Token::Eof) {
104                    body.push(self.parse_item()?);
105                }
106                self.expect(&Token::RBrace)?;
107                Ok(Item::Mod(name, body))
108            },
109            Token::Type => {
110                self.advance();
111                let name = self.parse_name()?;
112                // Skip optional generic params
113                self.skip_generics();
114                self.expect(&Token::As)?;
115                let ty = self.parse_type_str();
116                Ok(Item::TypeAlias(name, ty))
117            },
118            Token::Form => self.parse_struct_item(),
119            Token::Choose => self.parse_enum_item(),
120            Token::Use => {
121                self.advance();
122                // Expect a string path: use "path/to/module"
123                let path = match self.advance() {
124                    Token::String(s) => s,
125                    tok => return Err(format!("use: expected string path, got {:?}", tok)),
126                };
127                // Optional `as name` alias
128                let alias = if matches!(self.peek(), Token::As) {
129                    self.advance();
130                    Some(self.parse_name()?)
131                } else {
132                    None
133                };
134                Ok(Item::Use { path, alias })
135            },
136            tok => Err(format!("unexpected token at top level: {:?}", tok)),
137        }
138    }
139
140    /// `form Name { field (: Type)?, ... }` — record/struct definition.
141    /// Types after `:` are parsed and discarded; only field names (in order) survive.
142    fn parse_struct_item(&mut self) -> Result<Item, String> {
143        self.advance(); // consume `form`
144        let name = self.parse_name()?;
145        self.skip_generics();
146        self.expect(&Token::LBrace)?;
147        let mut fields = Vec::new();
148        while !matches!(self.peek(), Token::RBrace | Token::Eof) {
149            fields.push(self.parse_name()?);
150            if matches!(self.peek(), Token::Colon) {
151                self.advance();
152                self.parse_type_str(); // ignored
153            }
154            if matches!(self.peek(), Token::Comma | Token::Semicolon) {
155                self.advance();
156            }
157        }
158        self.expect(&Token::RBrace)?;
159        Ok(Item::Struct(name, fields))
160    }
161
162    /// `choose Name { Variant, Variant(a, b), ... }` — sum type / enum.
163    /// Each variant records its name and payload arity; payload field names/types
164    /// are parsed and discarded.
165    fn parse_enum_item(&mut self) -> Result<Item, String> {
166        self.advance(); // consume `choose`
167        let name = self.parse_name()?;
168        self.skip_generics();
169        self.expect(&Token::LBrace)?;
170        let mut variants = Vec::new();
171        while !matches!(self.peek(), Token::RBrace | Token::Eof) {
172            let vname = self.parse_name()?;
173            let mut arity = 0usize;
174            if matches!(self.peek(), Token::LParen) {
175                self.advance();
176                while !matches!(self.peek(), Token::RParen | Token::Eof) {
177                    // A payload slot may be `name: Type`, just `Type`, or just a name.
178                    self.parse_name().ok();
179                    if matches!(self.peek(), Token::Colon) {
180                        self.advance();
181                        self.parse_type_str();
182                    }
183                    arity += 1;
184                    if matches!(self.peek(), Token::Comma) {
185                        self.advance();
186                    }
187                }
188                self.expect(&Token::RParen)?;
189            }
190            variants.push(EnumVariant { name: vname, arity });
191            if matches!(self.peek(), Token::Comma | Token::Semicolon) {
192                self.advance();
193            }
194        }
195        self.expect(&Token::RBrace)?;
196        Ok(Item::Enum(name, variants))
197    }
198
199    fn parse_fn_item(&mut self, is_async: bool) -> Result<Item, String> {
200        self.advance(); // consume `fn`
201        let name = self.parse_name()?;
202        self.skip_generics(); // ignore `<T, U>`
203        self.expect(&Token::LParen)?;
204        let params = self.parse_params()?;
205        self.expect(&Token::RParen)?;
206        // Optional return type: `-> Type`
207        if matches!(self.peek(), Token::Arrow) {
208            self.advance();
209            self.parse_type_str();
210        }
211        // Optional `where` clause
212        if matches!(self.peek(), Token::Where) {
213            self.advance();
214            while !matches!(self.peek(), Token::LBrace | Token::Eof) {
215                self.advance();
216            }
217        }
218        self.expect(&Token::LBrace)?;
219        let body = self.parse_block()?;
220        self.expect(&Token::RBrace)?;
221        Ok(Item::Fn(FnDef { name, is_async, params, body }))
222    }
223
224    fn parse_params(&mut self) -> Result<Vec<String>, String> {
225        let mut params = Vec::new();
226        while !matches!(self.peek(), Token::RParen | Token::Eof) {
227            // Skip leading & or own/lend
228            while matches!(self.peek(), Token::Ampersand | Token::Own | Token::Lend) {
229                self.advance();
230            }
231            let name = self.parse_name()?;
232            params.push(name);
233            // Skip `: Type`
234            if matches!(self.peek(), Token::Colon) {
235                self.advance();
236                self.parse_type_str();
237            }
238            if matches!(self.peek(), Token::Comma) {
239                self.advance();
240            }
241        }
242        Ok(params)
243    }
244
245    /// Eat a type expression (until `,`, `)`, `{`, `where`, `>`) — ignored at runtime.
246    fn parse_type_str(&mut self) -> String {
247        let mut depth = 0usize;
248        let mut result = String::new();
249        loop {
250            match self.peek() {
251                Token::Eof => break,
252                Token::Lt => {
253                    depth += 1;
254                    result.push('<');
255                    self.advance();
256                },
257                Token::Gt if depth > 0 => {
258                    depth -= 1;
259                    result.push('>');
260                    self.advance();
261                },
262                Token::LBrace | Token::Where if depth == 0 => break,
263                Token::RParen | Token::Comma | Token::Semicolon if depth == 0 => break,
264                Token::Arrow if depth == 0 => break,
265                tok => {
266                    result.push_str(&format!("{:?}", tok));
267                    self.advance();
268                },
269            }
270        }
271        result
272    }
273
274    fn skip_generics(&mut self) {
275        if matches!(self.peek(), Token::Lt) {
276            let mut depth = 0;
277            loop {
278                match self.advance() {
279                    Token::Lt => depth += 1,
280                    Token::Gt => {
281                        depth -= 1;
282                        if depth == 0 {
283                            break;
284                        }
285                    },
286                    Token::Eof => break,
287                    _ => {},
288                }
289            }
290        }
291    }
292
293    // ─── Blocks ──────────────────────────────────────────────────────────────
294
295    fn parse_block(&mut self) -> Result<Vec<Stmt>, String> {
296        let mut stmts = Vec::new();
297        while !matches!(self.peek(), Token::RBrace | Token::Eof) {
298            stmts.push(self.parse_stmt()?);
299            // Optional trailing semicolon
300            if matches!(self.peek(), Token::Semicolon) {
301                self.advance();
302            }
303        }
304        Ok(stmts)
305    }
306
307    fn parse_stmt(&mut self) -> Result<Stmt, String> {
308        match self.peek().clone() {
309            Token::Bind => {
310                self.advance();
311                let name = self.parse_name()?;
312                self.expect(&Token::Eq)?;
313                let expr = self.parse_expr()?;
314                Ok(Stmt::Bind(name, expr))
315            },
316            Token::Return => {
317                self.advance();
318                if matches!(self.peek(), Token::Semicolon | Token::RBrace) {
319                    Ok(Stmt::Return(Expr::Unit))
320                } else {
321                    Ok(Stmt::Return(self.parse_expr()?))
322                }
323            },
324            _ => Ok(Stmt::Expr(self.parse_expr()?)),
325        }
326    }
327
328    // ─── Expressions ─────────────────────────────────────────────────────────
329
330    fn parse_expr(&mut self) -> Result<Expr, String> {
331        self.parse_or_expr()
332    }
333
334    fn parse_or_expr(&mut self) -> Result<Expr, String> {
335        let mut left = self.parse_and_expr()?;
336        while matches!(self.peek(), Token::Or) {
337            self.advance();
338            let right = self.parse_and_expr()?;
339            left = Expr::BinOp(BinOp::Or, Box::new(left), Box::new(right));
340        }
341        Ok(left)
342    }
343
344    fn parse_and_expr(&mut self) -> Result<Expr, String> {
345        let mut left = self.parse_cmp_expr()?;
346        while matches!(self.peek(), Token::And) {
347            self.advance();
348            let right = self.parse_cmp_expr()?;
349            left = Expr::BinOp(BinOp::And, Box::new(left), Box::new(right));
350        }
351        Ok(left)
352    }
353
354    fn parse_cmp_expr(&mut self) -> Result<Expr, String> {
355        let mut left = self.parse_add_expr()?;
356        loop {
357            let op = match self.peek() {
358                Token::EqEq => BinOp::Eq,
359                Token::Ne => BinOp::Ne,
360                Token::Lt => BinOp::Lt,
361                Token::Gt => BinOp::Gt,
362                Token::Le => BinOp::Le,
363                Token::Ge => BinOp::Ge,
364                _ => break,
365            };
366            self.advance();
367            let right = self.parse_add_expr()?;
368            left = Expr::BinOp(op, Box::new(left), Box::new(right));
369        }
370        Ok(left)
371    }
372
373    fn parse_add_expr(&mut self) -> Result<Expr, String> {
374        let mut left = self.parse_mul_expr()?;
375        loop {
376            let op = match self.peek() {
377                Token::Plus => BinOp::Add,
378                Token::Minus => BinOp::Sub,
379                _ => break,
380            };
381            self.advance();
382            let right = self.parse_mul_expr()?;
383            left = Expr::BinOp(op, Box::new(left), Box::new(right));
384        }
385        Ok(left)
386    }
387
388    fn parse_mul_expr(&mut self) -> Result<Expr, String> {
389        let mut left = self.parse_unary_expr()?;
390        loop {
391            let op = match self.peek() {
392                Token::Star => BinOp::Mul,
393                Token::Slash => BinOp::Div,
394                Token::Percent => BinOp::Rem,
395                _ => break,
396            };
397            self.advance();
398            let right = self.parse_unary_expr()?;
399            left = Expr::BinOp(op, Box::new(left), Box::new(right));
400        }
401        Ok(left)
402    }
403
404    fn parse_unary_expr(&mut self) -> Result<Expr, String> {
405        match self.peek().clone() {
406            Token::Ampersand => {
407                self.advance();
408                Ok(Expr::Ref(Box::new(self.parse_postfix_expr()?)))
409            },
410            Token::Not => {
411                self.advance();
412                Ok(Expr::BinOp(
413                    BinOp::Eq,
414                    Box::new(self.parse_postfix_expr()?),
415                    Box::new(Expr::Bool(false)),
416                ))
417            },
418            Token::Minus => {
419                self.advance();
420                Ok(Expr::BinOp(
421                    BinOp::Sub,
422                    Box::new(Expr::Number(0.0)),
423                    Box::new(self.parse_postfix_expr()?),
424                ))
425            },
426            Token::Wait => {
427                self.advance();
428                Ok(Expr::Await(Box::new(self.parse_postfix_expr()?)))
429            },
430            // Ownership modifiers are hints; just evaluate the inner expression
431            Token::Own | Token::Lend | Token::Share | Token::Move | Token::Copy => {
432                self.advance();
433                self.parse_unary_expr()
434            },
435            _ => self.parse_postfix_expr(),
436        }
437    }
438
439    /// Parse suffix operations: calls, method calls, indexing, `..`, path (::)
440    fn parse_postfix_expr(&mut self) -> Result<Expr, String> {
441        let mut base = self.parse_primary()?;
442
443        loop {
444            match self.peek().clone() {
445                // `.method(args)` or `.field`
446                Token::Dot => {
447                    self.advance();
448                    let method = self.parse_name()?;
449                    if matches!(self.peek(), Token::LParen) {
450                        self.advance();
451                        let args = self.parse_call_args()?;
452                        self.expect(&Token::RParen)?;
453                        base = Expr::MethodCall { receiver: Box::new(base), method, args };
454                    } else {
455                        // field access — treat as method call with no args
456                        base =
457                            Expr::MethodCall { receiver: Box::new(base), method, args: Vec::new() };
458                    }
459                },
460                // `::ident` — extend path
461                Token::ColonColon => {
462                    self.advance();
463                    let segment = self.parse_name()?;
464                    // Collect any further `::` segments
465                    base = match base {
466                        Expr::Path(mut segs) => {
467                            segs.push(segment);
468                            Expr::Path(segs)
469                        },
470                        Expr::Ident(s) => Expr::Path(vec![s, segment]),
471                        other => Expr::Path(vec![format!("{:?}", other), segment]),
472                    };
473                },
474                // `(args)` — call
475                Token::LParen => {
476                    self.advance();
477                    let args = self.parse_call_args()?;
478                    self.expect(&Token::RParen)?;
479                    base = Expr::Call(Box::new(base), args);
480                },
481                // `[idx]`
482                Token::LBracket => {
483                    self.advance();
484                    let idx = self.parse_expr()?;
485                    self.expect(&Token::RBracket)?;
486                    base = Expr::Index(Box::new(base), Box::new(idx));
487                },
488                // `..hi` — range
489                Token::DotDot => {
490                    self.advance();
491                    let hi = self.parse_primary()?;
492                    base = Expr::Range(Box::new(base), Box::new(hi));
493                },
494                _ => break,
495            }
496        }
497        Ok(base)
498    }
499
500    fn parse_call_args(&mut self) -> Result<Vec<Expr>, String> {
501        let mut args = Vec::new();
502        while !matches!(self.peek(), Token::RParen | Token::Eof) {
503            args.push(self.parse_expr()?);
504            if matches!(self.peek(), Token::Comma) {
505                self.advance();
506            }
507        }
508        Ok(args)
509    }
510
511    fn parse_primary(&mut self) -> Result<Expr, String> {
512        match self.peek().clone() {
513            // Literals
514            Token::String(s) => {
515                self.advance();
516                Ok(Expr::Str(s))
517            },
518            Token::Number(n) => {
519                self.advance();
520                Ok(Expr::Number(n.parse().unwrap_or(0.0)))
521            },
522            Token::Bool(b) => {
523                self.advance();
524                Ok(Expr::Bool(b))
525            },
526
527            // Keywords that start expressions
528            Token::Do => {
529                self.advance();
530                self.expect(&Token::LBrace)?;
531                let stmts = self.parse_block()?;
532                self.expect(&Token::RBrace)?;
533                Ok(Expr::Do(stmts))
534            },
535            Token::LBrace => {
536                self.advance();
537                let stmts = self.parse_block()?;
538                self.expect(&Token::RBrace)?;
539                Ok(Expr::Do(stmts))
540            },
541            Token::If => self.parse_if_expr(),
542            Token::For => self.parse_for_expr(),
543            Token::While => self.parse_while_expr(),
544            Token::Match => self.parse_match_expr(),
545            Token::Return => {
546                self.advance();
547                let val = if matches!(self.peek(), Token::Semicolon | Token::RBrace | Token::Eof) {
548                    Expr::Unit
549                } else {
550                    self.parse_expr()?
551                };
552                Ok(Expr::Do(vec![Stmt::Return(val)]))
553            },
554
555            // Array literal
556            Token::LBracket => {
557                self.advance();
558                let mut elems = Vec::new();
559                while !matches!(self.peek(), Token::RBracket | Token::Eof) {
560                    elems.push(self.parse_expr()?);
561                    if matches!(self.peek(), Token::Comma) {
562                        self.advance();
563                    }
564                }
565                self.expect(&Token::RBracket)?;
566                Ok(Expr::Array(elems))
567            },
568
569            // Closure `|| expr` or `|params| expr`
570            Token::Or => {
571                self.advance(); // first |
572                let mut params = Vec::new();
573                // If next is not |, parse params
574                if !matches!(self.peek(), Token::Or) {
575                    while !matches!(self.peek(), Token::Or | Token::Eof) {
576                        params.push(self.parse_name()?);
577                        if matches!(self.peek(), Token::Comma) {
578                            self.advance();
579                        }
580                    }
581                }
582                self.advance(); // closing |
583                let body = self.parse_expr()?;
584                Ok(Expr::Closure(params, Box::new(body)))
585            },
586
587            // Grouped expression
588            Token::LParen => {
589                self.advance();
590                if matches!(self.peek(), Token::RParen) {
591                    self.advance();
592                    return Ok(Expr::Unit);
593                }
594                let e = self.parse_expr()?;
595                self.expect(&Token::RParen)?;
596                Ok(e)
597            },
598
599            // Async block
600            Token::Async => {
601                self.advance();
602                let inner = self.parse_expr()?;
603                Ok(inner) // async is a hint; we just execute synchronously
604            },
605
606            // Identifier — could start a path
607            Token::Ident(name) => {
608                self.advance();
609                Ok(Expr::Ident(name))
610            },
611
612            // Allow keywords as expression-position identifiers (e.g. 移动/move)
613            tok => {
614                if let Some(name) = token_to_name(&tok) {
615                    self.advance();
616                    Ok(Expr::Ident(name.to_string()))
617                } else {
618                    Err(format!("unexpected token in expression: {:?}", tok))
619                }
620            },
621        }
622    }
623
624    // ─── if / for / match ────────────────────────────────────────────────────
625
626    fn parse_if_expr(&mut self) -> Result<Expr, String> {
627        self.advance(); // consume `if`
628        let cond = self.parse_cmp_expr()?;
629        self.expect(&Token::LBrace)?;
630        let then = self.parse_block()?;
631        self.expect(&Token::RBrace)?;
632
633        let mut elseifs = Vec::new();
634        let mut else_body = None;
635
636        while matches!(self.peek(), Token::Else) {
637            self.advance(); // consume `else`
638            if matches!(self.peek(), Token::If) {
639                self.advance(); // consume `if`
640                let ei_cond = self.parse_cmp_expr()?;
641                self.expect(&Token::LBrace)?;
642                let ei_body = self.parse_block()?;
643                self.expect(&Token::RBrace)?;
644                elseifs.push((ei_cond, ei_body));
645            } else {
646                self.expect(&Token::LBrace)?;
647                else_body = Some(self.parse_block()?);
648                self.expect(&Token::RBrace)?;
649                break;
650            }
651        }
652
653        Ok(Expr::If { cond: Box::new(cond), then, elseifs, else_body })
654    }
655
656    fn parse_while_expr(&mut self) -> Result<Expr, String> {
657        self.advance(); // consume `while` / `ขณะที่`
658        let cond = self.parse_expr()?;
659        self.expect(&Token::LBrace)?;
660        let body = self.parse_block()?;
661        self.expect(&Token::RBrace)?;
662        Ok(Expr::While { cond: Box::new(cond), body })
663    }
664
665    fn parse_for_expr(&mut self) -> Result<Expr, String> {
666        self.advance(); // consume `for` / `历`
667        let var = self.parse_name()?;
668        self.expect(&Token::In)?;
669        let iter = self.parse_postfix_expr()?;
670        // Handle `0..n` already parsed as Range in postfix
671        self.expect(&Token::LBrace)?;
672        let body = self.parse_block()?;
673        self.expect(&Token::RBrace)?;
674        Ok(Expr::For { var, iter: Box::new(iter), body })
675    }
676
677    fn parse_match_expr(&mut self) -> Result<Expr, String> {
678        self.advance(); // consume `match` / `配`
679        let subject = self.parse_postfix_expr()?;
680        self.expect(&Token::LBrace)?;
681        let mut arms = Vec::new();
682        while !matches!(self.peek(), Token::RBrace | Token::Eof) {
683            let pattern = self.parse_pattern()?;
684            self.expect(&Token::FatArrow)?;
685            let body = self.parse_expr()?;
686            // Optional trailing comma
687            if matches!(self.peek(), Token::Comma) {
688                self.advance();
689            }
690            arms.push(MatchArm { pattern, body });
691        }
692        self.expect(&Token::RBrace)?;
693        Ok(Expr::Match(Box::new(subject), arms))
694    }
695
696    fn parse_pattern(&mut self) -> Result<Pattern, String> {
697        match self.peek().clone() {
698            Token::Ident(s) if s == "_" => {
699                self.advance();
700                Ok(Pattern::Wildcard)
701            },
702            Token::String(s) => {
703                self.advance();
704                Ok(Pattern::Str(s))
705            },
706            Token::Number(n) => {
707                self.advance();
708                Ok(Pattern::Number(n.parse().unwrap_or(0.0)))
709            },
710            Token::Bool(b) => {
711                self.advance();
712                Ok(Pattern::Bool(b))
713            },
714            // Ok(inner), Bad(inner), 好(inner), 坏(inner)
715            Token::Ok | Token::Bad => {
716                let ctor_tok = self.advance();
717                let ctor = match ctor_tok {
718                    Token::Ok => "ok".to_string(),
719                    Token::Bad => "bad".to_string(),
720                    _ => unreachable!(),
721                };
722                if matches!(self.peek(), Token::LParen) {
723                    self.advance();
724                    let inner = self.parse_pattern()?;
725                    self.expect(&Token::RParen)?;
726                    Ok(Pattern::Constructor(ctor, Some(Box::new(inner))))
727                } else {
728                    Ok(Pattern::Constructor(ctor, None))
729                }
730            },
731            _ => {
732                let name = self.parse_name()?;
733                if matches!(self.peek(), Token::LParen) {
734                    // User enum variant pattern: `Variant(p1, p2, ...)` or nullary `Variant()`.
735                    self.advance();
736                    let mut subs = Vec::new();
737                    while !matches!(self.peek(), Token::RParen | Token::Eof) {
738                        subs.push(self.parse_pattern()?);
739                        if matches!(self.peek(), Token::Comma) {
740                            self.advance();
741                        }
742                    }
743                    self.expect(&Token::RParen)?;
744                    Ok(Pattern::Variant(name, subs))
745                } else if name == "_" {
746                    Ok(Pattern::Wildcard)
747                } else {
748                    Ok(Pattern::Ident(name))
749                }
750            },
751        }
752    }
753}
754
755// ─── Helper ──────────────────────────────────────────────────────────────────
756
757/// Convert a keyword token to its string name for use as an identifier.
758fn token_to_name(tok: &Token) -> Option<&'static str> {
759    match tok {
760        Token::Bind => Some("bind"),
761        Token::Do => Some("do"),
762        Token::Fn => Some("fn"),
763        Token::Mod => Some("mod"),
764        Token::Type => Some("type"),
765        Token::If => Some("if"),
766        Token::Else => Some("else"),
767        Token::While => Some("while"),
768        Token::For => Some("for"),
769        Token::In => Some("in"),
770        Token::Match => Some("match"),
771        Token::Return => Some("return"),
772        Token::Own => Some("own"),
773        Token::Lend => Some("lend"),
774        Token::Share => Some("share"),
775        Token::Move => Some("move"),
776        Token::Copy => Some("copy"),
777        Token::Async => Some("async"),
778        Token::Wait => Some("wait"),
779        Token::As => Some("as"),
780        Token::Where => Some("where"),
781        Token::Post => Some("post"),
782        Token::Give => Some("give"),
783        Token::Fit => Some("fit"),
784        Token::Form => Some("form"),
785        Token::Choose => Some("choose"),
786        Token::Can => Some("can"),
787        Token::Change => Some("change"),
788        Token::Stop => Some("stop"),
789        Token::Again => Some("again"),
790        Token::Try => Some("try"),
791        Token::Sure => Some("sure"),
792        Token::Maybe => Some("maybe"),
793        Token::Pure => Some("pure"),
794        Token::Spawn => Some("spawn"),
795        Token::Ok => Some("ok"),
796        Token::Bad => Some("bad"),
797        Token::None => Some("none"),
798        Token::Use => Some("use"),
799        _ => None,
800    }
801}