1use crate::ast::{
6 Argument, BinaryOp, Expr, ExprKind, Modifiers, Parameter, SourceFile, Statement, UnaryOp,
7};
8use crate::error::{ParseError, ParseResult};
9use crate::lexer::{self, SpannedToken};
10use crate::span::Span;
11use crate::token::Token;
12
13pub fn parse(source: &str) -> ParseResult<SourceFile> {
18 let tokens = lexer::lex(source);
19 let mut parser = Parser::new(source, tokens);
20 parser.parse_file()
21}
22
23struct Parser<'src> {
24 source: &'src str,
25 tokens: Vec<SpannedToken>,
26 pos: usize,
27 depth: usize,
28}
29
30const MAX_DEPTH: usize = 256;
31
32impl<'src> Parser<'src> {
33 const fn new(source: &'src str, tokens: Vec<SpannedToken>) -> Self {
34 Self {
35 source,
36 tokens,
37 pos: 0,
38 depth: 0,
39 }
40 }
41
42 fn enter_recursion(&mut self) -> ParseResult<()> {
43 self.depth += 1;
44 if self.depth > MAX_DEPTH {
45 Err(ParseError::custom(
46 "maximum nesting depth exceeded",
47 self.peek_span(),
48 ))
49 } else {
50 Ok(())
51 }
52 }
53
54 const fn leave_recursion(&mut self) {
55 self.depth = self.depth.saturating_sub(1);
56 }
57
58 fn peek(&self) -> Option<&Token> {
61 self.tokens.get(self.pos).map(|(t, _)| t)
62 }
63
64 fn peek_at(&self, offset: usize) -> Option<&Token> {
65 self.tokens.get(self.pos + offset).map(|(t, _)| t)
66 }
67
68 fn peek_span(&self) -> Span {
69 self.tokens.get(self.pos).map_or_else(
70 || Span::new(self.source.len(), self.source.len()),
71 |(_, s)| *s,
72 )
73 }
74
75 fn advance(&mut self) -> Option<SpannedToken> {
76 if self.pos < self.tokens.len() {
77 let tok = self.tokens[self.pos].clone();
78 self.pos += 1;
79 Some(tok)
80 } else {
81 None
82 }
83 }
84
85 const fn at_end(&self) -> bool {
86 self.pos >= self.tokens.len()
87 }
88
89 fn slice(&self, span: Span) -> &'src str {
90 &self.source[span.start..span.end]
91 }
92
93 fn expect(&mut self, expected: &Token) -> ParseResult<Span> {
94 match self.peek() {
95 Some(tok) if std::mem::discriminant(tok) == std::mem::discriminant(expected) => {
96 let (_, span) = self.advance().unwrap();
97 Ok(span)
98 }
99 Some(_) => {
100 let (tok, span) = self.tokens[self.pos].clone();
101 Err(ParseError::unexpected_token(
102 &tok.to_string(),
103 &expected.to_string(),
104 span,
105 ))
106 }
107 None => Err(ParseError::unexpected_eof(
108 &expected.to_string(),
109 self.source.len(),
110 )),
111 }
112 }
113
114 fn expect_identifier(&mut self) -> ParseResult<(String, Span)> {
115 match self.peek() {
116 Some(Token::Identifier) => {
117 let (_, span) = self.advance().unwrap();
118 Ok((self.slice(span).to_string(), span))
119 }
120 Some(Token::For | Token::Let | Token::Each | Token::Assert | Token::Echo) => {
122 let (tok, span) = self.advance().unwrap();
123 Ok((tok.to_string(), span))
124 }
125 Some(_) => {
126 let (tok, span) = self.tokens[self.pos].clone();
127 Err(ParseError::unexpected_token(
128 &tok.to_string(),
129 "identifier",
130 span,
131 ))
132 }
133 None => Err(ParseError::unexpected_eof("identifier", self.source.len())),
134 }
135 }
136
137 fn eat(&mut self, expected: &Token) -> Option<Span> {
138 if self
139 .peek()
140 .is_some_and(|t| std::mem::discriminant(t) == std::mem::discriminant(expected))
141 {
142 Some(self.advance().unwrap().1)
143 } else {
144 None
145 }
146 }
147
148 fn parse_file(&mut self) -> ParseResult<SourceFile> {
151 let mut statements = Vec::new();
152 while !self.at_end() {
153 statements.push(self.parse_statement()?);
154 }
155 let span = if statements.is_empty() {
156 Span::new(0, 0)
157 } else {
158 statements[0]
159 .span()
160 .merge(statements.last().unwrap().span())
161 };
162 Ok(SourceFile { statements, span })
163 }
164
165 fn parse_statement(&mut self) -> ParseResult<Statement> {
168 self.enter_recursion()?;
169 let result = self.parse_statement_inner();
170 self.leave_recursion();
171 result
172 }
173
174 fn parse_statement_inner(&mut self) -> ParseResult<Statement> {
175 match self.peek() {
176 Some(Token::Semicolon) => {
177 let span = self.advance().unwrap().1;
178 Ok(Statement::Empty { span })
179 }
180 Some(Token::LBrace) => self.parse_block(),
181 Some(Token::Include) => self.parse_include(),
182 Some(Token::Use) => self.parse_use(),
183 Some(Token::Module) => self.parse_module_def(),
184 Some(Token::Function) => self.parse_function_def(),
185 Some(Token::If) => self.parse_if_else(),
186 Some(Token::Identifier) if self.is_assignment_ahead() => self.parse_assignment(),
188 Some(
190 Token::Identifier
191 | Token::For
192 | Token::Let
193 | Token::Assert
194 | Token::Echo
195 | Token::Each
196 | Token::Bang
197 | Token::Hash
198 | Token::Percent
199 | Token::Star,
200 ) => self.parse_module_instantiation(),
201 Some(_) => {
202 let (tok, span) = self.tokens[self.pos].clone();
203 Err(ParseError::unexpected_token(
204 &tok.to_string(),
205 "statement",
206 span,
207 ))
208 }
209 None => Err(ParseError::unexpected_eof("statement", self.source.len())),
210 }
211 }
212
213 fn is_assignment_ahead(&self) -> bool {
214 if self.pos + 1 < self.tokens.len() {
216 matches!(self.tokens[self.pos + 1].0, Token::Assign)
217 && (self.pos + 2 >= self.tokens.len()
218 || !matches!(self.tokens[self.pos + 2].0, Token::Assign))
219 } else {
220 false
221 }
222 }
223
224 fn parse_block(&mut self) -> ParseResult<Statement> {
225 let start = self.expect(&Token::LBrace)?;
226 let mut body = Vec::new();
227 while self.peek() != Some(&Token::RBrace) && !self.at_end() {
228 body.push(self.parse_statement()?);
229 }
230 let end = self.expect(&Token::RBrace)?;
231 Ok(Statement::Block {
232 body,
233 span: start.merge(end),
234 })
235 }
236
237 #[allow(clippy::unnecessary_wraps)]
238 fn parse_include(&mut self) -> ParseResult<Statement> {
239 let (_, span) = self.advance().unwrap(); let path = lexer::extract_include_path(self.slice(span)).to_string();
241 Ok(Statement::Include { path, span })
242 }
243
244 #[allow(clippy::unnecessary_wraps)]
245 fn parse_use(&mut self) -> ParseResult<Statement> {
246 let (_, span) = self.advance().unwrap(); let path = lexer::extract_include_path(self.slice(span)).to_string();
248 Ok(Statement::Use { path, span })
249 }
250
251 fn parse_assignment(&mut self) -> ParseResult<Statement> {
252 let (name, start) = self.expect_identifier()?;
253 self.expect(&Token::Assign)?;
254 let expr = self.parse_expr()?;
255 let end = self.expect(&Token::Semicolon)?;
256 Ok(Statement::Assignment {
257 name,
258 expr,
259 span: start.merge(end),
260 })
261 }
262
263 fn parse_module_def(&mut self) -> ParseResult<Statement> {
264 let start = self.expect(&Token::Module)?;
265 let (name, _) = self.expect_identifier()?;
266 self.expect(&Token::LParen)?;
267 let params = self.parse_parameters()?;
268 self.expect(&Token::RParen)?;
269 let body = self.parse_child_body()?;
270 let span = start.merge(
271 body.last()
272 .map_or_else(|| self.peek_span(), super::ast::Statement::span),
273 );
274 Ok(Statement::ModuleDefinition {
275 name,
276 params,
277 body,
278 span: start.merge(span),
279 })
280 }
281
282 fn parse_function_def(&mut self) -> ParseResult<Statement> {
283 let start = self.expect(&Token::Function)?;
284 let (name, _) = self.expect_identifier()?;
285 self.expect(&Token::LParen)?;
286 let params = self.parse_parameters()?;
287 self.expect(&Token::RParen)?;
288 self.expect(&Token::Assign)?;
289 let body = self.parse_expr()?;
290 let end = self.expect(&Token::Semicolon)?;
291 Ok(Statement::FunctionDefinition {
292 name,
293 params,
294 body,
295 span: start.merge(end),
296 })
297 }
298
299 fn parse_if_else(&mut self) -> ParseResult<Statement> {
300 let start = self.expect(&Token::If)?;
301 self.expect(&Token::LParen)?;
302 let condition = self.parse_expr()?;
303 self.expect(&Token::RParen)?;
304 let then_body = self.parse_child_body()?;
305 let else_body = if self.eat(&Token::Else).is_some() {
306 Some(self.parse_child_body()?)
307 } else {
308 None
309 };
310 let end_span = else_body
311 .as_ref()
312 .and_then(|b| b.last().map(super::ast::Statement::span))
313 .or_else(|| then_body.last().map(super::ast::Statement::span))
314 .unwrap_or(start);
315 Ok(Statement::IfElse {
316 condition,
317 then_body,
318 else_body,
319 span: start.merge(end_span),
320 })
321 }
322
323 fn parse_module_instantiation(&mut self) -> ParseResult<Statement> {
324 let start_span = self.peek_span();
325 let mut modifiers = Modifiers::default();
326
327 loop {
329 match self.peek() {
330 Some(Token::Bang) => {
331 self.advance();
332 modifiers.root = true;
333 }
334 Some(Token::Hash) => {
335 self.advance();
336 modifiers.highlight = true;
337 }
338 Some(Token::Percent) => {
339 self.advance();
340 modifiers.background = true;
341 }
342 Some(Token::Star) if self.is_modifier_star() => {
343 self.advance();
344 modifiers.disable = true;
345 }
346 _ => break,
347 }
348 }
349
350 if self.peek() == Some(&Token::If) {
352 let stmt = self.parse_if_else()?;
353 if modifiers != Modifiers::default()
355 && let Statement::IfElse {
356 condition,
357 then_body,
358 else_body,
359 span,
360 } = stmt
361 {
362 return Ok(Statement::IfElse {
363 condition,
364 then_body,
365 else_body,
366 span: start_span.merge(span),
367 });
368 }
369 return Ok(stmt);
370 }
371
372 let (name, _) = self.expect_identifier()?;
373 self.expect(&Token::LParen)?;
374 let args = self.parse_arguments()?;
375 self.expect(&Token::RParen)?;
376
377 let children = self.parse_child_body()?;
378 let end_span = children
379 .last()
380 .map_or_else(|| self.peek_span(), super::ast::Statement::span);
381
382 Ok(Statement::ModuleInstantiation {
383 name,
384 args,
385 children,
386 modifiers,
387 span: start_span.merge(end_span),
388 })
389 }
390
391 fn is_modifier_star(&self) -> bool {
393 if self.pos + 1 < self.tokens.len() {
394 matches!(
395 self.tokens[self.pos + 1].0,
396 Token::Identifier
397 | Token::For
398 | Token::Let
399 | Token::Assert
400 | Token::Echo
401 | Token::Each
402 | Token::If
403 | Token::Bang
404 | Token::Hash
405 | Token::Percent
406 | Token::Star
407 )
408 } else {
409 false
410 }
411 }
412
413 fn parse_child_body(&mut self) -> ParseResult<Vec<Statement>> {
415 match self.peek() {
416 Some(Token::Semicolon) => {
417 self.advance();
418 Ok(vec![])
419 }
420 Some(Token::LBrace) => {
421 self.advance(); let mut body = Vec::new();
423 while self.peek() != Some(&Token::RBrace) && !self.at_end() {
424 body.push(self.parse_statement()?);
425 }
426 self.expect(&Token::RBrace)?;
427 Ok(body)
428 }
429 _ => {
430 let stmt = self.parse_statement()?;
431 Ok(vec![stmt])
432 }
433 }
434 }
435
436 fn parse_parameters(&mut self) -> ParseResult<Vec<Parameter>> {
439 let mut params = Vec::new();
440 if self.peek() == Some(&Token::RParen) {
441 return Ok(params);
442 }
443 loop {
444 params.push(self.parse_parameter()?);
445 if self.eat(&Token::Comma).is_none() {
446 break;
447 }
448 if self.peek() == Some(&Token::RParen) {
450 break;
451 }
452 }
453 Ok(params)
454 }
455
456 fn parse_parameter(&mut self) -> ParseResult<Parameter> {
457 let (name, span) = self.expect_identifier()?;
458 let default = if self.eat(&Token::Assign).is_some() {
459 Some(self.parse_expr()?)
460 } else {
461 None
462 };
463 let end = default.as_ref().map_or(span, |e| e.span);
464 Ok(Parameter {
465 name,
466 default,
467 span: span.merge(end),
468 })
469 }
470
471 fn parse_arguments(&mut self) -> ParseResult<Vec<Argument>> {
472 let mut args = Vec::new();
473 if self.peek() == Some(&Token::RParen) {
474 return Ok(args);
475 }
476 loop {
477 args.push(self.parse_argument()?);
478 if self.eat(&Token::Comma).is_none() {
479 break;
480 }
481 if self.peek() == Some(&Token::RParen) {
483 break;
484 }
485 }
486 Ok(args)
487 }
488
489 fn parse_argument(&mut self) -> ParseResult<Argument> {
490 if matches!(self.peek(), Some(Token::Identifier)) && self.is_named_arg_ahead() {
492 let (name, start) = self.expect_identifier()?;
493 self.expect(&Token::Assign)?;
494 let value = self.parse_expr()?;
495 let span = start.merge(value.span);
496 return Ok(Argument {
497 name: Some(name),
498 value,
499 span,
500 });
501 }
502 let value = self.parse_expr()?;
503 let span = value.span;
504 Ok(Argument {
505 name: None,
506 value,
507 span,
508 })
509 }
510
511 fn is_named_arg_ahead(&self) -> bool {
512 if self.pos + 1 < self.tokens.len() {
513 matches!(self.tokens[self.pos + 1].0, Token::Assign)
514 && (self.pos + 2 >= self.tokens.len()
515 || !matches!(self.tokens[self.pos + 2].0, Token::Assign))
516 } else {
517 false
518 }
519 }
520
521 fn parse_expr(&mut self) -> ParseResult<Expr> {
524 self.enter_recursion()?;
525 let result = self.parse_expr_inner();
526 self.leave_recursion();
527 result
528 }
529
530 fn parse_expr_inner(&mut self) -> ParseResult<Expr> {
531 match self.peek() {
533 Some(Token::Function) => return self.parse_anonymous_function(),
534 Some(Token::Let) => return self.parse_let_expr(),
535 Some(Token::Assert) => return self.parse_assert_expr(),
536 Some(Token::Echo) => return self.parse_echo_expr(),
537 _ => {}
538 }
539
540 let mut expr = self.parse_ternary()?;
541
542 if self.peek() == Some(&Token::Question) {
544 self.advance();
545 let then_expr = self.parse_expr()?;
546 self.expect(&Token::Colon)?;
547 let else_expr = self.parse_expr()?;
548 let span = expr.span.merge(else_expr.span);
549 expr = Expr::new(
550 ExprKind::Ternary {
551 condition: Box::new(expr),
552 then_expr: Box::new(then_expr),
553 else_expr: Box::new(else_expr),
554 },
555 span,
556 );
557 }
558
559 Ok(expr)
560 }
561
562 fn parse_anonymous_function(&mut self) -> ParseResult<Expr> {
563 let start = self.expect(&Token::Function)?;
564 self.expect(&Token::LParen)?;
565 let params = self.parse_parameters()?;
566 self.expect(&Token::RParen)?;
567 let body = self.parse_expr()?;
568 let span = start.merge(body.span);
569 Ok(Expr::new(
570 ExprKind::AnonymousFunction {
571 params,
572 body: Box::new(body),
573 },
574 span,
575 ))
576 }
577
578 fn parse_let_expr(&mut self) -> ParseResult<Expr> {
579 let start = self.expect(&Token::Let)?;
580 self.expect(&Token::LParen)?;
581 let assignments = self.parse_arguments()?;
582 self.expect(&Token::RParen)?;
583 let body = self.parse_expr()?;
584 let span = start.merge(body.span);
585 Ok(Expr::new(
586 ExprKind::Let {
587 assignments,
588 body: Box::new(body),
589 },
590 span,
591 ))
592 }
593
594 fn parse_assert_expr(&mut self) -> ParseResult<Expr> {
595 let start = self.expect(&Token::Assert)?;
596 self.expect(&Token::LParen)?;
597 let args = self.parse_arguments()?;
598 self.expect(&Token::RParen)?;
599 let body = if !self.at_end()
600 && !matches!(
601 self.peek(),
602 Some(Token::Semicolon | Token::RParen | Token::RBracket | Token::Comma)
603 ) {
604 Some(Box::new(self.parse_expr()?))
605 } else {
606 None
607 };
608 let end = body.as_ref().map_or(start, |b| b.span);
609 Ok(Expr::new(ExprKind::Assert { args, body }, start.merge(end)))
610 }
611
612 fn parse_echo_expr(&mut self) -> ParseResult<Expr> {
613 let start = self.expect(&Token::Echo)?;
614 self.expect(&Token::LParen)?;
615 let args = self.parse_arguments()?;
616 self.expect(&Token::RParen)?;
617 let body = if !self.at_end()
618 && !matches!(
619 self.peek(),
620 Some(Token::Semicolon | Token::RParen | Token::RBracket | Token::Comma)
621 ) {
622 Some(Box::new(self.parse_expr()?))
623 } else {
624 None
625 };
626 let end = body.as_ref().map_or(start, |b| b.span);
627 Ok(Expr::new(ExprKind::Echo { args, body }, start.merge(end)))
628 }
629
630 fn parse_ternary(&mut self) -> ParseResult<Expr> {
647 self.parse_logical_or()
648 }
649
650 fn parse_logical_or(&mut self) -> ParseResult<Expr> {
651 let mut left = self.parse_logical_and()?;
652 while self.peek() == Some(&Token::Or) {
653 self.advance();
654 let right = self.parse_logical_and()?;
655 let span = left.span.merge(right.span);
656 left = Expr::new(
657 ExprKind::BinaryOp {
658 op: BinaryOp::LogicalOr,
659 left: Box::new(left),
660 right: Box::new(right),
661 },
662 span,
663 );
664 }
665 Ok(left)
666 }
667
668 fn parse_logical_and(&mut self) -> ParseResult<Expr> {
669 let mut left = self.parse_equality()?;
670 while self.peek() == Some(&Token::And) {
671 self.advance();
672 let right = self.parse_equality()?;
673 let span = left.span.merge(right.span);
674 left = Expr::new(
675 ExprKind::BinaryOp {
676 op: BinaryOp::LogicalAnd,
677 left: Box::new(left),
678 right: Box::new(right),
679 },
680 span,
681 );
682 }
683 Ok(left)
684 }
685
686 fn parse_equality(&mut self) -> ParseResult<Expr> {
687 let mut left = self.parse_comparison()?;
688 loop {
689 let op = match self.peek() {
690 Some(Token::EqualEqual) => BinaryOp::Equal,
691 Some(Token::NotEqual) => BinaryOp::NotEqual,
692 _ => break,
693 };
694 self.advance();
695 let right = self.parse_comparison()?;
696 let span = left.span.merge(right.span);
697 left = Expr::new(
698 ExprKind::BinaryOp {
699 op,
700 left: Box::new(left),
701 right: Box::new(right),
702 },
703 span,
704 );
705 }
706 Ok(left)
707 }
708
709 fn parse_comparison(&mut self) -> ParseResult<Expr> {
710 let mut left = self.parse_bitwise_or()?;
711 loop {
712 let op = match self.peek() {
713 Some(Token::Less) => BinaryOp::Less,
714 Some(Token::LessEqual) => BinaryOp::LessEqual,
715 Some(Token::Greater) => BinaryOp::Greater,
716 Some(Token::GreaterEqual) => BinaryOp::GreaterEqual,
717 _ => break,
718 };
719 self.advance();
720 let right = self.parse_bitwise_or()?;
721 let span = left.span.merge(right.span);
722 left = Expr::new(
723 ExprKind::BinaryOp {
724 op,
725 left: Box::new(left),
726 right: Box::new(right),
727 },
728 span,
729 );
730 }
731 Ok(left)
732 }
733
734 fn parse_bitwise_or(&mut self) -> ParseResult<Expr> {
735 let mut left = self.parse_bitwise_and()?;
736 while self.peek() == Some(&Token::Pipe) {
737 self.advance();
738 let right = self.parse_bitwise_and()?;
739 let span = left.span.merge(right.span);
740 left = Expr::new(
741 ExprKind::BinaryOp {
742 op: BinaryOp::BitwiseOr,
743 left: Box::new(left),
744 right: Box::new(right),
745 },
746 span,
747 );
748 }
749 Ok(left)
750 }
751
752 fn parse_bitwise_and(&mut self) -> ParseResult<Expr> {
753 let mut left = self.parse_shift()?;
754 while self.peek() == Some(&Token::Ampersand) {
755 self.advance();
756 let right = self.parse_shift()?;
757 let span = left.span.merge(right.span);
758 left = Expr::new(
759 ExprKind::BinaryOp {
760 op: BinaryOp::BitwiseAnd,
761 left: Box::new(left),
762 right: Box::new(right),
763 },
764 span,
765 );
766 }
767 Ok(left)
768 }
769
770 fn parse_shift(&mut self) -> ParseResult<Expr> {
771 let mut left = self.parse_addition()?;
772 loop {
773 let op = match self.peek() {
774 Some(Token::ShiftLeft) => BinaryOp::ShiftLeft,
775 Some(Token::ShiftRight) => BinaryOp::ShiftRight,
776 _ => break,
777 };
778 self.advance();
779 let right = self.parse_addition()?;
780 let span = left.span.merge(right.span);
781 left = Expr::new(
782 ExprKind::BinaryOp {
783 op,
784 left: Box::new(left),
785 right: Box::new(right),
786 },
787 span,
788 );
789 }
790 Ok(left)
791 }
792
793 fn parse_addition(&mut self) -> ParseResult<Expr> {
794 let mut left = self.parse_multiplication()?;
795 loop {
796 let op = match self.peek() {
797 Some(Token::Plus) => BinaryOp::Add,
798 Some(Token::Minus) => BinaryOp::Subtract,
799 _ => break,
800 };
801 self.advance();
802 let right = self.parse_multiplication()?;
803 let span = left.span.merge(right.span);
804 left = Expr::new(
805 ExprKind::BinaryOp {
806 op,
807 left: Box::new(left),
808 right: Box::new(right),
809 },
810 span,
811 );
812 }
813 Ok(left)
814 }
815
816 fn parse_multiplication(&mut self) -> ParseResult<Expr> {
817 let mut left = self.parse_unary()?;
818 loop {
819 let op = match self.peek() {
820 Some(Token::Star) => BinaryOp::Multiply,
821 Some(Token::Slash) => BinaryOp::Divide,
822 Some(Token::Percent) => BinaryOp::Modulo,
823 _ => break,
824 };
825 self.advance();
826 let right = self.parse_unary()?;
827 let span = left.span.merge(right.span);
828 left = Expr::new(
829 ExprKind::BinaryOp {
830 op,
831 left: Box::new(left),
832 right: Box::new(right),
833 },
834 span,
835 );
836 }
837 Ok(left)
838 }
839
840 fn parse_unary(&mut self) -> ParseResult<Expr> {
841 match self.peek() {
842 Some(Token::Minus) => {
843 let start = self.advance().unwrap().1;
844 let operand = self.parse_unary()?;
845 if let ExprKind::Number(n) = operand.kind {
847 return Ok(Expr::new(ExprKind::Number(-n), start.merge(operand.span)));
848 }
849 let span = start.merge(operand.span);
850 Ok(Expr::new(
851 ExprKind::UnaryOp {
852 op: UnaryOp::Negate,
853 operand: Box::new(operand),
854 },
855 span,
856 ))
857 }
858 Some(Token::Plus) => {
859 self.advance();
860 self.parse_unary()
861 }
862 Some(Token::Bang) => {
863 let start = self.advance().unwrap().1;
864 let operand = self.parse_unary()?;
865 let span = start.merge(operand.span);
866 Ok(Expr::new(
867 ExprKind::UnaryOp {
868 op: UnaryOp::Not,
869 operand: Box::new(operand),
870 },
871 span,
872 ))
873 }
874 Some(Token::Tilde) => {
875 let start = self.advance().unwrap().1;
876 let operand = self.parse_unary()?;
877 let span = start.merge(operand.span);
878 Ok(Expr::new(
879 ExprKind::UnaryOp {
880 op: UnaryOp::BinaryNot,
881 operand: Box::new(operand),
882 },
883 span,
884 ))
885 }
886 _ => self.parse_exponent(),
887 }
888 }
889
890 fn parse_exponent(&mut self) -> ParseResult<Expr> {
891 let left = self.parse_postfix()?;
892 if self.peek() == Some(&Token::Caret) {
893 self.advance();
894 let right = self.parse_unary()?;
896 let span = left.span.merge(right.span);
897 Ok(Expr::new(
898 ExprKind::BinaryOp {
899 op: BinaryOp::Exponent,
900 left: Box::new(left),
901 right: Box::new(right),
902 },
903 span,
904 ))
905 } else {
906 Ok(left)
907 }
908 }
909
910 fn parse_postfix(&mut self) -> ParseResult<Expr> {
911 let mut expr = self.parse_primary()?;
912 loop {
913 match self.peek() {
914 Some(Token::LParen) => {
915 self.advance();
916 let args = self.parse_arguments()?;
917 let end = self.expect(&Token::RParen)?;
918 let span = expr.span.merge(end);
919 expr = Expr::new(
920 ExprKind::FunctionCall {
921 callee: Box::new(expr),
922 args,
923 },
924 span,
925 );
926 }
927 Some(Token::LBracket) => {
928 self.advance();
929 let index = self.parse_expr()?;
930 let end = self.expect(&Token::RBracket)?;
931 let span = expr.span.merge(end);
932 expr = Expr::new(
933 ExprKind::Index {
934 object: Box::new(expr),
935 index: Box::new(index),
936 },
937 span,
938 );
939 }
940 Some(Token::Dot) => {
941 self.advance();
942 let (member, end) = self.expect_identifier()?;
943 let span = expr.span.merge(end);
944 expr = Expr::new(
945 ExprKind::MemberAccess {
946 object: Box::new(expr),
947 member,
948 },
949 span,
950 );
951 }
952 _ => break,
953 }
954 }
955 Ok(expr)
956 }
957
958 fn parse_primary(&mut self) -> ParseResult<Expr> {
959 match self.peek() {
960 Some(Token::Number(_)) => {
961 let (tok, span) = self.advance().unwrap();
962 if let Token::Number(n) = tok {
963 Ok(Expr::new(ExprKind::Number(n), span))
964 } else {
965 unreachable!()
966 }
967 }
968 Some(Token::String(_)) => {
969 let (tok, span) = self.advance().unwrap();
970 if let Token::String(s) = tok {
971 Ok(Expr::new(ExprKind::String(s), span))
972 } else {
973 unreachable!()
974 }
975 }
976 Some(Token::True) => {
977 let span = self.advance().unwrap().1;
978 Ok(Expr::new(ExprKind::BoolTrue, span))
979 }
980 Some(Token::False) => {
981 let span = self.advance().unwrap().1;
982 Ok(Expr::new(ExprKind::BoolFalse, span))
983 }
984 Some(Token::Undef) => {
985 let span = self.advance().unwrap().1;
986 Ok(Expr::new(ExprKind::Undef, span))
987 }
988 Some(Token::Identifier) => {
989 let (_, span) = self.advance().unwrap();
990 let name = self.slice(span).to_string();
991 Ok(Expr::new(ExprKind::Identifier(name), span))
992 }
993 Some(Token::LParen) => {
994 self.advance();
995 let expr = self.parse_expr()?;
996 self.expect(&Token::RParen)?;
997 Ok(expr)
998 }
999 Some(Token::LBracket) => self.parse_vector_or_range(),
1000 Some(_) => {
1001 let (tok, span) = self.tokens[self.pos].clone();
1002 Err(ParseError::unexpected_token(
1003 &tok.to_string(),
1004 "expression",
1005 span,
1006 ))
1007 }
1008 None => Err(ParseError::unexpected_eof("expression", self.source.len())),
1009 }
1010 }
1011
1012 fn parse_vector_or_range(&mut self) -> ParseResult<Expr> {
1013 let start = self.expect(&Token::LBracket)?;
1014
1015 if self.peek() == Some(&Token::RBracket) {
1017 let end = self.advance().unwrap().1;
1018 return Ok(Expr::new(ExprKind::Vector(vec![]), start.merge(end)));
1019 }
1020
1021 if matches!(
1023 self.peek(),
1024 Some(Token::For | Token::Let | Token::If | Token::Each)
1025 ) {
1026 let lc = self.parse_list_comprehension_element()?;
1027 let mut elements = vec![lc];
1028 while self.eat(&Token::Comma).is_some() {
1029 if self.peek() == Some(&Token::RBracket) {
1030 break;
1031 }
1032 if matches!(
1033 self.peek(),
1034 Some(Token::For | Token::Let | Token::If | Token::Each)
1035 ) {
1036 elements.push(self.parse_list_comprehension_element()?);
1037 } else {
1038 elements.push(self.parse_expr()?);
1039 }
1040 }
1041 let end = self.expect(&Token::RBracket)?;
1042 return Ok(Expr::new(ExprKind::Vector(elements), start.merge(end)));
1043 }
1044
1045 let first = self.parse_expr()?;
1047
1048 if self.peek() == Some(&Token::Colon) {
1050 self.advance();
1051 let second = self.parse_expr()?;
1052 if self.peek() == Some(&Token::Colon) {
1053 self.advance();
1055 let third = self.parse_expr()?;
1056 let end = self.expect(&Token::RBracket)?;
1057 return Ok(Expr::new(
1058 ExprKind::Range {
1059 start: Box::new(first),
1060 step: Some(Box::new(second)),
1061 end: Box::new(third),
1062 },
1063 start.merge(end),
1064 ));
1065 }
1066 let end = self.expect(&Token::RBracket)?;
1068 return Ok(Expr::new(
1069 ExprKind::Range {
1070 start: Box::new(first),
1071 step: None,
1072 end: Box::new(second),
1073 },
1074 start.merge(end),
1075 ));
1076 }
1077
1078 let mut elements = vec![first];
1080 while self.eat(&Token::Comma).is_some() {
1081 if self.peek() == Some(&Token::RBracket) {
1083 break;
1084 }
1085 if matches!(
1087 self.peek(),
1088 Some(Token::For | Token::Let | Token::If | Token::Each)
1089 ) {
1090 elements.push(self.parse_list_comprehension_element()?);
1091 } else {
1092 elements.push(self.parse_expr()?);
1093 }
1094 }
1095 let end = self.expect(&Token::RBracket)?;
1096 Ok(Expr::new(ExprKind::Vector(elements), start.merge(end)))
1097 }
1098
1099 fn parse_list_comprehension_element(&mut self) -> ParseResult<Expr> {
1100 match self.peek() {
1101 Some(Token::For) => {
1102 let start = self.advance().unwrap().1;
1103 self.expect(&Token::LParen)?;
1104 let args = self.parse_arguments()?;
1105
1106 if self.peek() == Some(&Token::Semicolon) {
1108 self.advance();
1109 let condition = self.parse_expr()?;
1110 self.expect(&Token::Semicolon)?;
1111 let update = self.parse_arguments()?;
1112 self.expect(&Token::RParen)?;
1113 let body = self.parse_lc_body()?;
1114 let span = start.merge(body.span);
1115 return Ok(Expr::new(
1116 ExprKind::LcForC {
1117 init: args,
1118 condition: Box::new(condition),
1119 update,
1120 body: Box::new(body),
1121 },
1122 span,
1123 ));
1124 }
1125
1126 self.expect(&Token::RParen)?;
1127 let body = self.parse_lc_body()?;
1128 let span = start.merge(body.span);
1129 Ok(Expr::new(
1130 ExprKind::LcFor {
1131 assignments: args,
1132 body: Box::new(body),
1133 },
1134 span,
1135 ))
1136 }
1137 Some(Token::Let) => {
1138 let start = self.advance().unwrap().1;
1139 self.expect(&Token::LParen)?;
1140 let assignments = self.parse_arguments()?;
1141 self.expect(&Token::RParen)?;
1142 let body = self.parse_lc_body()?;
1143 let span = start.merge(body.span);
1144 Ok(Expr::new(
1145 ExprKind::LcLet {
1146 assignments,
1147 body: Box::new(body),
1148 },
1149 span,
1150 ))
1151 }
1152 Some(Token::If) => {
1153 let start = self.advance().unwrap().1;
1154 self.expect(&Token::LParen)?;
1155 let condition = self.parse_expr()?;
1156 self.expect(&Token::RParen)?;
1157 let then_expr = self.parse_lc_body()?;
1158 let else_expr = if self.eat(&Token::Else).is_some() {
1159 Some(Box::new(self.parse_lc_body()?))
1160 } else {
1161 None
1162 };
1163 let end = else_expr.as_ref().map_or(then_expr.span, |e| e.span);
1164 Ok(Expr::new(
1165 ExprKind::LcIf {
1166 condition: Box::new(condition),
1167 then_expr: Box::new(then_expr),
1168 else_expr,
1169 },
1170 start.merge(end),
1171 ))
1172 }
1173 Some(Token::Each) => {
1174 let start = self.advance().unwrap().1;
1175 let body = self.parse_lc_body()?;
1176 let span = start.merge(body.span);
1177 Ok(Expr::new(
1178 ExprKind::LcEach {
1179 body: Box::new(body),
1180 },
1181 span,
1182 ))
1183 }
1184 _ => self.parse_expr(),
1185 }
1186 }
1187
1188 fn parse_lc_body(&mut self) -> ParseResult<Expr> {
1190 if matches!(
1191 self.peek(),
1192 Some(Token::For | Token::Let | Token::If | Token::Each)
1193 ) {
1194 self.parse_list_comprehension_element()
1195 } else if self.peek() == Some(&Token::LParen)
1196 && matches!(
1197 self.peek_at(1),
1198 Some(Token::For | Token::Let | Token::If | Token::Each)
1199 )
1200 {
1201 self.advance();
1203 let inner = self.parse_list_comprehension_element()?;
1204 self.expect(&Token::RParen)?;
1205 Ok(inner)
1206 } else {
1207 self.parse_expr()
1208 }
1209 }
1210}
1211
1212#[cfg(test)]
1213mod tests {
1214 use super::*;
1215
1216 fn parse_ok(source: &str) -> SourceFile {
1217 parse(source).unwrap_or_else(|e| panic!("parse error for `{source}`: {e}"))
1218 }
1219
1220 fn parse_err(source: &str) -> ParseError {
1221 parse(source).unwrap_err()
1222 }
1223
1224 #[test]
1225 fn test_empty() {
1226 let file = parse_ok("");
1227 assert!(file.statements.is_empty());
1228 }
1229
1230 #[test]
1231 fn test_assignment() {
1232 let file = parse_ok("x = 42;");
1233 assert_eq!(file.statements.len(), 1);
1234 match &file.statements[0] {
1235 Statement::Assignment { name, expr, .. } => {
1236 assert_eq!(name, "x");
1237 assert!(
1238 matches!(expr.kind, ExprKind::Number(n) if (n - 42.0).abs() < f64::EPSILON)
1239 );
1240 }
1241 other => panic!("expected assignment, got {other:?}"),
1242 }
1243 }
1244
1245 #[test]
1246 fn test_module_instantiation() {
1247 let file = parse_ok("cube(10);");
1248 assert_eq!(file.statements.len(), 1);
1249 match &file.statements[0] {
1250 Statement::ModuleInstantiation { name, args, .. } => {
1251 assert_eq!(name, "cube");
1252 assert_eq!(args.len(), 1);
1253 }
1254 other => panic!("expected module instantiation, got {other:?}"),
1255 }
1256 }
1257
1258 #[test]
1259 fn test_module_with_children() {
1260 let file = parse_ok("translate([1,2,3]) { cube(5); sphere(3); }");
1261 match &file.statements[0] {
1262 Statement::ModuleInstantiation { name, children, .. } => {
1263 assert_eq!(name, "translate");
1264 assert_eq!(children.len(), 2);
1265 }
1266 other => panic!("expected module instantiation, got {other:?}"),
1267 }
1268 }
1269
1270 #[test]
1271 fn test_module_definition() {
1272 let file = parse_ok("module box(size = 10, h) { cube(size); }");
1273 match &file.statements[0] {
1274 Statement::ModuleDefinition {
1275 name, params, body, ..
1276 } => {
1277 assert_eq!(name, "box");
1278 assert_eq!(params.len(), 2);
1279 assert_eq!(params[0].name, "size");
1280 assert!(params[0].default.is_some());
1281 assert_eq!(params[1].name, "h");
1282 assert!(params[1].default.is_none());
1283 assert_eq!(body.len(), 1);
1284 }
1285 other => panic!("expected module def, got {other:?}"),
1286 }
1287 }
1288
1289 #[test]
1290 fn test_function_definition() {
1291 let file = parse_ok("function add(a, b) = a + b;");
1292 match &file.statements[0] {
1293 Statement::FunctionDefinition {
1294 name, params, body, ..
1295 } => {
1296 assert_eq!(name, "add");
1297 assert_eq!(params.len(), 2);
1298 assert!(matches!(
1299 body.kind,
1300 ExprKind::BinaryOp {
1301 op: BinaryOp::Add,
1302 ..
1303 }
1304 ));
1305 }
1306 other => panic!("expected function def, got {other:?}"),
1307 }
1308 }
1309
1310 #[test]
1311 fn test_if_else() {
1312 let file = parse_ok("if (x > 0) cube(x); else sphere(1);");
1313 match &file.statements[0] {
1314 Statement::IfElse {
1315 then_body,
1316 else_body,
1317 ..
1318 } => {
1319 assert_eq!(then_body.len(), 1);
1320 assert!(else_body.is_some());
1321 assert_eq!(else_body.as_ref().unwrap().len(), 1);
1322 }
1323 other => panic!("expected if/else, got {other:?}"),
1324 }
1325 }
1326
1327 #[test]
1328 fn test_modifiers() {
1329 let file = parse_ok("!#cube(10);");
1330 match &file.statements[0] {
1331 Statement::ModuleInstantiation { modifiers, .. } => {
1332 assert!(modifiers.root);
1333 assert!(modifiers.highlight);
1334 assert!(!modifiers.background);
1335 assert!(!modifiers.disable);
1336 }
1337 other => panic!("expected module instantiation, got {other:?}"),
1338 }
1339 }
1340
1341 #[test]
1342 fn test_vector() {
1343 let file = parse_ok("x = [1, 2, 3];");
1344 match &file.statements[0] {
1345 Statement::Assignment { expr, .. } => {
1346 assert!(matches!(expr.kind, ExprKind::Vector(ref v) if v.len() == 3));
1347 }
1348 other => panic!("expected assignment, got {other:?}"),
1349 }
1350 }
1351
1352 #[test]
1353 fn test_range() {
1354 let file = parse_ok("x = [0:10];");
1355 match &file.statements[0] {
1356 Statement::Assignment { expr, .. } => {
1357 assert!(matches!(expr.kind, ExprKind::Range { step: None, .. }));
1358 }
1359 other => panic!("expected assignment, got {other:?}"),
1360 }
1361 }
1362
1363 #[test]
1364 fn test_range_with_step() {
1365 let file = parse_ok("x = [0:2:10];");
1366 match &file.statements[0] {
1367 Statement::Assignment { expr, .. } => {
1368 assert!(matches!(expr.kind, ExprKind::Range { step: Some(_), .. }));
1369 }
1370 other => panic!("expected assignment, got {other:?}"),
1371 }
1372 }
1373
1374 #[test]
1375 fn test_include_use() {
1376 let file = parse_ok("include <lib/base.scad>\nuse <utils.scad>");
1377 assert_eq!(file.statements.len(), 2);
1378 match &file.statements[0] {
1379 Statement::Include { path, .. } => assert_eq!(path, "lib/base.scad"),
1380 other => panic!("expected include, got {other:?}"),
1381 }
1382 match &file.statements[1] {
1383 Statement::Use { path, .. } => assert_eq!(path, "utils.scad"),
1384 other => panic!("expected use, got {other:?}"),
1385 }
1386 }
1387
1388 #[test]
1389 fn test_operator_precedence() {
1390 let file = parse_ok("x = 1 + 2 * 3;");
1391 match &file.statements[0] {
1392 Statement::Assignment { expr, .. } => {
1393 match &expr.kind {
1395 ExprKind::BinaryOp {
1396 op: BinaryOp::Add,
1397 right,
1398 ..
1399 } => {
1400 assert!(matches!(
1401 right.kind,
1402 ExprKind::BinaryOp {
1403 op: BinaryOp::Multiply,
1404 ..
1405 }
1406 ));
1407 }
1408 other => panic!("expected Add, got {other:?}"),
1409 }
1410 }
1411 other => panic!("expected assignment, got {other:?}"),
1412 }
1413 }
1414
1415 #[test]
1416 fn test_ternary() {
1417 let file = parse_ok("x = a ? b : c;");
1418 match &file.statements[0] {
1419 Statement::Assignment { expr, .. } => {
1420 assert!(matches!(expr.kind, ExprKind::Ternary { .. }));
1421 }
1422 other => panic!("expected assignment, got {other:?}"),
1423 }
1424 }
1425
1426 #[test]
1427 fn test_anonymous_function() {
1428 let file = parse_ok("f = function(x) x * 2;");
1429 match &file.statements[0] {
1430 Statement::Assignment { expr, .. } => {
1431 assert!(matches!(expr.kind, ExprKind::AnonymousFunction { .. }));
1432 }
1433 other => panic!("expected assignment, got {other:?}"),
1434 }
1435 }
1436
1437 #[test]
1438 fn test_list_comprehension() {
1439 let file = parse_ok("x = [for (i = [0:10]) i * 2];");
1440 assert_eq!(file.statements.len(), 1);
1441 }
1442
1443 #[test]
1444 fn test_nested_modules() {
1445 let file = parse_ok("rotate([0, 0, 45]) translate([10, 0, 0]) cube(5);");
1446 assert_eq!(file.statements.len(), 1);
1447 match &file.statements[0] {
1448 Statement::ModuleInstantiation { name, children, .. } => {
1449 assert_eq!(name, "rotate");
1450 assert_eq!(children.len(), 1);
1451 }
1452 other => panic!("expected module instantiation, got {other:?}"),
1453 }
1454 }
1455
1456 #[test]
1457 fn test_complex_program() {
1458 let source = r"
1459 // A parametric box
1460 module rounded_box(size = [10, 10, 10], r = 1) {
1461 if (r > 0) {
1462 translate([r, r, 0])
1463 cube(size - [2*r, 2*r, 0]);
1464 } else {
1465 cube(size);
1466 }
1467 }
1468
1469 function area(w, h) = w * h;
1470
1471 x = area(10, 20);
1472 rounded_box(size = [x, 30, 5], r = 2);
1473 ";
1474 let file = parse_ok(source);
1475 assert_eq!(file.statements.len(), 4);
1476 }
1477
1478 #[test]
1479 fn test_error_missing_semicolon() {
1480 let err = parse_err("x = 42");
1481 assert!(matches!(err, ParseError::UnexpectedEof { .. }));
1482 }
1483
1484 #[test]
1485 fn test_named_arguments() {
1486 let file = parse_ok("cube(size = 10, center = true);");
1487 match &file.statements[0] {
1488 Statement::ModuleInstantiation { args, .. } => {
1489 assert_eq!(args.len(), 2);
1490 assert_eq!(args[0].name.as_deref(), Some("size"));
1491 assert_eq!(args[1].name.as_deref(), Some("center"));
1492 }
1493 other => panic!("expected module instantiation, got {other:?}"),
1494 }
1495 }
1496
1497 #[test]
1498 fn test_member_access() {
1499 let file = parse_ok("x = v.x;");
1500 match &file.statements[0] {
1501 Statement::Assignment { expr, .. } => {
1502 assert!(
1503 matches!(expr.kind, ExprKind::MemberAccess { ref member, .. } if member == "x")
1504 );
1505 }
1506 other => panic!("expected assignment, got {other:?}"),
1507 }
1508 }
1509
1510 #[test]
1511 fn test_index_access() {
1512 let file = parse_ok("x = v[0];");
1513 match &file.statements[0] {
1514 Statement::Assignment { expr, .. } => {
1515 assert!(matches!(expr.kind, ExprKind::Index { .. }));
1516 }
1517 other => panic!("expected assignment, got {other:?}"),
1518 }
1519 }
1520
1521 #[test]
1522 fn test_let_expression() {
1523 let file = parse_ok("x = let(a = 1, b = 2) a + b;");
1524 match &file.statements[0] {
1525 Statement::Assignment { expr, .. } => {
1526 assert!(matches!(expr.kind, ExprKind::Let { .. }));
1527 }
1528 other => panic!("expected assignment, got {other:?}"),
1529 }
1530 }
1531}