1use crate::syntax::*;
5use crate::token::{Token, TokenKind};
6
7pub fn parse(tokens: Vec<Token>) -> Result<Program, ParseError> {
8 let mut p = Parser::new(tokens);
9 let program = p.parse_program()?;
10 p.skip_newlines();
11 if !p.at_eof() {
12 return Err(p.error("unexpected token after program"));
13 }
14 Ok(program)
15}
16
17#[derive(Debug, thiserror::Error)]
18#[error("parse error at byte {pos}: {msg}")]
19pub struct ParseError {
20 pub pos: usize,
21 pub msg: String,
22}
23
24struct Parser {
25 tokens: Vec<Token>,
26 idx: usize,
27 depth: u32,
32 discard_counter: u32,
38}
39
40const MAX_DEPTH: u32 = 96;
49
50impl Parser {
51 fn new(tokens: Vec<Token>) -> Self {
52 Self { tokens, idx: 0, depth: 0, discard_counter: 0 }
53 }
54
55 fn at_eof(&self) -> bool {
56 self.idx >= self.tokens.len()
57 }
58
59 fn peek(&self) -> Option<&TokenKind> {
60 self.tokens.get(self.idx).map(|t| &t.kind)
61 }
62
63 fn bump(&mut self) -> Option<Token> {
64 let t = self.tokens.get(self.idx).cloned();
65 if t.is_some() {
66 self.idx += 1;
67 }
68 t
69 }
70
71 fn current_pos(&self) -> usize {
72 self.tokens
73 .get(self.idx)
74 .map(|t| t.span.start)
75 .unwrap_or_else(|| self.tokens.last().map(|t| t.span.end).unwrap_or(0))
76 }
77
78 fn error(&self, msg: impl Into<String>) -> ParseError {
79 ParseError { pos: self.current_pos(), msg: msg.into() }
80 }
81
82 fn skip_newlines(&mut self) {
83 while matches!(self.peek(), Some(TokenKind::Newline) | Some(TokenKind::Semi)) {
84 self.idx += 1;
85 }
86 }
87
88 fn expect(&mut self, expected: &TokenKind, ctx: &str) -> Result<Token, ParseError> {
89 self.skip_newlines();
90 match self.peek() {
91 Some(k) if std::mem::discriminant(k) == std::mem::discriminant(expected) => {
92 Ok(self.bump().unwrap())
93 }
94 Some(other) => Err(self.error(format!(
95 "expected {expected:?} {ctx}, got {other:?}"
96 ))),
97 None => Err(self.error(format!("expected {expected:?} {ctx}, got EOF"))),
98 }
99 }
100
101 fn eat(&mut self, k: &TokenKind) -> bool {
102 self.skip_newlines();
103 if let Some(cur) = self.peek() {
104 if std::mem::discriminant(cur) == std::mem::discriminant(k) {
105 self.bump();
106 return true;
107 }
108 }
109 false
110 }
111
112 fn expect_ident(&mut self, ctx: &str) -> Result<String, ParseError> {
113 self.skip_newlines();
114 match self.peek() {
115 Some(TokenKind::Ident(_)) => match self.bump().unwrap().kind {
116 TokenKind::Ident(name) => Ok(name),
117 _ => unreachable!(),
118 },
119 other => Err(self.error(format!("expected identifier {ctx}, got {other:?}"))),
120 }
121 }
122
123 fn parse_program(&mut self) -> Result<Program, ParseError> {
126 let mut items = Vec::new();
127 loop {
128 self.skip_newlines();
129 if self.at_eof() {
130 break;
131 }
132 items.push(self.parse_item()?);
133 }
134 Ok(Program { items })
135 }
136
137 fn parse_item(&mut self) -> Result<Item, ParseError> {
138 match self.peek() {
139 Some(TokenKind::Import) => self.parse_import().map(Item::Import),
140 Some(TokenKind::Type) => self.parse_type_decl().map(Item::TypeDecl),
141 Some(TokenKind::Fn) => self.parse_fn_decl().map(Item::FnDecl),
142 other => Err(self.error(format!(
143 "expected `import`, `type`, or `fn` at top level, got {other:?}"
144 ))),
145 }
146 }
147
148 fn parse_import(&mut self) -> Result<Import, ParseError> {
149 self.expect(&TokenKind::Import, "in import")?;
150 let reference = match self.bump().map(|t| t.kind) {
151 Some(TokenKind::Str(s)) => s,
152 other => return Err(self.error(format!("expected string after `import`, got {other:?}"))),
153 };
154 self.expect(&TokenKind::As, "in import")?;
155 let alias = self.expect_ident("for import alias")?;
156 Ok(Import { reference, alias })
157 }
158
159 fn parse_type_decl(&mut self) -> Result<TypeDecl, ParseError> {
160 self.expect(&TokenKind::Type, "in type decl")?;
161 let name = self.expect_ident("for type name")?;
162 let params = if self.eat(&TokenKind::LBracket) {
163 let ps = self.parse_ident_list()?;
164 self.expect(&TokenKind::RBracket, "after type params")?;
165 ps
166 } else {
167 Vec::new()
168 };
169 self.expect(&TokenKind::Eq, "in type decl")?;
170 let definition = self.parse_type_decl_rhs()?;
171 Ok(TypeDecl { name, params, definition })
172 }
173
174 fn parse_ident_list(&mut self) -> Result<Vec<String>, ParseError> {
175 let mut out = Vec::new();
176 out.push(self.expect_ident("in identifier list")?);
177 while self.eat(&TokenKind::Comma) {
178 if matches!(self.peek_skip_newlines(), Some(TokenKind::RBracket)) { break; }
179 out.push(self.expect_ident("in identifier list")?);
180 }
181 Ok(out)
182 }
183
184 fn parse_type_decl_rhs(&mut self) -> Result<TypeExpr, ParseError> {
186 let first = self.parse_type_expr()?;
187 if matches!(self.peek_skip_newlines(), Some(TokenKind::Bar)) {
189 let mut variants = Vec::new();
190 variants.push(type_to_variant(first)?);
191 while self.eat(&TokenKind::Bar) {
192 let next = self.parse_type_expr()?;
193 variants.push(type_to_variant(next)?);
194 }
195 Ok(TypeExpr::Union(variants))
196 } else {
197 Ok(first)
198 }
199 }
200
201 fn peek_skip_newlines(&mut self) -> Option<TokenKind> {
202 let saved = self.idx;
203 self.skip_newlines();
204 let out = self.peek().cloned();
205 self.idx = saved;
206 out
207 }
208
209 fn parse_type_expr(&mut self) -> Result<TypeExpr, ParseError> {
210 self.skip_newlines();
211 match self.peek() {
212 Some(TokenKind::LBrace) => self.parse_record_type(),
213 Some(TokenKind::LParen) => self.parse_paren_type_or_function(),
214 Some(TokenKind::Ident(_)) => {
215 let mut name = self.expect_ident("in type expr")?;
216 while matches!(self.peek(), Some(TokenKind::Dot)) {
221 self.bump();
222 let next = self.expect_ident("after `.` in qualified type")?;
223 name.push('.');
224 name.push_str(&next);
225 }
226 let args = if matches!(self.peek(), Some(TokenKind::LBracket)) {
227 self.bump();
228 let mut args = Vec::new();
229 args.push(self.parse_type_expr()?);
230 while self.eat(&TokenKind::Comma) {
231 if matches!(self.peek_skip_newlines(), Some(TokenKind::RBracket)) { break; }
232 args.push(self.parse_type_expr()?);
233 }
234 self.expect(&TokenKind::RBracket, "after type args")?;
235 args
236 } else if matches!(self.peek(), Some(TokenKind::LParen)) {
237 self.bump();
239 let mut args = Vec::new();
240 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) {
241 args.push(self.parse_type_expr()?);
242 while self.eat(&TokenKind::Comma) {
243 if matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) { break; }
244 args.push(self.parse_type_expr()?);
245 }
246 }
247 self.expect(&TokenKind::RParen, "after constructor payload")?;
248 args
249 } else {
250 Vec::new()
251 };
252 Ok(TypeExpr::Named { name, args })
253 }
254 other => Err(self.error(format!("expected type expression, got {other:?}"))),
255 }
256 }
257
258 fn parse_record_type(&mut self) -> Result<TypeExpr, ParseError> {
259 self.expect(&TokenKind::LBrace, "in record type")?;
260 let mut fields = Vec::new();
261 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RBrace)) {
262 loop {
263 self.skip_newlines();
264 let name = self.expect_ident("in record field")?;
265 self.expect(&TokenKind::ColonColon, "after record field name")?;
266 let ty = self.parse_type_expr()?;
267 fields.push(TypeField { name, ty });
268 self.skip_newlines();
269 if !self.eat(&TokenKind::Comma) { break; }
270 if matches!(self.peek_skip_newlines(), Some(TokenKind::RBrace)) { break; }
271 }
272 }
273 self.expect(&TokenKind::RBrace, "in record type")?;
274 Ok(TypeExpr::Record(fields))
275 }
276
277 fn parse_paren_type_or_function(&mut self) -> Result<TypeExpr, ParseError> {
278 self.expect(&TokenKind::LParen, "in type")?;
279 let mut args = Vec::new();
280 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) {
281 args.push(self.parse_type_expr()?);
282 while self.eat(&TokenKind::Comma) {
283 if matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) { break; }
284 args.push(self.parse_type_expr()?);
285 }
286 }
287 self.expect(&TokenKind::RParen, "in type")?;
288 if matches!(self.peek_skip_newlines(), Some(TokenKind::Arrow)) {
290 self.skip_newlines();
291 self.bump();
292 let effects = self.parse_effects()?;
293 let ret = self.parse_type_expr()?;
294 Ok(TypeExpr::Function {
295 params: args,
296 effects,
297 ret: Box::new(ret),
298 })
299 } else if args.len() == 1 {
300 Ok(args.into_iter().next().unwrap())
302 } else {
303 Ok(TypeExpr::Tuple(args))
304 }
305 }
306
307 fn parse_fn_decl(&mut self) -> Result<FnDecl, ParseError> {
308 self.expect(&TokenKind::Fn, "in fn decl")?;
309 let name = self.expect_ident("for function name")?;
310 let type_params = if self.eat(&TokenKind::LBracket) {
311 let ps = self.parse_ident_list()?;
312 self.expect(&TokenKind::RBracket, "after type params")?;
313 ps
314 } else {
315 Vec::new()
316 };
317 self.expect(&TokenKind::LParen, "before params")?;
318 let mut params = Vec::new();
319 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) {
320 params.push(self.parse_param()?);
321 while self.eat(&TokenKind::Comma) {
322 if matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) { break; }
323 params.push(self.parse_param()?);
324 }
325 }
326 self.expect(&TokenKind::RParen, "after params")?;
327 self.expect(&TokenKind::Arrow, "before return type")?;
328 let effects = self.parse_effects()?;
329 let return_type = self.parse_type_expr()?;
330 let body = self.parse_block()?;
331 Ok(FnDecl { name, type_params, params, effects, return_type, body })
332 }
333
334 fn parse_param(&mut self) -> Result<Param, ParseError> {
335 let name = self.expect_ident("for parameter name")?;
336 self.expect(&TokenKind::ColonColon, "after parameter name")?;
337 let ty = self.parse_type_expr()?;
338 Ok(Param { name, ty })
339 }
340
341 fn parse_effects(&mut self) -> Result<Vec<Effect>, ParseError> {
342 if !self.eat(&TokenKind::LBracket) {
343 return Ok(Vec::new());
344 }
345 let mut out = Vec::new();
346 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RBracket)) {
347 out.push(self.parse_effect()?);
348 while self.eat(&TokenKind::Comma) {
349 if matches!(self.peek_skip_newlines(), Some(TokenKind::RBracket)) { break; }
350 out.push(self.parse_effect()?);
351 }
352 }
353 self.expect(&TokenKind::RBracket, "after effects")?;
354 Ok(out)
355 }
356
357 fn parse_effect(&mut self) -> Result<Effect, ParseError> {
358 let name = self.expect_ident("for effect name")?;
359 let arg = if self.eat(&TokenKind::LParen) {
360 let arg = match self.bump().map(|t| t.kind) {
361 Some(TokenKind::Str(s)) => EffectArg::Str(s),
362 Some(TokenKind::Int(n)) => EffectArg::Int(n),
363 Some(TokenKind::Ident(s)) => EffectArg::Ident(s),
364 other => return Err(self.error(format!("invalid effect arg: {other:?}"))),
365 };
366 self.expect(&TokenKind::RParen, "after effect arg")?;
367 Some(arg)
368 } else {
369 None
370 };
371 Ok(Effect { name, arg })
372 }
373
374 fn parse_block(&mut self) -> Result<Block, ParseError> {
377 self.expect(&TokenKind::LBrace, "before block")?;
378 let mut statements = Vec::new();
379 let result;
380 loop {
381 self.skip_newlines();
382 if matches!(self.peek(), Some(TokenKind::RBrace)) {
383 result = Box::new(Expr::Lit(Literal::Unit));
385 break;
386 }
387 if matches!(self.peek(), Some(TokenKind::Let)) {
389 let stmt = self.parse_let_statement()?;
390 statements.push(stmt);
391 self.skip_newlines();
392 continue;
393 }
394 let expr = self.parse_expr()?;
395 self.skip_newlines();
396 if matches!(self.peek(), Some(TokenKind::RBrace)) {
398 result = Box::new(expr);
399 break;
400 }
401 statements.push(Statement::Expr(expr));
402 }
403 self.expect(&TokenKind::RBrace, "to close block")?;
404 Ok(Block { statements, result })
405 }
406
407 fn parse_let_statement(&mut self) -> Result<Statement, ParseError> {
408 self.expect(&TokenKind::Let, "in let")?;
409 let name = if matches!(self.peek_skip_newlines(), Some(TokenKind::Underscore)) {
415 self.skip_newlines();
416 self.bump();
417 self.discard_counter += 1;
418 format!("__lex_discard_{}", self.discard_counter)
419 } else {
420 self.expect_ident("after `let`")?
421 };
422 let ty = if self.eat(&TokenKind::ColonColon) {
423 Some(self.parse_type_expr()?)
424 } else {
425 None
426 };
427 self.expect(&TokenKind::ColonEq, "in let")?;
428 let value = self.parse_expr()?;
429 Ok(Statement::Let { name, ty, value })
430 }
431
432 fn parse_expr(&mut self) -> Result<Expr, ParseError> {
435 if self.depth >= MAX_DEPTH {
440 return Err(ParseError {
441 pos: self.current_pos(),
442 msg: format!(
443 "expression nests too deeply (max {MAX_DEPTH}); \
444 malformed or hand-crafted input?"),
445 });
446 }
447 self.depth += 1;
448 let r = self.parse_expr_inner();
449 self.depth -= 1;
450 r
451 }
452
453 fn parse_expr_inner(&mut self) -> Result<Expr, ParseError> {
454 let mut left = self.parse_binary_expr(0)?;
456 while matches!(self.peek_skip_newlines(), Some(TokenKind::Pipe)) {
457 self.skip_newlines();
458 self.bump();
459 let right = self.parse_binary_expr(0)?;
460 left = Expr::Pipe { left: Box::new(left), right: Box::new(right) };
461 }
462 Ok(left)
463 }
464
465 fn parse_binary_expr(&mut self, min_prec: u8) -> Result<Expr, ParseError> {
466 let mut lhs = self.parse_unary()?;
467 loop {
468 let op = match self.peek_binop() {
469 Some(op) if op.precedence() >= min_prec => op,
470 _ => break,
471 };
472 self.skip_newlines();
473 self.bump();
474 let rhs = self.parse_binary_expr(op.precedence() + 1)?;
475 lhs = Expr::BinOp { op, lhs: Box::new(lhs), rhs: Box::new(rhs) };
476 }
477 Ok(lhs)
478 }
479
480 fn peek_binop(&mut self) -> Option<BinOp> {
481 match self.peek_skip_newlines()? {
482 TokenKind::Plus => Some(BinOp::Add),
483 TokenKind::Minus => Some(BinOp::Sub),
484 TokenKind::Star => Some(BinOp::Mul),
485 TokenKind::Slash => Some(BinOp::Div),
486 TokenKind::Percent => Some(BinOp::Mod),
487 TokenKind::EqEq => Some(BinOp::Eq),
488 TokenKind::BangEq => Some(BinOp::Neq),
489 TokenKind::Lt => Some(BinOp::Lt),
490 TokenKind::LtEq => Some(BinOp::Lte),
491 TokenKind::Gt => Some(BinOp::Gt),
492 TokenKind::GtEq => Some(BinOp::Gte),
493 TokenKind::And => Some(BinOp::And),
494 TokenKind::Or => Some(BinOp::Or),
495 _ => None,
496 }
497 }
498
499 fn parse_unary(&mut self) -> Result<Expr, ParseError> {
500 self.skip_newlines();
501 match self.peek() {
502 Some(TokenKind::Not) => {
503 self.bump();
504 let inner = self.parse_unary()?;
505 Ok(Expr::UnaryOp { op: UnaryOp::Not, expr: Box::new(inner) })
506 }
507 Some(TokenKind::Minus) => {
508 self.bump();
509 let inner = self.parse_unary()?;
510 Ok(Expr::UnaryOp { op: UnaryOp::Neg, expr: Box::new(inner) })
511 }
512 _ => self.parse_postfix(),
513 }
514 }
515
516 fn parse_postfix(&mut self) -> Result<Expr, ParseError> {
517 let mut expr = self.parse_primary()?;
518 loop {
519 match self.peek() {
521 Some(TokenKind::Dot) => {
522 self.bump();
523 let field = self.expect_ident("after `.`")?;
524 expr = Expr::Field { value: Box::new(expr), field };
525 }
526 Some(TokenKind::LParen) => {
527 self.bump();
528 let mut args = Vec::new();
529 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) {
530 args.push(self.parse_expr()?);
531 while self.eat(&TokenKind::Comma) {
532 if matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) { break; }
533 args.push(self.parse_expr()?);
534 }
535 }
536 self.expect(&TokenKind::RParen, "in call")?;
537 expr = Expr::Call { callee: Box::new(expr), args };
538 }
539 Some(TokenKind::Question) => {
540 self.bump();
541 expr = Expr::Try(Box::new(expr));
542 }
543 _ => break,
544 }
545 }
546 Ok(expr)
547 }
548
549 fn parse_primary(&mut self) -> Result<Expr, ParseError> {
550 self.skip_newlines();
551 match self.peek() {
552 Some(TokenKind::Int(_)) => match self.bump().unwrap().kind {
553 TokenKind::Int(n) => Ok(Expr::Lit(Literal::Int(n))),
554 _ => unreachable!(),
555 },
556 Some(TokenKind::Float(_)) => match self.bump().unwrap().kind {
557 TokenKind::Float(n) => Ok(Expr::Lit(Literal::Float(n))),
558 _ => unreachable!(),
559 },
560 Some(TokenKind::Str(_)) => match self.bump().unwrap().kind {
561 TokenKind::Str(s) => Ok(Expr::Lit(Literal::Str(s))),
562 _ => unreachable!(),
563 },
564 Some(TokenKind::Bytes(_)) => match self.bump().unwrap().kind {
565 TokenKind::Bytes(b) => Ok(Expr::Lit(Literal::Bytes(b))),
566 _ => unreachable!(),
567 },
568 Some(TokenKind::True) => { self.bump(); Ok(Expr::Lit(Literal::Bool(true))) }
569 Some(TokenKind::False) => { self.bump(); Ok(Expr::Lit(Literal::Bool(false))) }
570 Some(TokenKind::If) => self.parse_if(),
571 Some(TokenKind::Match) => self.parse_match(),
572 Some(TokenKind::Fn) => self.parse_lambda(),
573 Some(TokenKind::LBrace) => self.parse_brace_expr(),
574 Some(TokenKind::LBracket) => self.parse_list_literal(),
575 Some(TokenKind::LParen) => self.parse_paren_or_tuple(),
576 Some(TokenKind::Ident(_)) => self.parse_ident_or_record(),
577 other => Err(self.error(format!("expected expression, got {other:?}"))),
578 }
579 }
580
581 fn parse_brace_expr(&mut self) -> Result<Expr, ParseError> {
585 let saved = self.idx;
587 self.bump(); while matches!(self.peek(), Some(TokenKind::Newline) | Some(TokenKind::Semi)) {
590 self.idx += 1;
591 }
592 let is_record = matches!(self.peek(), Some(TokenKind::RBrace))
593 || (matches!(self.peek(), Some(TokenKind::Ident(_)))
594 && matches!(self.tokens.get(self.idx + 1).map(|t| &t.kind), Some(TokenKind::Colon) | Some(TokenKind::Comma) | Some(TokenKind::RBrace)));
595 self.idx = saved;
596 if is_record {
597 self.parse_record_literal()
598 } else {
599 Ok(Expr::Block(self.parse_block()?))
600 }
601 }
602
603 fn parse_record_literal(&mut self) -> Result<Expr, ParseError> {
604 self.expect(&TokenKind::LBrace, "in record literal")?;
605 let mut fields = Vec::new();
606 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RBrace)) {
607 loop {
608 self.skip_newlines();
609 let name = self.expect_ident("in record literal")?;
610 let value = if self.eat(&TokenKind::Colon) {
611 self.parse_expr()?
612 } else {
613 Expr::Var(name.clone())
615 };
616 fields.push(RecordLitField { name, value });
617 self.skip_newlines();
618 if !self.eat(&TokenKind::Comma) { break; }
619 if matches!(self.peek_skip_newlines(), Some(TokenKind::RBrace)) { break; }
620 }
621 }
622 self.expect(&TokenKind::RBrace, "after record literal")?;
623 Ok(Expr::RecordLit(fields))
624 }
625
626 fn parse_if(&mut self) -> Result<Expr, ParseError> {
627 self.expect(&TokenKind::If, "in if")?;
628 let cond = self.parse_expr()?;
629 let then_block = self.parse_block()?;
630 self.expect(&TokenKind::Else, "expected `else`")?;
631 let else_block = self.parse_block()?;
632 Ok(Expr::If { cond: Box::new(cond), then_block, else_block })
633 }
634
635 fn parse_match(&mut self) -> Result<Expr, ParseError> {
636 self.expect(&TokenKind::Match, "in match")?;
637 let scrutinee = self.parse_expr()?;
638 self.expect(&TokenKind::LBrace, "before match arms")?;
639 let mut arms = Vec::new();
640 loop {
641 self.skip_newlines();
642 if matches!(self.peek(), Some(TokenKind::RBrace)) { break; }
643 let pattern = self.parse_pattern()?;
644 self.expect(&TokenKind::FatArrow, "in match arm")?;
645 let body = self.parse_expr()?;
646 arms.push(Arm { pattern, body });
647 self.skip_newlines();
648 if !self.eat(&TokenKind::Comma) { break; }
649 }
650 self.expect(&TokenKind::RBrace, "after match arms")?;
651 Ok(Expr::Match { scrutinee: Box::new(scrutinee), arms })
652 }
653
654 fn parse_lambda(&mut self) -> Result<Expr, ParseError> {
655 self.expect(&TokenKind::Fn, "in lambda")?;
656 self.expect(&TokenKind::LParen, "before lambda params")?;
657 let mut params = Vec::new();
658 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) {
659 params.push(self.parse_param()?);
660 while self.eat(&TokenKind::Comma) {
661 if matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) { break; }
662 params.push(self.parse_param()?);
663 }
664 }
665 self.expect(&TokenKind::RParen, "after lambda params")?;
666 self.expect(&TokenKind::Arrow, "before lambda return type")?;
667 let effects = self.parse_effects()?;
668 let return_type = self.parse_type_expr()?;
669 let body = self.parse_block()?;
670 Ok(Expr::Lambda(Box::new(Lambda { params, effects, return_type, body })))
671 }
672
673 fn parse_list_literal(&mut self) -> Result<Expr, ParseError> {
674 self.expect(&TokenKind::LBracket, "before list literal")?;
675 let mut items = Vec::new();
676 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RBracket)) {
677 items.push(self.parse_expr()?);
678 while self.eat(&TokenKind::Comma) {
679 if matches!(self.peek_skip_newlines(), Some(TokenKind::RBracket)) { break; }
680 items.push(self.parse_expr()?);
681 }
682 }
683 self.expect(&TokenKind::RBracket, "after list literal")?;
684 Ok(Expr::ListLit(items))
685 }
686
687 fn parse_paren_or_tuple(&mut self) -> Result<Expr, ParseError> {
688 self.expect(&TokenKind::LParen, "")?;
689 if matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) {
690 self.bump();
691 return Ok(Expr::Lit(Literal::Unit));
692 }
693 let first = self.parse_expr()?;
694 if self.eat(&TokenKind::Comma) {
695 let mut items = vec![first];
696 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) {
697 items.push(self.parse_expr()?);
698 while self.eat(&TokenKind::Comma) {
699 if matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) { break; }
700 items.push(self.parse_expr()?);
701 }
702 }
703 self.expect(&TokenKind::RParen, "after tuple")?;
704 Ok(Expr::TupleLit(items))
705 } else {
706 self.expect(&TokenKind::RParen, "after parenthesized expression")?;
707 Ok(first)
708 }
709 }
710
711 fn parse_ident_or_record(&mut self) -> Result<Expr, ParseError> {
712 let name = self.expect_ident("")?;
714 Ok(Expr::Var(name))
715 }
716
717 fn parse_pattern(&mut self) -> Result<Pattern, ParseError> {
720 self.skip_newlines();
721 match self.peek() {
722 Some(TokenKind::Underscore) => { self.bump(); Ok(Pattern::Wild) }
723 Some(TokenKind::Int(_)) => match self.bump().unwrap().kind {
724 TokenKind::Int(n) => Ok(Pattern::Lit(Literal::Int(n))),
725 _ => unreachable!(),
726 },
727 Some(TokenKind::Float(_)) => match self.bump().unwrap().kind {
728 TokenKind::Float(n) => Ok(Pattern::Lit(Literal::Float(n))),
729 _ => unreachable!(),
730 },
731 Some(TokenKind::Str(_)) => match self.bump().unwrap().kind {
732 TokenKind::Str(s) => Ok(Pattern::Lit(Literal::Str(s))),
733 _ => unreachable!(),
734 },
735 Some(TokenKind::True) => { self.bump(); Ok(Pattern::Lit(Literal::Bool(true))) }
736 Some(TokenKind::False) => { self.bump(); Ok(Pattern::Lit(Literal::Bool(false))) }
737 Some(TokenKind::LBrace) => self.parse_record_pattern(),
738 Some(TokenKind::LParen) => self.parse_tuple_pattern(),
739 Some(TokenKind::Ident(_)) => {
740 let name = self.expect_ident("")?;
741 if matches!(self.peek(), Some(TokenKind::LParen)) {
742 self.bump();
743 let mut args = Vec::new();
744 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) {
745 args.push(self.parse_pattern()?);
746 while self.eat(&TokenKind::Comma) {
747 if matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) { break; }
748 args.push(self.parse_pattern()?);
749 }
750 }
751 self.expect(&TokenKind::RParen, "after constructor pattern")?;
752 Ok(Pattern::Constructor { name, args })
753 } else {
754 Ok(Pattern::Var(name))
755 }
756 }
757 other => Err(self.error(format!("expected pattern, got {other:?}"))),
758 }
759 }
760
761 fn parse_record_pattern(&mut self) -> Result<Pattern, ParseError> {
762 self.expect(&TokenKind::LBrace, "")?;
763 let mut fields = Vec::new();
764 let rest = false;
765 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RBrace)) {
766 loop {
767 self.skip_newlines();
768 let name = self.expect_ident("in record pattern")?;
769 let pattern = if self.eat(&TokenKind::Colon) {
770 Some(self.parse_pattern()?)
771 } else {
772 None
773 };
774 fields.push(RecordPatField { name, pattern });
775 self.skip_newlines();
776 if !self.eat(&TokenKind::Comma) { break; }
777 if matches!(self.peek_skip_newlines(), Some(TokenKind::RBrace)) { break; }
778 }
779 }
780 self.expect(&TokenKind::RBrace, "after record pattern")?;
781 Ok(Pattern::Record { fields, rest })
782 }
783
784 fn parse_tuple_pattern(&mut self) -> Result<Pattern, ParseError> {
785 self.expect(&TokenKind::LParen, "")?;
786 let mut items = Vec::new();
787 if !matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) {
788 items.push(self.parse_pattern()?);
789 while self.eat(&TokenKind::Comma) {
790 if matches!(self.peek_skip_newlines(), Some(TokenKind::RParen)) { break; }
791 items.push(self.parse_pattern()?);
792 }
793 }
794 self.expect(&TokenKind::RParen, "after tuple pattern")?;
795 if items.len() == 1 {
796 Ok(items.into_iter().next().unwrap())
797 } else {
798 Ok(Pattern::Tuple(items))
799 }
800 }
801}
802
803fn type_to_variant(t: TypeExpr) -> Result<UnionVariant, ParseError> {
806 match t {
807 TypeExpr::Named { name, args } => {
808 let payload = match args.len() {
809 0 => None,
810 1 => Some(args.into_iter().next().unwrap()),
811 _ => Some(TypeExpr::Tuple(args)),
812 };
813 Ok(UnionVariant { name, payload })
814 }
815 _ => Err(ParseError {
817 pos: 0,
818 msg: "union variant must be a constructor name".into(),
819 }),
820 }
821}