1use crate::ast::*;
10use crate::diagnostic::{LuxError, Span};
11use crate::lexer::{Tok, Token};
12
13struct Parser {
14 tokens: Vec<Token>,
15 pos: usize,
16}
17
18pub fn parse(tokens: Vec<Token>) -> Result<Vec<Stmt>, LuxError> {
20 let mut p = Parser { tokens, pos: 0 };
21 let mut stmts = Vec::new();
22 while !p.at_eof() {
23 stmts.push(p.statement()?);
24 }
25 Ok(stmts)
26}
27
28impl Parser {
29 fn peek(&self) -> &Token {
30 &self.tokens[self.pos]
31 }
32
33 fn peek_tok(&self) -> &Tok {
34 &self.tokens[self.pos].tok
35 }
36
37 fn next_tok(&self) -> &Tok {
38 let j = (self.pos + 1).min(self.tokens.len() - 1);
39 &self.tokens[j].tok
40 }
41
42 fn span(&self) -> Span {
43 self.peek().span
44 }
45
46 fn at_eof(&self) -> bool {
47 matches!(self.peek_tok(), Tok::Eof)
48 }
49
50 fn advance(&mut self) -> Token {
51 let t = self.tokens[self.pos].clone();
52 if self.pos < self.tokens.len() - 1 {
53 self.pos += 1;
54 }
55 t
56 }
57
58 fn expect(&mut self, want: &Tok, what: &str) -> Result<Token, LuxError> {
60 if std::mem::discriminant(self.peek_tok()) == std::mem::discriminant(want) {
61 Ok(self.advance())
62 } else {
63 Err(LuxError::new(format!("expected {}", what), self.span()))
64 }
65 }
66
67 fn ident(&mut self, what: &str) -> Result<(String, Span), LuxError> {
68 let t = self.peek().clone();
69 if let Tok::Ident(name) = t.tok {
70 self.advance();
71 Ok((name, t.span))
72 } else {
73 Err(LuxError::new(format!("expected {}", what), t.span))
74 }
75 }
76
77 fn optional_type(&mut self) -> Result<Option<TypeAnn>, LuxError> {
78 if matches!(self.peek_tok(), Tok::Colon) {
79 self.advance();
80 Ok(Some(self.parse_type()?))
81 } else {
82 Ok(None)
83 }
84 }
85
86 fn parse_type(&mut self) -> Result<TypeAnn, LuxError> {
88 if matches!(self.peek_tok(), Tok::LBracket) {
89 let start = self.span();
90 self.advance();
91 let elem = self.parse_type()?;
92 let close = self.expect(&Tok::RBracket, "']' to close the array type")?;
93 Ok(TypeAnn {
94 kind: TypeKind::Array(Box::new(elem)),
95 span: start.to(close.span),
96 })
97 } else {
98 let (name, span) = self.ident("a type name")?;
99 if matches!(self.peek_tok(), Tok::Lt) {
101 self.advance(); let mut args = Vec::new();
103 loop {
104 args.push(self.parse_type()?);
105 if matches!(self.peek_tok(), Tok::Comma) {
106 self.advance();
107 if matches!(self.peek_tok(), Tok::Gt) {
109 break;
110 }
111 } else {
112 break;
113 }
114 }
115 let close = self.expect(&Tok::Gt, "'>' to close the type parameters")?;
116 Ok(TypeAnn {
117 kind: TypeKind::Generic(name, args),
118 span: span.to(close.span),
119 })
120 } else {
121 Ok(TypeAnn {
122 kind: TypeKind::Named(name),
123 span,
124 })
125 }
126 }
127 }
128
129 fn statement(&mut self) -> Result<Stmt, LuxError> {
132 match self.peek_tok() {
133 Tok::Let => self.let_stmt(),
134 Tok::Var => self.var_stmt(),
135 Tok::Func => self.func_stmt(),
136 Tok::Return => self.return_stmt(),
137 Tok::Struct => self.struct_stmt(),
138 Tok::Enum => self.enum_stmt(),
139 Tok::If => self.if_stmt(),
140 Tok::While => self.while_stmt(),
141 Tok::For => self.for_stmt(),
142 Tok::Ident(_) if self.assign_ahead() => self.assign_stmt(),
143 _ => Ok(Stmt::Expr(self.expression()?)),
144 }
145 }
146
147 fn assign_ahead(&self) -> bool {
149 matches!(self.next_tok(), Tok::Eq | Tok::PlusEq | Tok::MinusEq)
150 }
151
152 fn let_stmt(&mut self) -> Result<Stmt, LuxError> {
153 let start = self.span();
154 self.advance(); let (name, _) = self.ident("a name after 'let'")?;
156 let ty = self.optional_type()?;
157 self.expect(&Tok::Eq, "'=' and a value ('let' always needs a value)")?;
158 let value = self.expression()?;
159 let span = start.to(value.span());
160 Ok(Stmt::Let {
161 name,
162 ty,
163 value,
164 span,
165 })
166 }
167
168 fn var_stmt(&mut self) -> Result<Stmt, LuxError> {
169 let start = self.span();
170 self.advance(); let (name, name_span) = self.ident("a name after 'var'")?;
172 let ty = self.optional_type()?;
173 let (value, end) = if matches!(self.peek_tok(), Tok::Eq) {
174 self.advance();
175 let v = self.expression()?;
176 let sp = v.span();
177 (Some(v), sp)
178 } else {
179 let end = ty.as_ref().map(|t| t.span).unwrap_or(name_span);
180 (None, end)
181 };
182 Ok(Stmt::Var {
183 name,
184 ty,
185 value,
186 span: start.to(end),
187 })
188 }
189
190 fn func_stmt(&mut self) -> Result<Stmt, LuxError> {
191 let start = self.span();
192 self.advance(); let (name, _) = self.ident("a function name after 'func'")?;
194 let params = self.params()?;
195 let ret = if matches!(self.peek_tok(), Tok::Arrow) {
196 self.advance();
197 Some(self.parse_type()?)
198 } else {
199 None
200 };
201 let body = self.block()?;
202 Ok(Stmt::Func {
203 name,
204 params,
205 ret,
206 body,
207 span: start,
208 })
209 }
210
211 fn params(&mut self) -> Result<Vec<Param>, LuxError> {
213 self.expect(&Tok::LParen, "'(' to start the parameter list")?;
214 let mut params = Vec::new();
215 if !matches!(self.peek_tok(), Tok::RParen) {
216 loop {
217 let (name, name_span) = self.ident("a parameter name")?;
218 self.expect(&Tok::Colon, "':' and a type for the parameter")?;
219 let ty = self.parse_type()?;
220 let span = name_span.to(ty.span);
221 params.push(Param { name, ty, span });
222 if matches!(self.peek_tok(), Tok::Comma) {
223 self.advance();
224 if matches!(self.peek_tok(), Tok::RParen) {
225 break;
226 }
227 } else {
228 break;
229 }
230 }
231 }
232 self.expect(&Tok::RParen, "')' to close the parameter list")?;
233 Ok(params)
234 }
235
236 fn struct_stmt(&mut self) -> Result<Stmt, LuxError> {
237 let start = self.span();
238 self.advance(); let (name, _) = self.ident("a struct name after 'struct'")?;
240 self.expect(&Tok::LBrace, "'{' to start the struct body")?;
241 let mut fields = Vec::new();
242 while !matches!(self.peek_tok(), Tok::RBrace | Tok::Eof) {
243 fields.push(self.field_def()?);
244 if matches!(self.peek_tok(), Tok::Comma) {
246 self.advance();
247 }
248 }
249 self.expect(&Tok::RBrace, "'}' to close the struct")?;
250 Ok(Stmt::Struct {
251 name,
252 fields,
253 span: start,
254 })
255 }
256
257 fn enum_stmt(&mut self) -> Result<Stmt, LuxError> {
258 let start = self.span();
259 self.advance(); let (name, _) = self.ident("an enum name after 'enum'")?;
261 self.expect(&Tok::LBrace, "'{' to start the enum body")?;
262 let mut variants = Vec::new();
263 while !matches!(self.peek_tok(), Tok::RBrace | Tok::Eof) {
264 let (vname, vspan) = self.ident("a case name")?;
265 let mut fields = Vec::new();
266 if matches!(self.peek_tok(), Tok::LParen) {
267 self.advance(); if !matches!(self.peek_tok(), Tok::RParen) {
269 loop {
270 fields.push(self.field_def()?);
271 if matches!(self.peek_tok(), Tok::Comma) {
272 self.advance();
273 if matches!(self.peek_tok(), Tok::RParen) {
274 break;
275 }
276 } else {
277 break;
278 }
279 }
280 }
281 self.expect(&Tok::RParen, "')' to close the case's values")?;
282 }
283 variants.push(VariantDef {
284 name: vname,
285 fields,
286 span: vspan,
287 });
288 if matches!(self.peek_tok(), Tok::Comma) {
289 self.advance();
290 }
291 }
292 self.expect(&Tok::RBrace, "'}' to close the enum")?;
293 Ok(Stmt::Enum {
294 name,
295 variants,
296 span: start,
297 })
298 }
299
300 fn field_def(&mut self) -> Result<FieldDef, LuxError> {
302 let (name, name_span) = self.ident("a field name")?;
303 self.expect(&Tok::Colon, "':' and a type for the field")?;
304 let ty = self.parse_type()?;
305 let span = name_span.to(ty.span);
306 Ok(FieldDef { name, ty, span })
307 }
308
309 fn return_stmt(&mut self) -> Result<Stmt, LuxError> {
310 let start = self.span();
311 self.advance(); if matches!(self.peek_tok(), Tok::RBrace | Tok::Eof) {
314 Ok(Stmt::Return {
315 value: None,
316 span: start,
317 })
318 } else {
319 let value = self.expression()?;
320 let span = start.to(value.span());
321 Ok(Stmt::Return {
322 value: Some(value),
323 span,
324 })
325 }
326 }
327
328 fn for_stmt(&mut self) -> Result<Stmt, LuxError> {
329 let start = self.span();
330 self.advance(); let (var, _) = self.ident("a loop variable after 'for'")?;
332 self.expect(&Tok::In, "'in' after the loop variable")?;
333 let iter = self.expression()?;
334 let body = self.block()?;
335 Ok(Stmt::For {
336 var,
337 iter,
338 body,
339 span: start,
340 })
341 }
342
343 fn assign_stmt(&mut self) -> Result<Stmt, LuxError> {
344 let (name, name_span) = self.ident("a name")?;
345 let op = match self.peek_tok() {
346 Tok::Eq => AssignOp::Set,
347 Tok::PlusEq => AssignOp::Add,
348 Tok::MinusEq => AssignOp::Sub,
349 _ => unreachable!("assign_ahead guaranteed an assignment operator"),
350 };
351 self.advance();
352 let value = self.expression()?;
353 let span = name_span.to(value.span());
354 Ok(Stmt::Assign {
355 name,
356 name_span,
357 op,
358 value,
359 span,
360 })
361 }
362
363 fn if_stmt(&mut self) -> Result<Stmt, LuxError> {
364 let start = self.span();
365 self.advance(); let cond = self.expression()?;
367 let then_body = self.block()?;
368 let mut else_body = None;
369 if matches!(self.peek_tok(), Tok::Else) {
370 self.advance();
371 if matches!(self.peek_tok(), Tok::If) {
372 else_body = Some(vec![self.if_stmt()?]);
373 } else {
374 else_body = Some(self.block()?);
375 }
376 }
377 Ok(Stmt::If {
378 cond,
379 then_body,
380 else_body,
381 span: start,
382 })
383 }
384
385 fn while_stmt(&mut self) -> Result<Stmt, LuxError> {
386 let start = self.span();
387 self.advance(); let cond = self.expression()?;
389 let body = self.block()?;
390 Ok(Stmt::While {
391 cond,
392 body,
393 span: start,
394 })
395 }
396
397 fn block(&mut self) -> Result<Vec<Stmt>, LuxError> {
398 self.expect(&Tok::LBrace, "'{' to start a block")?;
399 let mut stmts = Vec::new();
400 while !matches!(self.peek_tok(), Tok::RBrace | Tok::Eof) {
401 stmts.push(self.statement()?);
402 }
403 self.expect(&Tok::RBrace, "'}' to close the block")?;
404 Ok(stmts)
405 }
406
407 fn expression(&mut self) -> Result<Expr, LuxError> {
410 self.range()
411 }
412
413 fn range(&mut self) -> Result<Expr, LuxError> {
416 let lhs = self.or()?;
417 if matches!(self.peek_tok(), Tok::DotDot) {
418 self.advance();
419 let rhs = self.or()?;
420 let span = lhs.span().to(rhs.span());
421 Ok(Expr::Range {
422 start: Box::new(lhs),
423 end: Box::new(rhs),
424 span,
425 })
426 } else {
427 Ok(lhs)
428 }
429 }
430
431 fn or(&mut self) -> Result<Expr, LuxError> {
432 let mut lhs = self.and()?;
433 while matches!(self.peek_tok(), Tok::OrOr) {
434 self.advance();
435 let rhs = self.and()?;
436 lhs = binary(BinOp::Or, lhs, rhs);
437 }
438 Ok(lhs)
439 }
440
441 fn and(&mut self) -> Result<Expr, LuxError> {
442 let mut lhs = self.equality()?;
443 while matches!(self.peek_tok(), Tok::AndAnd) {
444 self.advance();
445 let rhs = self.equality()?;
446 lhs = binary(BinOp::And, lhs, rhs);
447 }
448 Ok(lhs)
449 }
450
451 fn equality(&mut self) -> Result<Expr, LuxError> {
452 let mut lhs = self.comparison()?;
453 loop {
454 let op = match self.peek_tok() {
455 Tok::EqEq => BinOp::Eq,
456 Tok::NotEq => BinOp::Ne,
457 _ => break,
458 };
459 self.advance();
460 let rhs = self.comparison()?;
461 lhs = binary(op, lhs, rhs);
462 }
463 Ok(lhs)
464 }
465
466 fn comparison(&mut self) -> Result<Expr, LuxError> {
467 let mut lhs = self.term()?;
468 loop {
469 let op = match self.peek_tok() {
470 Tok::Lt => BinOp::Lt,
471 Tok::Gt => BinOp::Gt,
472 Tok::Le => BinOp::Le,
473 Tok::Ge => BinOp::Ge,
474 _ => break,
475 };
476 self.advance();
477 let rhs = self.term()?;
478 lhs = binary(op, lhs, rhs);
479 }
480 Ok(lhs)
481 }
482
483 fn term(&mut self) -> Result<Expr, LuxError> {
484 let mut lhs = self.factor()?;
485 loop {
486 let op = match self.peek_tok() {
487 Tok::Plus => BinOp::Add,
488 Tok::Minus => BinOp::Sub,
489 _ => break,
490 };
491 self.advance();
492 let rhs = self.factor()?;
493 lhs = binary(op, lhs, rhs);
494 }
495 Ok(lhs)
496 }
497
498 fn factor(&mut self) -> Result<Expr, LuxError> {
499 let mut lhs = self.unary()?;
500 loop {
501 let op = match self.peek_tok() {
502 Tok::Star => BinOp::Mul,
503 Tok::Slash => BinOp::Div,
504 Tok::Percent => BinOp::Mod,
505 _ => break,
506 };
507 self.advance();
508 let rhs = self.unary()?;
509 lhs = binary(op, lhs, rhs);
510 }
511 Ok(lhs)
512 }
513
514 fn unary(&mut self) -> Result<Expr, LuxError> {
515 let t = self.peek().clone();
516 match t.tok {
517 Tok::Bang => {
518 self.advance();
519 let rhs = self.unary()?;
520 let span = t.span.to(rhs.span());
521 Ok(Expr::Unary {
522 op: UnOp::Not,
523 rhs: Box::new(rhs),
524 span,
525 })
526 }
527 Tok::Minus => {
528 self.advance();
529 let rhs = self.unary()?;
530 let span = t.span.to(rhs.span());
531 Ok(Expr::Unary {
532 op: UnOp::Neg,
533 rhs: Box::new(rhs),
534 span,
535 })
536 }
537 _ => self.postfix(),
538 }
539 }
540
541 fn postfix(&mut self) -> Result<Expr, LuxError> {
544 let mut e = self.primary()?;
545 loop {
546 match self.peek_tok() {
547 Tok::LBracket => {
548 self.advance();
549 let index = self.expression()?;
550 let close = self.expect(&Tok::RBracket, "']' to close the index")?;
551 let span = e.span().to(close.span);
552 e = Expr::Index {
553 base: Box::new(e),
554 index: Box::new(index),
555 span,
556 };
557 }
558 Tok::Dot => {
559 self.advance();
560 let (field, field_span) = self.ident("a field or case name after '.'")?;
561 if matches!(self.peek_tok(), Tok::LParen) {
562 let enum_name = match &e {
565 Expr::Ident(n, _) => n.clone(),
566 _ => {
567 return Err(LuxError::new(
568 "only an enum name can be used like `Name.case(...)`",
569 e.span(),
570 )
571 .with_learn(
572 "enums",
573 "`Shape.circle(...)` builds one case of an enum",
574 ));
575 }
576 };
577 self.advance(); let fields = self.label_list()?;
579 let close = self.expect(&Tok::RParen, "')' to close the case's values")?;
580 let span = e.span().to(close.span);
581 e = Expr::EnumLit {
582 enum_name,
583 variant: field,
584 fields,
585 span,
586 };
587 } else {
588 let span = e.span().to(field_span);
589 e = Expr::Field {
590 base: Box::new(e),
591 field,
592 span,
593 };
594 }
595 }
596 _ => break,
597 }
598 }
599 Ok(e)
600 }
601
602 fn label_list(&mut self) -> Result<Vec<(String, Expr)>, LuxError> {
606 let mut fields = Vec::new();
607 if !matches!(self.peek_tok(), Tok::RParen) {
608 loop {
609 let (name, _) = self.ident("a field name")?;
610 self.expect(&Tok::Colon, "':' after the field name")?;
611 let value = self.expression()?;
612 fields.push((name, value));
613 if matches!(self.peek_tok(), Tok::Comma) {
614 self.advance();
615 if matches!(self.peek_tok(), Tok::RParen) {
616 break;
617 }
618 } else {
619 break;
620 }
621 }
622 }
623 Ok(fields)
624 }
625
626 fn match_expr(&mut self) -> Result<Expr, LuxError> {
628 let start = self.span();
629 self.advance(); let scrutinee = self.expression()?;
631 self.expect(&Tok::LBrace, "'{' to start the match arms")?;
632 let mut arms = Vec::new();
633 while !matches!(self.peek_tok(), Tok::RBrace | Tok::Eof) {
634 let pattern = self.pattern()?;
635 self.expect(&Tok::FatArrow, "'=>' after the pattern")?;
636 let body = self.expression()?;
637 let span = pattern.span().to(body.span());
638 arms.push(MatchArm {
639 pattern,
640 body,
641 span,
642 });
643 }
644 let close = self.expect(&Tok::RBrace, "'}' to close the match")?;
645 Ok(Expr::Match {
646 scrutinee: Box::new(scrutinee),
647 arms,
648 span: start.to(close.span),
649 })
650 }
651
652 fn pattern(&mut self) -> Result<Pattern, LuxError> {
655 let t = self.peek().clone();
656 match t.tok {
657 Tok::Int(v) => {
658 self.advance();
659 Ok(Pattern::Int(v, t.span))
660 }
661 Tok::Minus => {
662 self.advance();
663 let nt = self.peek().clone();
664 if let Tok::Int(v) = nt.tok {
665 self.advance();
666 Ok(Pattern::Int(-v, t.span.to(nt.span)))
667 } else {
668 Err(LuxError::new(
669 "expected a number after '-' in a pattern",
670 nt.span,
671 ))
672 }
673 }
674 Tok::Str(s) => {
675 self.advance();
676 Ok(Pattern::Str(s, t.span))
677 }
678 Tok::True => {
679 self.advance();
680 Ok(Pattern::Bool(true, t.span))
681 }
682 Tok::False => {
683 self.advance();
684 Ok(Pattern::Bool(false, t.span))
685 }
686 Tok::Ident(name) => {
687 self.advance();
688 if name == "_" {
689 Ok(Pattern::Wildcard(t.span))
690 } else if matches!(self.peek_tok(), Tok::LParen) {
691 self.advance(); let mut bindings = Vec::new();
693 if !matches!(self.peek_tok(), Tok::RParen) {
694 loop {
695 self.expect(
696 &Tok::Let,
697 "'let' before each captured name, like circle(let r)",
698 )?;
699 let (b, _) = self.ident("a name to bind")?;
700 bindings.push(b);
701 if matches!(self.peek_tok(), Tok::Comma) {
702 self.advance();
703 if matches!(self.peek_tok(), Tok::RParen) {
704 break;
705 }
706 } else {
707 break;
708 }
709 }
710 }
711 let close = self.expect(&Tok::RParen, "')' to close the pattern")?;
712 Ok(Pattern::Variant {
713 name,
714 bindings,
715 span: t.span.to(close.span),
716 })
717 } else {
718 Ok(Pattern::Variant {
719 name,
720 bindings: Vec::new(),
721 span: t.span,
722 })
723 }
724 }
725 _ => Err(LuxError::new("expected a pattern", t.span)
726 .with_note("a pattern is a case name, a literal (int, string, true/false), or `_`")
727 .with_learn(
728 "match",
729 "each arm starts with a pattern — what it's looking for",
730 )),
731 }
732 }
733
734 fn primary(&mut self) -> Result<Expr, LuxError> {
735 let t = self.peek().clone();
736 match t.tok {
737 Tok::Int(v) => {
738 self.advance();
739 Ok(Expr::Int(v, t.span))
740 }
741 Tok::Float(v) => {
742 self.advance();
743 Ok(Expr::Float(v, t.span))
744 }
745 Tok::Str(s) => {
746 self.advance();
747 Ok(Expr::Str(s, t.span))
748 }
749 Tok::True => {
750 self.advance();
751 Ok(Expr::Bool(true, t.span))
752 }
753 Tok::False => {
754 self.advance();
755 Ok(Expr::Bool(false, t.span))
756 }
757 Tok::LParen => {
758 self.advance();
759 let e = self.expression()?;
760 self.expect(&Tok::RParen, "')' to close the group")?;
761 Ok(e)
762 }
763 Tok::LBracket => {
764 self.advance();
765 let mut elems = Vec::new();
766 if !matches!(self.peek_tok(), Tok::RBracket) {
767 loop {
768 elems.push(self.expression()?);
769 if matches!(self.peek_tok(), Tok::Comma) {
770 self.advance();
771 if matches!(self.peek_tok(), Tok::RBracket) {
773 break;
774 }
775 } else {
776 break;
777 }
778 }
779 }
780 let close = self.expect(&Tok::RBracket, "']' to close the array")?;
781 Ok(Expr::Array(elems, t.span.to(close.span)))
782 }
783 Tok::Match => self.match_expr(),
784 Tok::Ident(name) => {
785 self.advance();
786 if matches!(self.peek_tok(), Tok::LParen) {
787 self.advance(); if matches!(self.peek_tok(), Tok::Ident(_))
792 && matches!(self.next_tok(), Tok::Colon)
793 {
794 let fields = self.label_list()?;
795 let close = self.expect(&Tok::RParen, "')' to close the struct fields")?;
796 Ok(Expr::StructLit {
797 name,
798 fields,
799 span: t.span.to(close.span),
800 })
801 } else {
802 let mut args = Vec::new();
803 if !matches!(self.peek_tok(), Tok::RParen) {
804 loop {
805 args.push(self.expression()?);
806 if matches!(self.peek_tok(), Tok::Comma) {
807 self.advance();
808 if matches!(self.peek_tok(), Tok::RParen) {
809 break;
810 }
811 } else {
812 break;
813 }
814 }
815 }
816 let close = self.expect(&Tok::RParen, "')' to close the call")?;
817 Ok(Expr::Call {
818 name,
819 args,
820 span: t.span.to(close.span),
821 })
822 }
823 } else {
824 Ok(Expr::Ident(name, t.span))
825 }
826 }
827 _ => Err(LuxError::new("expected a value", t.span)),
828 }
829 }
830}
831
832fn binary(op: BinOp, lhs: Expr, rhs: Expr) -> Expr {
834 let span = lhs.span().to(rhs.span());
835 Expr::Binary {
836 op,
837 lhs: Box::new(lhs),
838 rhs: Box::new(rhs),
839 span,
840 }
841}