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