1use crate::ast::*;
16use crate::errors::{AddSpan, CarmenError, ErrorSource, Result, Span};
17use crate::lexer::{Token, TokenType};
18
19#[derive(Debug, PartialEq)]
24enum TokenCategory {
25 ValidIdentifier,
27 Reserved(&'static str), Invalid,
31}
32
33fn capitalize_first(s: &str) -> String {
34 let mut chars = s.chars();
35 match chars.next() {
36 None => String::new(),
37 Some(first) => first.to_uppercase().collect::<String>() + chars.as_str(),
38 }
39}
40
41fn pluralize_symbol_type(symbol_type: &str) -> String {
43 match symbol_type {
44 "pitch" => "Pitches".to_string(),
45 "duration" => "Durations".to_string(),
46 "dynamic" => "Dynamics".to_string(),
47 "attribute" => "Attributes".to_string(),
48 "keyword" => "Keywords".to_string(),
49 _ => format!("{}s", capitalize_first(symbol_type)),
50 }
51}
52
53#[derive(Debug, Clone)]
59enum CommentContext {
60 Leading(Span),
62 Trailing(Span),
64 Between(usize),
66 Standalone,
68}
69
70pub struct Parser {
75 tokens: Vec<Token>,
77 current: usize,
79 comments: Vec<CommentInfo>,
81}
82
83impl Parser {
84 pub fn new(tokens: Vec<Token>) -> Self {
86 Self {
87 tokens,
88 current: 0,
89 comments: Vec::new(),
90 }
91 }
92
93 fn collect_comments(&mut self, context: CommentContext) -> Vec<CommentInfo> {
98 let mut collected = Vec::new();
99
100 while !self.is_at_end() {
101 if let TokenType::Comment(content) = &self.current_token().token_type {
102 let comment_span = self.current_token().span;
103 let mut comment = CommentInfo::new(content.clone(), comment_span);
104
105 comment.position = match context {
106 CommentContext::Leading(ref target_span) => {
107 if comment.is_same_line(target_span) {
108 CommentPosition::Trailing
109 } else {
110 CommentPosition::Leading
111 }
112 }
113 CommentContext::Trailing(ref target_span) => {
114 comment.associated_span = Some(*target_span);
115 if comment.is_same_line(target_span) {
116 CommentPosition::Trailing
117 } else {
118 CommentPosition::Standalone
119 }
120 }
121 CommentContext::Between(index) => CommentPosition::Between(index),
122 CommentContext::Standalone => CommentPosition::Standalone,
123 };
124
125 collected.push(comment.clone());
126 self.comments.push(comment);
127 self.advance();
128 } else {
129 break;
130 }
131 }
132 collected
133 }
134
135 fn skip_comments(&mut self) {
139 self.collect_comments(CommentContext::Standalone);
140 }
141
142 fn collect_leading_comments(&mut self, target_span: &Span) -> Vec<CommentInfo> {
143 self.collect_comments(CommentContext::Leading(*target_span))
144 }
145
146 fn collect_trailing_comments(&mut self, target_span: &Span) -> Vec<CommentInfo> {
147 self.collect_comments(CommentContext::Trailing(*target_span))
148 }
149
150 fn collect_between_comments(&mut self, element_index: usize) -> Vec<CommentInfo> {
151 self.collect_comments(CommentContext::Between(element_index))
152 }
153
154 fn current_token(&self) -> &Token {
155 &self.tokens[self.current]
156 }
157
158 fn previous_token(&self) -> &Token {
159 &self.tokens[self.current - 1]
160 }
161
162 fn is_at_end(&self) -> bool {
163 matches!(self.current_token().token_type, TokenType::Eof)
164 }
165
166 fn advance(&mut self) -> &Token {
167 if !self.is_at_end() {
168 self.current += 1;
169 }
170 self.previous_token()
171 }
172
173 fn check(&self, token_type: &TokenType) -> bool {
174 if self.is_at_end() {
175 false
176 } else {
177 std::mem::discriminant(&self.current_token().token_type)
178 == std::mem::discriminant(token_type)
179 }
180 }
181
182 fn match_token(&mut self, token_type: &TokenType) -> bool {
183 if self.check(token_type) {
184 self.advance();
185 true
186 } else {
187 false
188 }
189 }
190
191 fn categorize_token(&self, token_type: &TokenType) -> TokenCategory {
196 match token_type {
197 TokenType::Identifier(_) => TokenCategory::ValidIdentifier,
198 TokenType::Pitch(_) => TokenCategory::Reserved("pitch"),
199 TokenType::Duration(_) => TokenCategory::Reserved("duration"),
200 TokenType::Dynamic(_) => TokenCategory::Reserved("dynamic"),
201 TokenType::Attribute(_) => TokenCategory::Reserved("attribute"),
202 TokenType::Let
203 | TokenType::Def
204 | TokenType::If
205 | TokenType::Else
206 | TokenType::For
207 | TokenType::While
208 | TokenType::In
209 | TokenType::Return
210 | TokenType::Part
211 | TokenType::Staff
212 | TokenType::Timeline
213 | TokenType::And
214 | TokenType::Or
215 | TokenType::Not
216 | TokenType::True
217 | TokenType::False => TokenCategory::Reserved("keyword"),
218 _ => TokenCategory::Invalid,
219 }
220 }
221
222 fn extract_token_value(&self, token_type: &TokenType) -> String {
224 match token_type {
225 TokenType::Pitch(s)
226 | TokenType::Duration(s)
227 | TokenType::Dynamic(s)
228 | TokenType::Attribute(s)
229 | TokenType::Identifier(s) => s.clone(),
230 TokenType::Let => "let".to_string(),
231 TokenType::Def => "def".to_string(),
232 TokenType::If => "if".to_string(),
233 TokenType::Else => "else".to_string(),
234 TokenType::For => "for".to_string(),
235 TokenType::While => "while".to_string(),
236 TokenType::In => "in".to_string(),
237 TokenType::Return => "return".to_string(),
238 TokenType::Part => "part".to_string(),
239 TokenType::Staff => "staff".to_string(),
240 TokenType::Timeline => "timeline".to_string(),
241 TokenType::And => "and".to_string(),
242 TokenType::Or => "or".to_string(),
243 TokenType::Not => "not".to_string(),
244 TokenType::True => "true".to_string(),
245 TokenType::False => "false".to_string(),
246 _ => "unknown".to_string(),
247 }
248 }
249
250 fn expect_identifier(&self, context: &str) -> Result<String> {
256 let token = self.current_token();
257
258 match self.categorize_token(&token.token_type) {
259 TokenCategory::ValidIdentifier => {
260 if let TokenType::Identifier(name) = &token.token_type {
261 Ok(name.clone())
262 } else {
263 unreachable!("ValidIdentifier should only be returned for Identifier tokens")
264 }
265 }
266 TokenCategory::Reserved(symbol_type) => {
267 let symbol_value = self.extract_token_value(&token.token_type);
268 Err(ErrorSource::Parsing(format!(
269 "Cannot use {} '{}' as {}. {} are reserved.",
270 symbol_type,
271 symbol_value,
272 context,
273 pluralize_symbol_type(symbol_type)
274 ))
275 .with_span(token.span))
276 }
277 TokenCategory::Invalid => Err(self.error(&format!("Expected {context}"))),
278 }
279 }
280
281 fn error(&self, message: &str) -> CarmenError {
282 ErrorSource::Parsing(message.to_string()).with_span(self.current_token().span)
283 }
284
285 fn consume(&mut self, token_type: TokenType, message: &str) -> Result<()> {
286 if self.check(&token_type) {
287 self.advance();
288 Ok(())
289 } else {
290 Err(self.error(message))
291 }
292 }
293
294 fn parse_identifier_in_musical_context(&mut self, context: &str) -> Result<SpannedExpression> {
300 let token = self.current_token().clone();
301
302 if let TokenType::Identifier(name) = &token.token_type {
303 if context == "dynamic_or_attribute" && Literal::is_dynamic(name) {
305 self.advance();
306 return Ok(Spanned {
307 node: Expression::Literal(Literal::Dynamic(name.clone())),
308 span: token.span,
309 });
310 }
311
312 if context == "dynamic_or_attribute" && Literal::is_attribute(name) {
314 self.advance();
315 return Ok(Spanned {
316 node: Expression::Literal(Literal::Attribute(name.clone())),
317 span: token.span,
318 });
319 }
320
321 if context == "pitch" && self.could_be_pitch_identifier(name) {
323 self.advance();
324 if let Some(pitch) = Literal::parse_pitch(name) {
325 return Ok(Spanned {
326 node: Expression::Literal(pitch),
327 span: token.span,
328 });
329 }
330 }
331 }
332
333 if context == "dynamic_or_attribute" {
336 return Err(
337 ErrorSource::Parsing("Expected dynamic or attribute".to_string())
338 .with_span(token.span),
339 );
340 }
341
342 let name = match &token.token_type {
344 TokenType::Identifier(name) => name.clone(),
345 _ => return Err(self.error(&format!("Expected identifier in {context} context"))),
346 };
347
348 self.advance();
349 Ok(Spanned {
350 node: Expression::Identifier(name),
351 span: token.span,
352 })
353 }
354
355 fn could_be_pitch_identifier(&self, name: &str) -> bool {
360 Literal::parse_pitch(name).is_some()
361 }
362
363 fn could_be_musical_event(&self) -> bool {
368 match &self.current_token().token_type {
369 TokenType::Duration(_) => {
370 if self.current + 1 < self.tokens.len() {
372 match &self.tokens[self.current + 1].token_type {
373 TokenType::Pitch(_) |
374 TokenType::Identifier(_) | TokenType::LeftParen | TokenType::LeftBracket | TokenType::Tilde => true, _ => false,
379 }
380 } else {
381 false
382 }
383 }
384 TokenType::Number(n) if *n == 1.0 => {
385 if self.current + 1 < self.tokens.len() {
387 match &self.tokens[self.current + 1].token_type {
388 TokenType::Pitch(_)
389 | TokenType::Tilde
390 | TokenType::LeftParen
391 | TokenType::LeftBracket => true,
392 TokenType::Identifier(name) => {
393 self.could_be_pitch_identifier(name)
395 }
396 _ => false,
397 }
398 } else {
399 false
400 }
401 }
402 _ => false,
403 }
404 }
405
406 fn grouping_or_tuple(&mut self) -> Result<SpannedExpression> {
407 let start = self.current_token().span.start;
408 self.consume(TokenType::LeftParen, "Expected '('")?;
409
410 self.skip_comments();
411
412 if self.check(&TokenType::RightParen) {
413 self.advance();
414 return Ok(Spanned {
415 node: Expression::Tuple {
416 elements: Vec::new(),
417 },
418 span: Span {
419 start,
420 end: self.previous_token().span.end,
421 },
422 });
423 }
424
425 let mut elements = vec![self.expression()?];
426 self.collect_leading_comments(&elements[0].span);
427
428 if self.match_token(&TokenType::Comma) {
429 self.collect_between_comments(0);
430 while !self.check(&TokenType::RightParen) && !self.is_at_end() {
432 let element = self.expression()?;
433 self.collect_trailing_comments(&element.span);
434 elements.push(element);
435
436 if !self.match_token(&TokenType::Comma) {
437 break;
438 }
439
440 self.collect_between_comments(elements.len() - 1);
441
442 if self.check(&TokenType::RightParen) {
444 break;
445 }
446 }
447
448 self.skip_comments();
449 self.consume(TokenType::RightParen, "Expected ')' after tuple elements")?;
450 Ok(Spanned {
451 node: Expression::Tuple { elements },
452 span: Span {
453 start,
454 end: self.previous_token().span.end,
455 },
456 })
457 } else {
458 self.skip_comments();
459 self.consume(TokenType::RightParen, "Expected ')' after expression")?;
461 Ok(elements.into_iter().next().unwrap())
462 }
463 }
464
465 fn list(&mut self) -> Result<SpannedExpression> {
466 let start = self.current_token().span.start;
467 self.consume(TokenType::LeftBracket, "Expected '['")?;
468
469 let mut elements = Vec::new();
470
471 self.skip_comments(); if !self.check(&TokenType::RightBracket) {
474 loop {
475 let element = self.expression()?;
476 self.collect_trailing_comments(&element.span);
477 elements.push(element);
478 if !self.match_token(&TokenType::Comma) {
479 break;
480 }
481 self.collect_between_comments(elements.len() - 1);
483
484 if self.check(&TokenType::RightBracket) {
486 break;
487 }
488 }
489 }
490
491 self.skip_comments(); self.consume(TokenType::RightBracket, "Expected ']' after list elements")?;
493
494 Ok(Spanned {
495 node: Expression::List { elements },
496 span: Span {
497 start,
498 end: self.previous_token().span.end,
499 },
500 })
501 }
502
503 fn is_pitch_class_number(expr: &SpannedExpression) -> bool {
507 match expr.node {
508 Expression::Literal(Literal::Number(value)) => {
509 (0.0..=11.0).contains(&value) && value.fract() == 0.0
510 }
511 _ => false,
512 }
513 }
514
515 fn extract_pitch_class_number(expr: &SpannedExpression) -> Option<u8> {
516 match expr.node {
517 Expression::Literal(Literal::Number(value)) => {
518 if (0.0..=11.0).contains(&value) && value.fract() == 0.0 {
519 Some(value as u8)
520 } else {
521 None
522 }
523 }
524 _ => None,
525 }
526 }
527
528 fn is_all_pitch_class_numbers(elements: &[SpannedExpression]) -> bool {
532 !elements.is_empty() && elements.iter().all(Self::is_pitch_class_number)
533 }
534
535 fn set_or_block(&mut self) -> Result<SpannedExpression> {
541 let start = self.current_token().span.start;
542 self.consume(TokenType::LeftBrace, "Expected '{'")?;
543
544 self.skip_comments();
545
546 if self.check(&TokenType::RightBrace) {
547 self.advance();
548 return Ok(Spanned {
549 node: Expression::Set {
550 elements: Vec::new(),
551 },
552 span: Span {
553 start,
554 end: self.previous_token().span.end,
555 },
556 });
557 }
558
559 let checkpoint = self.current;
561
562 if self.declaration().is_ok() {
564 self.current = checkpoint; let mut statements = Vec::new();
566
567 while !self.check(&TokenType::RightBrace) && !self.is_at_end() {
568 self.skip_comments(); if self.check(&TokenType::RightBrace) {
570 break;
571 }
572
573 let stmt = self.declaration()?;
574 self.collect_trailing_comments(&stmt.span); statements.push(stmt);
576 }
577
578 self.skip_comments(); self.consume(TokenType::RightBrace, "Expected '}' after block")?;
580
581 Ok(Spanned {
582 node: Expression::Block { statements },
583 span: Span {
584 start,
585 end: self.previous_token().span.end,
586 },
587 })
588 } else {
589 self.current = checkpoint;
591 let mut elements = Vec::new();
592
593 self.skip_comments(); if !self.check(&TokenType::RightBrace) {
595 loop {
596 let expr = self.expression()?;
597 self.collect_trailing_comments(&expr.span);
598 elements.push(expr);
599
600 if !self.match_token(&TokenType::Comma) {
601 break;
602 }
603
604 self.collect_between_comments(elements.len() - 1);
605
606 if self.check(&TokenType::RightBrace) {
608 break;
609 }
610 }
611 }
612
613 self.skip_comments();
614 self.consume(TokenType::RightBrace, "Expected '}' after set elements")?;
615 if Self::is_all_pitch_class_numbers(&elements) {
616 let classes: Vec<u8> = elements
617 .iter()
618 .filter_map(Self::extract_pitch_class_number)
619 .collect();
620
621 Ok(Spanned {
622 node: Expression::PitchClassSet { classes },
623 span: Span {
624 start,
625 end: self.previous_token().span.end,
626 },
627 })
628 } else {
629 Ok(Spanned {
630 node: Expression::Set { elements },
631 span: Span {
632 start,
633 end: self.previous_token().span.end,
634 },
635 })
636 }
637 }
638 }
639
640 fn if_expression(&mut self) -> Result<SpannedExpression> {
641 let start = self.current_token().span.start;
642 self.consume(TokenType::If, "Expected 'if'")?;
643
644 self.consume(TokenType::LeftParen, "Expected '(' after 'if'")?;
645 let condition = self.expression()?;
646 self.consume(TokenType::RightParen, "Expected ')' after if condition")?;
647
648 let then_branch = self.expression()?;
649
650 let else_branch = if self.match_token(&TokenType::Else) {
651 Some(Box::new(self.expression()?))
652 } else {
653 None
654 };
655
656 let end = if let Some(ref else_expr) = else_branch {
657 else_expr.span.end
658 } else {
659 then_branch.span.end
660 };
661
662 Ok(Spanned {
663 node: Expression::If {
664 condition: Box::new(condition),
665 then_branch: Box::new(then_branch),
666 else_branch,
667 },
668 span: Span { start, end },
669 })
670 }
671
672 fn for_expression(&mut self) -> Result<SpannedExpression> {
673 let start = self.current_token().span.start;
674 self.consume(TokenType::For, "Expected 'for'")?;
675
676 self.consume(TokenType::LeftParen, "Expected '(' after 'for'")?;
677
678 let variable = self.expect_identifier("a loop variable")?;
679 self.advance();
680
681 self.consume(TokenType::In, "Expected 'in' after for variable")?;
682 let iterable = self.expression()?;
683 self.consume(TokenType::RightParen, "Expected ')' after for clause")?;
684
685 let body = self.expression()?;
686
687 let end = body.span.end;
688
689 Ok(Spanned {
690 node: Expression::For {
691 variable,
692 iterable: Box::new(iterable),
693 body: Box::new(body),
694 },
695 span: Span { start, end },
696 })
697 }
698
699 fn while_expression(&mut self) -> Result<SpannedExpression> {
700 let start = self.current_token().span.start;
701 self.consume(TokenType::While, "Expected 'while'")?;
702
703 self.consume(TokenType::LeftParen, "Expected '(' after 'while'")?;
704 let condition = self.expression()?;
705 self.consume(TokenType::RightParen, "Expected ')' after while condition")?;
706
707 let body = self.expression()?;
708
709 Ok(Spanned {
710 node: Expression::While {
711 condition: Box::new(condition),
712 body: Box::new(body.clone()),
713 },
714 span: Span {
715 start,
716 end: body.span.end,
717 },
718 })
719 }
720
721 fn part_expression(&mut self) -> Result<SpannedExpression> {
722 let start = self.current_token().span.start;
723 self.consume(TokenType::Part, "Expected 'part'")?;
724
725 let name = if matches!(self.current_token().token_type, TokenType::String(_)) {
726 Some(Box::new(self.expression()?))
727 } else {
728 None
729 };
730
731 let body = self.expression()?;
732
733 Ok(Spanned {
734 node: Expression::Part {
735 name,
736 body: Box::new(body.clone()),
737 },
738 span: Span {
739 start,
740 end: body.span.end,
741 },
742 })
743 }
744
745 fn staff_expression(&mut self) -> Result<SpannedExpression> {
746 let start = self.current_token().span.start;
747 self.consume(TokenType::Staff, "Expected 'staff'")?;
748
749 let number = self.expression()?;
750 let body = self.expression()?;
751
752 Ok(Spanned {
753 node: Expression::Staff {
754 number: Box::new(number),
755 body: Box::new(body.clone()),
756 },
757 span: Span {
758 start,
759 end: body.span.end,
760 },
761 })
762 }
763
764 fn timeline_expression(&mut self) -> Result<SpannedExpression> {
765 let start = self.current_token().span.start;
766 self.consume(TokenType::Timeline, "Expected 'timeline'")?;
767
768 let body = self.expression()?;
769
770 Ok(Spanned {
771 node: Expression::Timeline {
772 body: Box::new(body.clone()),
773 },
774 span: Span {
775 start,
776 end: body.span.end,
777 },
778 })
779 }
780
781 fn movement_expression(&mut self) -> Result<SpannedExpression> {
782 let start = self.current_token().span.start;
783 self.consume(TokenType::Movement, "Expected 'movement'")?;
784
785 let name = if matches!(self.current_token().token_type, TokenType::String(_)) {
786 Some(Box::new(self.expression()?))
787 } else {
788 None
789 };
790
791 let body = self.expression()?;
792
793 Ok(Spanned {
794 node: Expression::Movement {
795 name,
796 body: Box::new(body.clone()),
797 },
798 span: Span {
799 start,
800 end: body.span.end,
801 },
802 })
803 }
804
805 fn score_expression(&mut self) -> Result<SpannedExpression> {
806 let start = self.current_token().span.start;
807 self.consume(TokenType::Score, "Expected 'score'")?;
808
809 let name = if matches!(self.current_token().token_type, TokenType::String(_)) {
810 Some(Box::new(self.expression()?))
811 } else {
812 None
813 };
814
815 let body = self.expression()?;
816
817 let end = body.span.end;
818
819 Ok(Spanned {
820 node: Expression::Score {
821 name,
822 body: Box::new(body),
823 },
824 span: Span { start, end },
825 })
826 }
827
828 fn musical_event(&mut self) -> Result<SpannedExpression> {
830 let start_pos = self.current_token().span.start;
831
832 let duration = match &self.current_token().token_type {
834 TokenType::Duration(d) => {
835 let d = d.clone();
836 let span = self.current_token().span;
837 self.advance();
838 if let Some(duration) = Literal::parse_duration(&d) {
839 Spanned {
840 node: Expression::Literal(duration),
841 span,
842 }
843 } else {
844 return Err(
845 ErrorSource::Parsing(format!("Invalid duration: {d}")).with_span(span)
846 );
847 }
848 }
849 TokenType::Number(n) if *n == 1.0 => {
850 let span = self.current_token().span;
852 self.advance();
853
854 Spanned {
855 node: Expression::Literal(Literal::Duration {
856 numerator: 1,
857 denominator: 1,
858 dots: 0,
859 }),
860 span,
861 }
862 }
863 _ => return Err(self.error("Expected duration at start of musical event")),
864 };
865
866 let pitches = self.expression()?; let mut dynamic = None;
869 let mut attributes = Vec::new();
870
871 while !self.check(&TokenType::Semicolon) && !self.is_at_end() {
872 match &self.current_token().token_type {
874 TokenType::Dynamic(_) => {
875 if dynamic.is_some() {
876 return Err(self.error("Multiple dynamics not allowed"));
877 }
878 dynamic = Some(Box::new(self.expression()?));
879 }
880 TokenType::Attribute(_) => {
881 attributes.push(self.expression()?);
882 }
883 TokenType::Pitch(text) => {
884 let text = text.clone();
885
886 if Literal::is_dynamic(&text) {
888 if dynamic.is_some() {
889 return Err(self.error("Multiple dynamics not allowed"));
890 }
891 let span = self.current_token().span;
892 self.advance();
893 dynamic = Some(Box::new(Spanned {
894 node: Expression::Literal(Literal::Dynamic(text)),
895 span,
896 }));
897 } else if Literal::is_attribute(&text) {
898 let span = self.current_token().span;
899 self.advance();
900 attributes.push(Spanned {
901 node: Expression::Literal(Literal::Attribute(text)),
902 span,
903 });
904 } else {
905 break; }
907 }
908 TokenType::Identifier(_) => {
909 match self.parse_identifier_in_musical_context("dynamic_or_attribute") {
911 Ok(expr) => {
912 match expr.node {
913 Expression::Literal(Literal::Dynamic { .. }) => {
914 if dynamic.is_some() {
915 return Err(self.error("Multiple dynamics not allowed"));
916 }
917 dynamic = Some(Box::new(expr));
918 }
919 Expression::Literal(Literal::Attribute { .. }) => {
920 attributes.push(expr);
921 }
922 _ => unreachable!(), }
924 }
925 Err(_) => {
926 break;
928 }
929 }
930 }
931 _ => break,
932 }
933 }
934
935 let end = if !attributes.is_empty() {
936 attributes.last().unwrap().span.end
937 } else if let Some(ref dyn_expr) = dynamic {
938 dyn_expr.span.end
939 } else {
940 pitches.span.end
941 };
942
943 Ok(Spanned {
944 node: Expression::MusicalEvent {
945 duration: Box::new(duration),
946 pitches: Box::new(pitches),
947 dynamic,
948 attributes,
949 },
950 span: Span {
951 start: start_pos,
952 end,
953 },
954 })
955 }
956
957 fn primary(&mut self) -> Result<SpannedExpression> {
958 if self.could_be_musical_event() {
960 return self.musical_event();
961 }
962
963 let token = self.current_token().clone();
964
965 match &token.token_type {
966 TokenType::True => {
967 self.advance();
968 Ok(Spanned {
969 node: Expression::Literal(Literal::Boolean(true)),
970 span: token.span,
971 })
972 }
973 TokenType::False => {
974 self.advance();
975 Ok(Spanned {
976 node: Expression::Literal(Literal::Boolean(false)),
977 span: token.span,
978 })
979 }
980 TokenType::Number(n) => {
981 self.advance();
982 Ok(Spanned {
983 node: Expression::Literal(Literal::Number(*n)),
984 span: token.span,
985 })
986 }
987 TokenType::String(s) => {
988 self.advance();
989 Ok(Spanned {
990 node: Expression::Literal(Literal::String(s.to_owned())),
991 span: token.span,
992 })
993 }
994 TokenType::Pitch(p) => {
995 self.advance();
996 if let Some(pitch) = Literal::parse_pitch(p) {
997 Ok(Spanned {
998 node: Expression::Literal(pitch),
999 span: token.span,
1000 })
1001 } else {
1002 Err(ErrorSource::Parsing(format!("Invalid pitch: {p}")).with_span(token.span))
1003 }
1004 }
1005 TokenType::Duration(d) => {
1006 self.advance();
1007 if let Some(duration) = Literal::parse_duration(d) {
1008 Ok(Spanned {
1009 node: Expression::Literal(duration),
1010 span: token.span,
1011 })
1012 } else {
1013 Err(ErrorSource::Parsing(format!("Invalid duration: {d}"))
1014 .with_span(token.span))
1015 }
1016 }
1017 TokenType::Dynamic(d) => {
1018 self.advance();
1019 Ok(Spanned {
1020 node: Expression::Literal(Literal::Dynamic(d.to_owned())),
1021 span: token.span,
1022 })
1023 }
1024 TokenType::Attribute(a) => {
1025 self.advance();
1026 Ok(Spanned {
1027 node: Expression::Literal(Literal::Attribute(a.to_owned())),
1028 span: token.span,
1029 })
1030 }
1031 TokenType::Tilde => {
1032 self.advance();
1033 Ok(Spanned {
1034 node: Expression::Literal(Literal::Rest { duration: None }),
1035 span: token.span,
1036 })
1037 }
1038 TokenType::Identifier(name) => {
1039 if self.could_be_pitch_identifier(name) {
1040 self.advance();
1041 if let Some(pitch) = Literal::parse_pitch(name) {
1042 Ok(Spanned {
1043 node: Expression::Literal(pitch),
1044 span: token.span,
1045 })
1046 } else {
1047 Ok(Spanned {
1048 node: Expression::Identifier(name.to_owned()),
1049 span: token.span,
1050 })
1051 }
1052 } else {
1053 self.advance();
1054 Ok(Spanned {
1055 node: Expression::Identifier(name.to_owned()),
1056 span: token.span,
1057 })
1058 }
1059 }
1060 TokenType::LeftParen => self.grouping_or_tuple(),
1061 TokenType::LeftBracket => self.list(),
1062 TokenType::LeftBrace => self.set_or_block(),
1063 TokenType::If => self.if_expression(),
1064 TokenType::For => self.for_expression(),
1065 TokenType::While => self.while_expression(),
1066 TokenType::Part => self.part_expression(),
1067 TokenType::Staff => self.staff_expression(),
1068 TokenType::Timeline => self.timeline_expression(),
1069 TokenType::Movement => self.movement_expression(),
1070 TokenType::Score => self.score_expression(),
1071 _ => Err(self.error("Unexpected token")),
1072 }
1073 }
1074
1075 fn call(&mut self) -> Result<SpannedExpression> {
1076 let mut expr = self.primary()?;
1077
1078 while self.match_token(&TokenType::LeftParen) {
1079 let (args, kwargs) = self.parse_arguments()?;
1080 self.consume(TokenType::RightParen, "Expected ')' after arguments")?;
1081 let end = self.previous_token().span.end;
1082 expr = Spanned {
1083 node: Expression::Call {
1084 callee: Box::new(expr.clone()),
1085 args,
1086 kwargs,
1087 },
1088 span: Span {
1089 start: expr.span.start,
1090 end,
1091 },
1092 };
1093 }
1094
1095 Ok(expr)
1096 }
1097
1098 #[allow(clippy::type_complexity)]
1099 fn parse_arguments(
1100 &mut self,
1101 ) -> Result<(Vec<SpannedExpression>, Vec<(String, SpannedExpression)>)> {
1102 let mut args = Vec::new();
1103 let mut kwargs = Vec::new();
1104 if !self.check(&TokenType::RightParen) {
1105 loop {
1106 if let TokenType::Identifier(name) = &self.current_token().token_type {
1108 if self.current + 1 < self.tokens.len()
1110 && matches!(self.tokens[self.current + 1].token_type, TokenType::Assign)
1111 {
1112 let name = name.clone();
1113 self.advance(); self.advance(); let value = self.expression()?;
1116 kwargs.push((name, value));
1117 } else {
1118 args.push(self.expression()?);
1120 }
1121 } else {
1122 args.push(self.expression()?);
1124 }
1125
1126 if !self.match_token(&TokenType::Comma) {
1127 break;
1128 }
1129 }
1130 }
1131 Ok((args, kwargs))
1132 }
1133
1134 fn match_unary_op(&mut self) -> Option<UnaryOp> {
1135 match self.current_token().token_type {
1136 TokenType::Minus => {
1137 self.advance();
1138 Some(UnaryOp::Minus)
1139 }
1140 TokenType::Not => {
1141 self.advance();
1142 Some(UnaryOp::Not)
1143 }
1144 _ => None,
1145 }
1146 }
1147 fn unary(&mut self) -> Result<SpannedExpression> {
1148 if let Some(op) = self.match_unary_op() {
1149 let start = self.previous_token().span.start;
1150 let operand = self.unary()?;
1151 let span = Span::new(start, operand.span.end);
1152 return Ok(Spanned {
1153 node: Expression::Unary {
1154 operator: op,
1155 operand: Box::new(operand),
1156 },
1157 span,
1158 });
1159 }
1160 self.call()
1161 }
1162
1163 fn parse_binary_left_associative<F>(
1168 &mut self,
1169 mut next_precedence: F,
1170 operators: &[TokenType],
1171 ) -> Result<SpannedExpression>
1172 where
1173 F: FnMut(&mut Self) -> Result<SpannedExpression>,
1174 {
1175 let mut expr = next_precedence(self)?;
1176
1177 while operators.iter().any(|op| self.check(op)) {
1178 let op_token_type = &self.current_token().token_type;
1179 let binary_op = match op_token_type {
1180 TokenType::Multiply => BinaryOp::Multiply,
1181 TokenType::Divide => BinaryOp::Divide,
1182 TokenType::Modulo => BinaryOp::Modulo,
1183 TokenType::Plus => BinaryOp::Add,
1184 TokenType::Minus => BinaryOp::Subtract,
1185 TokenType::Greater => BinaryOp::Greater,
1186 TokenType::GreaterEqual => BinaryOp::GreaterEqual,
1187 TokenType::Less => BinaryOp::Less,
1188 TokenType::LessEqual => BinaryOp::LessEqual,
1189 TokenType::Equal => BinaryOp::Equal,
1190 TokenType::NotEqual => BinaryOp::NotEqual,
1191 TokenType::And => BinaryOp::And,
1192 TokenType::Or => BinaryOp::Or,
1193 _ => unreachable!(),
1194 };
1195
1196 self.advance();
1197 let right = next_precedence(self)?;
1198 let span = Span::new(expr.span.start, right.span.end);
1199
1200 expr = Spanned {
1201 node: Expression::Binary {
1202 left: Box::new(expr),
1203 operator: binary_op,
1204 right: Box::new(right),
1205 },
1206 span,
1207 };
1208 }
1209
1210 Ok(expr)
1211 }
1212
1213 fn factor(&mut self) -> Result<SpannedExpression> {
1214 self.parse_binary_left_associative(
1215 Self::unary,
1216 &[TokenType::Multiply, TokenType::Divide, TokenType::Modulo],
1217 )
1218 }
1219
1220 fn term(&mut self) -> Result<SpannedExpression> {
1221 self.parse_binary_left_associative(Self::factor, &[TokenType::Plus, TokenType::Minus])
1222 }
1223
1224 fn comparison(&mut self) -> Result<SpannedExpression> {
1225 self.parse_binary_left_associative(
1226 Self::term,
1227 &[
1228 TokenType::Greater,
1229 TokenType::GreaterEqual,
1230 TokenType::Less,
1231 TokenType::LessEqual,
1232 ],
1233 )
1234 }
1235
1236 fn equality(&mut self) -> Result<SpannedExpression> {
1237 self.parse_binary_left_associative(
1238 Self::comparison,
1239 &[TokenType::Equal, TokenType::NotEqual],
1240 )
1241 }
1242
1243 fn logical_and(&mut self) -> Result<SpannedExpression> {
1244 self.parse_binary_left_associative(Self::equality, &[TokenType::And])
1245 }
1246
1247 fn logical_or(&mut self) -> Result<SpannedExpression> {
1248 self.parse_binary_left_associative(Self::logical_and, &[TokenType::Or])
1249 }
1250
1251 fn pipe(&mut self) -> Result<SpannedExpression> {
1252 let mut expr = self.logical_or()?;
1253
1254 while self.match_token(&TokenType::Pipe) {
1255 let right = self.logical_or()?;
1256 let span = Span::new(expr.span.start, right.span.end);
1257 expr = Spanned {
1258 node: Expression::Pipe {
1259 left: Box::new(expr),
1260 right: Box::new(right),
1261 },
1262 span,
1263 };
1264 }
1265
1266 Ok(expr)
1267 }
1268
1269 fn expression(&mut self) -> Result<SpannedExpression> {
1270 self.pipe()
1271 }
1272
1273 fn variable_declaration(&mut self) -> Result<SpannedStatement> {
1274 let start = self.current_token().span.start;
1275 self.consume(TokenType::Let, "Expected 'let'")?;
1276
1277 let name = self.expect_identifier("a variable name")?;
1278 self.advance();
1279
1280 self.consume(TokenType::Assign, "Expected '=' after variable name")?;
1281 let value = self.expression()?;
1282 self.consume(
1283 TokenType::Semicolon,
1284 "Expected ';' after variable declaration",
1285 )?;
1286
1287 Ok(Spanned {
1288 node: Statement::VariableDeclaration { name, value },
1289 span: Span {
1290 start,
1291 end: self.previous_token().span.end,
1292 },
1293 })
1294 }
1295
1296 fn function_declaration(&mut self) -> Result<SpannedStatement> {
1297 let start = self.current_token().span.start;
1298 self.consume(TokenType::Def, "Expected 'def'")?;
1299
1300 let name = self.expect_identifier("a function name")?;
1301 self.advance();
1302
1303 self.consume(TokenType::LeftParen, "Expected '(' after function name")?;
1304
1305 let mut params = Vec::new();
1306 if !self.check(&TokenType::RightParen) {
1307 loop {
1308 let param = self.expect_identifier("a parameter name")?;
1309 params.push(param);
1310 self.advance();
1311
1312 if !self.match_token(&TokenType::Comma) {
1313 break;
1314 }
1315
1316 if self.check(&TokenType::RightParen) {
1317 break;
1318 }
1319 }
1320 }
1321
1322 self.consume(TokenType::RightParen, "Expected ')' after parameters")?;
1323 self.consume(TokenType::LeftBrace, "Expected '{' before function body")?;
1324
1325 let mut body = Vec::new();
1326 while !self.check(&TokenType::RightBrace) && !self.is_at_end() {
1327 self.skip_comments();
1328 if self.check(&TokenType::RightBrace) {
1329 break;
1330 }
1331 let decl = self.declaration()?;
1332 self.collect_trailing_comments(&decl.span);
1333 body.push(decl);
1334 }
1335
1336 self.consume(TokenType::RightBrace, "Expected '}' after function body")?;
1337 self.consume(
1338 TokenType::Semicolon,
1339 "Expected ';' after function declaration",
1340 )?;
1341
1342 Ok(Spanned {
1343 node: Statement::FunctionDeclaration { name, params, body },
1344 span: Span {
1345 start,
1346 end: self.previous_token().span.end,
1347 },
1348 })
1349 }
1350
1351 fn metadata_declaration(&mut self) -> Result<SpannedStatement> {
1356 let start = self.current_token().span.start;
1357 self.consume(TokenType::At, "Expected '@'")?;
1358
1359 let key = match &self.current_token().token_type {
1360 TokenType::Identifier(key) => {
1361 let key = key.clone();
1362 self.advance();
1363 key
1364 }
1365 _ => return Err(self.error("Expected metadata key")),
1366 };
1367 let value = match key.as_str() {
1369 "time_signature" => {
1370 let expr = self.expression()?;
1371 if let Expression::Binary {
1372 left,
1373 operator: BinaryOp::Divide,
1374 right,
1375 } = expr.node
1376 {
1377 Spanned {
1378 node: Expression::Tuple {
1379 elements: vec![*left, *right],
1380 },
1381 span: expr.span,
1382 }
1383 } else if let Expression::Literal(Literal::Duration {
1384 numerator,
1385 denominator,
1386 dots: 0,
1387 }) = expr.node
1388 {
1389 let num_expr = Spanned {
1390 node: Expression::Literal(Literal::Number(f64::from(numerator))),
1391 span: expr.span,
1392 };
1393 let den_expr = Spanned {
1394 node: Expression::Literal(Literal::Number(f64::from(denominator))),
1395 span: expr.span,
1396 };
1397 Spanned {
1398 node: Expression::Tuple {
1399 elements: vec![num_expr, den_expr],
1400 },
1401 span: expr.span,
1402 }
1403 } else {
1404 return Err(
1405 self.error("Time signature must be in numerator/denominator format.")
1406 );
1407 }
1408 }
1409 _ => self.expression()?,
1410 };
1411 self.consume(TokenType::Semicolon, "Expected ';' after metadata")?;
1412
1413 Ok(Spanned {
1414 node: Statement::Metadata { key, value },
1415 span: Span {
1416 start,
1417 end: self.previous_token().span.end,
1418 },
1419 })
1420 }
1421 fn return_statement(&mut self) -> Result<SpannedStatement> {
1422 let start = self.current_token().span.start;
1423 self.consume(TokenType::Return, "Expected 'return'")?;
1424
1425 let value = if self.check(&TokenType::Semicolon) {
1426 None
1427 } else {
1428 Some(self.expression()?)
1429 };
1430
1431 self.consume(TokenType::Semicolon, "Expected ';' after return statement")?;
1432
1433 Ok(Spanned {
1434 node: Statement::Return { value },
1435 span: Span {
1436 start,
1437 end: self.previous_token().span.end,
1438 },
1439 })
1440 }
1441
1442 fn statement(&mut self) -> Result<SpannedStatement> {
1443 match &self.current_token().token_type {
1444 TokenType::Return => self.return_statement(),
1445 _ => {
1446 let expr = self.expression()?;
1447 self.consume(TokenType::Semicolon, "Expected ';' after expression")?;
1448 Ok(Spanned {
1449 node: Statement::Expression(expr.clone()),
1450 span: expr.span,
1451 })
1452 }
1453 }
1454 }
1455
1456 fn declaration(&mut self) -> Result<SpannedStatement> {
1457 match &self.current_token().token_type {
1458 TokenType::Let => self.variable_declaration(),
1459 TokenType::Def => self.function_declaration(),
1460 TokenType::At => self.metadata_declaration(),
1461 _ => self.statement(),
1462 }
1463 }
1464
1465 pub fn parse(mut self) -> Result<Program> {
1473 let start_span = self.current_token().span;
1474 let mut statements = Vec::new();
1475
1476 while !self.is_at_end() {
1477 self.skip_comments();
1478 if self.is_at_end() {
1479 break;
1480 }
1481
1482 let stmt = self.declaration()?;
1483 self.collect_trailing_comments(&stmt.span);
1484 statements.push(stmt);
1485
1486 self.skip_comments();
1487 }
1488
1489 let end_span = if statements.is_empty() {
1490 start_span
1491 } else {
1492 statements.last().unwrap().span
1493 };
1494
1495 Ok(Program {
1496 statements,
1497 comments: self.comments.clone(),
1498 span: Span::new(start_span.start, end_span.end),
1499 })
1500 }
1501}