1use cove_diag::{Diagnostic, FileId, SourceMap, Span, Spanned};
65
66use crate::ast::*;
67use crate::lexer;
68use crate::token::{Keyword, StringPart, Token, TokenKind};
69
70pub fn parse(
74 sources: &SourceMap,
75 file: FileId,
76 tokens: Vec<Token>,
77) -> Result<SourceUnit, Vec<Diagnostic>> {
78 let mut parser = Parser::new(sources, file, tokens);
79 let unit = parser.parse_source_unit();
80 if parser.diagnostics.is_empty() {
81 Ok(unit)
82 } else {
83 Err(parser.diagnostics)
84 }
85}
86
87struct Bail;
90
91struct ItemModifiers {
93 exported: bool,
94 is_test: bool,
95 opaque: Option<Span>,
99}
100
101type PResult<T> = Result<T, Bail>;
102
103const NESTING_STACK: usize = 2 * 1024 * 1024;
125
126const STACK_PER_LEVEL: usize = 32 * 1024;
175
176const MAX_NESTING_DEPTH: u32 = (NESTING_STACK / STACK_PER_LEVEL) as u32;
222
223struct Parser<'a> {
224 sources: &'a SourceMap,
225 file: FileId,
226 tokens: Vec<Token>,
227 pos: usize,
228 diagnostics: Vec<Diagnostic>,
229 no_trailing_closure: bool,
233 group_depth: u32,
246 depth: u32,
255}
256
257fn expr(kind: ExprKind, span: Span) -> Expr {
263 Expr {
264 id: ExprId::UNSET,
265 kind,
266 span,
267 }
268}
269
270fn is_place_expr(target: &Expr) -> bool {
272 match &target.kind {
273 ExprKind::Ident(_) => true,
274 ExprKind::Field { base, .. } => is_place_expr(base),
275 _ => false,
276 }
277}
278
279fn can_take_trailing_closure(callee: &Expr) -> bool {
282 matches!(
283 callee.kind,
284 ExprKind::Ident(_) | ExprKind::Field { .. } | ExprKind::Call { trailing: None, .. }
285 )
286}
287
288const NEWLINE_OPERATOR_RULE: &str = "A newline ends a statement when the expression before it is \
290 complete, so an operator that continues an expression stays on the line it continues.";
291
292fn ends_expression(kind: &TokenKind) -> bool {
303 matches!(
304 kind,
305 TokenKind::Ident(_)
306 | TokenKind::Keyword(
307 Keyword::SelfValue | Keyword::Break | Keyword::Continue | Keyword::Return
308 )
309 | TokenKind::Int(_)
310 | TokenKind::Float(_)
311 | TokenKind::Bool(_)
312 | TokenKind::Duration(_)
313 | TokenKind::Str(_)
314 | TokenKind::RParen
315 | TokenKind::RBracket
316 | TokenKind::RBrace
317 | TokenKind::Question
318 | TokenKind::Ellipsis
319 )
320}
321
322fn continues_expression_only(kind: &TokenKind) -> bool {
327 matches!(
328 kind,
329 TokenKind::Plus
330 | TokenKind::Star
331 | TokenKind::Slash
332 | TokenKind::Percent
333 | TokenKind::EqEq
334 | TokenKind::BangEq
335 | TokenKind::Lt
336 | TokenKind::LtEq
337 | TokenKind::Gt
338 | TokenKind::GtEq
339 | TokenKind::AmpAmp
340 | TokenKind::PipePipe
341 | TokenKind::Eq
342 | TokenKind::PlusEq
343 | TokenKind::MinusEq
344 | TokenKind::StarEq
345 | TokenKind::SlashEq
346 | TokenKind::PercentEq
347 | TokenKind::DotDot
348 | TokenKind::DotDotLt
349 | TokenKind::Keyword(Keyword::Is)
350 )
351}
352
353fn rebase_span(span: Span, file: FileId, offset: u32) -> Span {
354 Span::new(file, offset + span.start, offset + span.end)
355}
356
357fn rebase_token(mut token: Token, file: FileId, offset: u32) -> Token {
360 token.span = rebase_span(token.span, file, offset);
361 if let TokenKind::Str(parts) = &mut token.kind {
362 for part in parts {
363 if let StringPart::Interpolation { span, .. } = part {
364 *span = rebase_span(*span, file, offset);
365 }
366 }
367 }
368 token
369}
370
371fn rebase_diagnostic(mut diagnostic: Diagnostic, file: FileId, offset: u32) -> Diagnostic {
372 if let Some(span) = diagnostic.primary {
373 diagnostic.primary = Some(rebase_span(span, file, offset));
374 }
375 for label in &mut diagnostic.labels {
376 label.span = rebase_span(label.span, file, offset);
377 }
378 diagnostic
379}
380
381impl<'a> Parser<'a> {
382 fn new(sources: &'a SourceMap, file: FileId, tokens: Vec<Token>) -> Self {
383 let tokens = if tokens.is_empty() {
384 vec![Token {
385 kind: TokenKind::Eof,
386 span: Span::new(file, 0, 0),
387 preceded_by_newline: false,
388 }]
389 } else {
390 tokens
391 };
392 Parser {
393 sources,
394 file,
395 tokens,
396 pos: 0,
397 diagnostics: Vec::new(),
398 no_trailing_closure: false,
399 group_depth: 0,
400 depth: 0,
401 }
402 }
403
404 fn peek(&self) -> &TokenKind {
405 &self.tokens[self.pos].kind
406 }
407
408 fn peek_at(&self, offset: usize) -> &TokenKind {
409 let index = (self.pos + offset).min(self.tokens.len() - 1);
410 &self.tokens[index].kind
411 }
412
413 fn span(&self) -> Span {
414 self.tokens[self.pos].span
415 }
416
417 fn prev_span(&self) -> Span {
420 self.tokens[self.pos.saturating_sub(1)].span
421 }
422
423 fn is_eof(&self) -> bool {
424 matches!(self.peek(), TokenKind::Eof)
425 }
426
427 fn bump(&mut self) -> Token {
428 let token = self.tokens[self.pos].clone();
429 if self.pos + 1 < self.tokens.len() {
430 self.pos += 1;
431 }
432 token
433 }
434
435 fn at(&self, kind: &TokenKind) -> bool {
436 self.peek() == kind
437 }
438
439 fn eat(&mut self, kind: &TokenKind) -> bool {
440 if self.at(kind) {
441 self.bump();
442 true
443 } else {
444 false
445 }
446 }
447
448 fn at_keyword(&self, keyword: Keyword) -> bool {
449 matches!(self.peek(), TokenKind::Keyword(found) if *found == keyword)
450 }
451
452 fn eat_keyword(&mut self, keyword: Keyword) -> bool {
453 if self.at_keyword(keyword) {
454 self.bump();
455 true
456 } else {
457 false
458 }
459 }
460
461 fn error(&mut self, diagnostic: Diagnostic) {
462 self.diagnostics.push(diagnostic);
463 }
464
465 fn unexpected(&mut self, expected: &str) -> Bail {
466 let found = self.peek().describe();
467 let span = self.span();
468 let mut diagnostic = Diagnostic::error(
469 "cove::parse::unexpected_token",
470 format!("expected {expected}, found {found}"),
471 )
472 .at(span);
473 diagnostic = self.note_newline_rule(diagnostic);
474 self.error(diagnostic);
475 Bail
476 }
477
478 fn note_newline_rule(&self, diagnostic: Diagnostic) -> Diagnostic {
482 if !(self.at_statement_break() && continues_expression_only(self.peek())) {
483 return diagnostic;
484 }
485 diagnostic
486 .label(self.prev_span(), "a newline ended the statement here")
487 .rule(NEWLINE_OPERATOR_RULE)
488 .help("Move this operator to the end of the previous line.")
489 }
490
491 fn expected_expression(&mut self) -> Bail {
497 if !(self.at_statement_break() && continues_expression_only(self.peek())) {
498 return self.unexpected("an expression");
499 }
500 let operator = self.peek().describe();
501 let span = self.span();
502 let previous = self.prev_span();
503 self.error(
504 Diagnostic::error(
505 "cove::parse::newline_ended_statement",
506 format!("{operator} cannot start a statement"),
507 )
508 .at(span)
509 .label(previous, "the previous statement ended here")
510 .rule(NEWLINE_OPERATOR_RULE)
511 .help("Move this operator to the end of the previous line."),
512 );
513 Bail
514 }
515
516 fn expect(&mut self, kind: &TokenKind, expected: &str) -> PResult<Token> {
517 if self.at(kind) {
518 Ok(self.bump())
519 } else {
520 Err(self.unexpected(expected))
521 }
522 }
523
524 fn expect_keyword(&mut self, keyword: Keyword, expected: &str) -> PResult<Span> {
525 if self.at_keyword(keyword) {
526 Ok(self.bump().span)
527 } else {
528 Err(self.unexpected(expected))
529 }
530 }
531
532 fn expect_ident(&mut self) -> PResult<Ident> {
533 let span = self.span();
534 match self.peek() {
535 TokenKind::Ident(name) => {
536 let name = name.clone();
537 self.bump();
538 Ok(Spanned::new(name, span))
539 }
540 _ => Err(self.unexpected("identifier")),
541 }
542 }
543
544 fn expect_member_name(&mut self) -> PResult<Ident> {
547 let span = self.span();
548 let name = match self.peek() {
549 TokenKind::Ident(name) => name.clone(),
550 TokenKind::Keyword(keyword) => keyword.as_str().to_string(),
551 _ => return Err(self.unexpected("a field or method name")),
552 };
553 self.bump();
554 Ok(Spanned::new(name, span))
555 }
556
557 fn scoped<T>(&mut self, no_trailing_closure: bool, parse: impl FnOnce(&mut Self) -> T) -> T {
561 let saved = self.no_trailing_closure;
562 self.no_trailing_closure = no_trailing_closure;
563 let result = parse(self);
564 self.no_trailing_closure = saved;
565 result
566 }
567
568 fn grouped<T>(&mut self, parse: impl FnOnce(&mut Self) -> T) -> T {
571 self.group_depth += 1;
572 let result = parse(self);
573 self.group_depth -= 1;
574 result
575 }
576
577 fn ungrouped<T>(&mut self, parse: impl FnOnce(&mut Self) -> T) -> T {
581 let saved = self.group_depth;
582 self.group_depth = 0;
583 let result = parse(self);
584 self.group_depth = saved;
585 result
586 }
587
588 fn nested<T>(&mut self, parse: impl FnOnce(&mut Self) -> PResult<T>) -> PResult<T> {
598 if self.depth >= MAX_NESTING_DEPTH {
599 return Err(self.nesting_too_deep());
600 }
601 self.depth += 1;
602 let result = parse(self);
603 self.depth -= 1;
604 result
605 }
606
607 fn link(&mut self) -> PResult<()> {
616 if self.depth >= MAX_NESTING_DEPTH {
617 return Err(self.nesting_too_deep());
618 }
619 self.depth += 1;
620 Ok(())
621 }
622
623 fn chained<T>(&mut self, parse: impl FnOnce(&mut Self) -> PResult<T>) -> PResult<T> {
626 let saved = self.depth;
627 let result = parse(self);
628 self.depth = saved;
629 result
630 }
631
632 fn nesting_too_deep(&mut self) -> Bail {
634 let span = self.span();
635 self.error(
636 Diagnostic::error(
637 "cove::parse::nesting_too_deep",
638 format!("this nests more than {MAX_NESTING_DEPTH} levels deep"),
639 )
640 .at(span)
641 .rule(format!(
642 "Source nests no more than {MAX_NESTING_DEPTH} levels deep, counting each link \
643 of a chain such as `a.b.c` or `1 + 2 + 3` as a level of its own."
644 ))
645 .help("Give an inner part a name of its own with `let`, or lift it into a function."),
646 );
647 Bail
648 }
649
650 fn at_statement_break(&self) -> bool {
656 if self.group_depth > 0 || self.pos == 0 {
657 return false;
658 }
659 let next = &self.tokens[self.pos];
660 if !next.preceded_by_newline {
661 return false;
662 }
663 if matches!(next.kind, TokenKind::Dot) {
665 return false;
666 }
667 ends_expression(&self.tokens[self.pos - 1].kind)
668 }
669
670 fn dangling_doc(&mut self, span: Span) {
671 self.error(
672 Diagnostic::error(
673 "cove::parse::dangling_doc_comment",
674 "doc comment is not attached to a declaration",
675 )
676 .at(span)
677 .rule("A `///` doc comment documents the declaration that follows it.")
678 .help("Move the comment above a declaration, or write it as an ordinary `//` comment."),
679 );
680 }
681
682 fn collect_doc(&mut self) -> Option<(String, Span)> {
684 let mut lines: Vec<String> = Vec::new();
685 let mut span: Option<Span> = None;
686 while let TokenKind::DocComment(text) = self.peek() {
687 let text = text.clone();
688 let line_span = self.span();
689 span = Some(match span {
690 Some(previous) => previous.to(line_span),
691 None => line_span,
692 });
693 lines.push(text);
694 self.bump();
695 }
696 span.map(|span| (lines.join("\n"), span))
697 }
698
699 fn at_item_start(&self) -> bool {
702 match self.peek() {
703 TokenKind::Keyword(
704 Keyword::Export
705 | Keyword::Test
706 | Keyword::Opaque
707 | Keyword::Struct
708 | Keyword::Enum
709 | Keyword::Trait
710 | Keyword::Impl
711 | Keyword::Type,
712 ) => true,
713 TokenKind::Keyword(Keyword::Fn) => matches!(self.peek_at(1), TokenKind::Ident(_)),
714 TokenKind::Keyword(Keyword::Async) => {
715 matches!(self.peek_at(1), TokenKind::Keyword(Keyword::Fn))
716 && matches!(self.peek_at(2), TokenKind::Ident(_))
717 }
718 _ => false,
719 }
720 }
721
722 fn at_stmt_start(&self) -> bool {
723 self.at_item_start()
724 || matches!(
725 self.peek(),
726 TokenKind::Keyword(
727 Keyword::Let
728 | Keyword::Var
729 | Keyword::Return
730 | Keyword::Break
731 | Keyword::Continue
732 ) | TokenKind::DocComment(_)
733 )
734 }
735
736 fn recover_to_item(&mut self, in_braces: bool) {
741 let mut depth = 0i32;
742 let mut consumed = false;
743 while !self.is_eof() {
744 if depth == 0 && self.at(&TokenKind::RBrace) && (in_braces || consumed) {
745 if in_braces {
746 return;
747 }
748 self.bump();
749 return;
750 }
751 if depth == 0
752 && consumed
753 && (self.at_item_start()
754 || self.at_keyword(Keyword::Use)
755 || matches!(self.peek(), TokenKind::DocComment(_)))
756 {
757 return;
758 }
759 match self.peek() {
760 TokenKind::LBrace => depth += 1,
761 TokenKind::RBrace => depth -= 1,
762 _ => {}
763 }
764 self.bump();
765 consumed = true;
766 }
767 }
768
769 fn recover_in_block(&mut self) {
772 let mut depth = 0i32;
773 let mut consumed = false;
774 while !self.is_eof() {
775 if depth == 0 && self.at(&TokenKind::RBrace) {
776 return;
777 }
778 if depth == 0 && consumed && self.at_stmt_start() {
779 return;
780 }
781 match self.peek() {
782 TokenKind::LBrace => depth += 1,
783 TokenKind::RBrace => depth -= 1,
784 _ => {}
785 }
786 self.bump();
787 consumed = true;
788 }
789 }
790}
791
792impl Parser<'_> {
794 fn parse_source_unit(&mut self) -> SourceUnit {
795 let start = self.span();
796 let mut uses = Vec::new();
797 let mut items = Vec::new();
798
799 while !self.is_eof() {
800 let doc = self.collect_doc();
801
802 if self.at_keyword(Keyword::Use) {
803 if let Some((_, span)) = doc {
804 self.dangling_doc(span);
805 }
806 match self.parse_use() {
807 Ok(use_decl) => uses.push(use_decl),
808 Err(Bail) => self.recover_to_item(false),
809 }
810 continue;
811 }
812
813 if !self.at_item_start() {
814 match doc {
815 Some((_, span)) => self.dangling_doc(span),
816 None => {
817 self.unexpected("a declaration");
818 }
819 }
820 self.recover_to_item(false);
821 continue;
822 }
823
824 match self.parse_item(doc.map(|(text, _)| text)) {
825 Ok(item) => items.push(item),
826 Err(Bail) => self.recover_to_item(false),
827 }
828 }
829
830 SourceUnit {
831 uses,
832 items,
833 span: start.to(self.span()),
834 }
835 }
836
837 fn parse_use(&mut self) -> PResult<Use> {
839 let start = self.expect_keyword(Keyword::Use, "`use`")?;
840 let mut path = vec![self.expect_ident()?];
841 while self.eat(&TokenKind::Dot) {
842 path.push(self.expect_ident()?);
843 }
844 Ok(Use {
845 path,
846 span: start.to(self.prev_span()),
847 })
848 }
849
850 fn parse_item(&mut self, doc: Option<String>) -> PResult<Item> {
851 let start = self.span();
852 let modifiers = self.parse_item_modifiers();
853 let keyword = match self.peek() {
854 TokenKind::Keyword(keyword) => Some(*keyword),
855 _ => None,
856 };
857 let kind = match keyword {
858 Some(Keyword::Fn | Keyword::Async) => ItemKind::Fn(self.parse_fn_decl()?),
859 Some(Keyword::Struct) => ItemKind::Struct(self.parse_struct_decl()?),
860 Some(Keyword::Enum) => ItemKind::Enum(self.parse_enum_decl()?),
861 Some(Keyword::Trait) => ItemKind::Trait(self.parse_trait_decl()?),
862 Some(Keyword::Impl) => ItemKind::Impl(self.parse_impl_block()?),
863 Some(Keyword::Type) => ItemKind::TypeAlias(self.parse_type_alias()?),
864 _ => return Err(self.unexpected("a declaration")),
865 };
866 let span = start.to(self.prev_span());
867 if modifiers.is_test && !matches!(kind, ItemKind::Fn(_)) {
868 self.error(
869 Diagnostic::error(
870 "cove::parse::test_not_a_function",
871 "`test` marks a function, not this declaration",
872 )
873 .at(span)
874 .rule("`test` marks a `fn` the test runner calls; no other declaration is a test.")
875 .help("Remove `test`, or move the behaviour into a `test fn`."),
876 );
877 }
878 let is_opaque = self.check_opaque(&modifiers, &kind, span);
879 Ok(Item {
880 doc,
881 exported: modifiers.exported,
882 is_test: modifiers.is_test,
883 is_opaque,
884 kind,
885 span,
886 })
887 }
888
889 fn parse_item_modifiers(&mut self) -> ItemModifiers {
902 let mut exported: Option<Span> = None;
903 let mut is_test: Option<Span> = None;
904 let mut opaque: Option<Span> = None;
905 loop {
906 let span = self.span();
907 let (seen, keyword) = if self.at_keyword(Keyword::Export) {
908 (&mut exported, Keyword::Export)
909 } else if self.at_keyword(Keyword::Test) {
910 (&mut is_test, Keyword::Test)
911 } else if self.at_keyword(Keyword::Opaque) {
912 (&mut opaque, Keyword::Opaque)
913 } else {
914 break;
915 };
916 self.bump();
917 let repeated = seen.is_some();
918 seen.get_or_insert(span);
919 if repeated {
920 self.error(
921 Diagnostic::error(
922 "cove::parse::repeated_modifier",
923 format!("`{}` is written twice", keyword.as_str()),
924 )
925 .at(span)
926 .rule("A declaration carries each modifier at most once.")
927 .help(format!("Remove the second `{}`.", keyword.as_str())),
928 );
929 }
930 }
931 if let (Some(exported), Some(is_test)) = (exported, is_test) {
932 self.error(
933 Diagnostic::error(
934 "cove::parse::exported_test",
935 "a `test fn` may not be exported",
936 )
937 .at(exported.to(is_test))
938 .rule(
939 "A test's whole contract is that the test runner is its only caller, so `test` and `export` cannot both apply to one declaration.",
940 )
941 .help("Remove `export`, or remove `test` and call it like any other declaration."),
942 );
943 }
944 ItemModifiers {
945 exported: exported.is_some() && is_test.is_none(),
948 is_test: is_test.is_some(),
949 opaque,
950 }
951 }
952
953 fn check_opaque(&mut self, modifiers: &ItemModifiers, kind: &ItemKind, span: Span) -> bool {
960 let Some(opaque) = modifiers.opaque else {
961 return false;
962 };
963 if !matches!(kind, ItemKind::Struct(_)) {
964 self.error(
965 Diagnostic::error(
966 "cove::parse::opaque_not_a_struct",
967 "`opaque` marks a struct, not this declaration",
968 )
969 .at(span)
970 .rule("`opaque` hides a struct's representation; an exported enum always exports its cases, and every other declaration is its own interface.")
971 .help("Remove `opaque`, or wrap the representation in a struct and export that."),
972 );
973 return false;
974 }
975 if !modifiers.exported {
976 self.error(
977 Diagnostic::error(
978 "cove::parse::opaque_not_exported",
979 "`opaque` describes an export, and this declaration is not exported",
980 )
981 .at(opaque)
982 .rule("A declaration without `export` is module-private, so there is no boundary for `opaque` to draw.")
983 .help("Write `export opaque struct`, or remove `opaque`."),
984 );
985 return false;
986 }
987 true
988 }
989
990 fn reject_nested_test(&mut self, item: &Item, place: &str) {
996 if !item.is_test {
997 return;
998 }
999 self.error(
1000 Diagnostic::error(
1001 "cove::parse::nested_test",
1002 format!("a `test fn` may not be declared {place}"),
1003 )
1004 .at(item.span)
1005 .rule("A test is a top-level declaration of its module, which is what the test runner calls.")
1006 .help("Move the `test fn` to the top level of the file."),
1007 );
1008 }
1009
1010 fn parse_fn_decl(&mut self) -> PResult<FnDecl> {
1011 let start = self.span();
1012 let is_async = self.eat_keyword(Keyword::Async);
1013 self.expect_keyword(Keyword::Fn, "`fn`")?;
1014 let name = self.expect_ident()?;
1015 let generics = self.parse_generic_params()?;
1016 self.expect(&TokenKind::LParen, "`(`")?;
1017 let (receiver, params) = self.parse_param_list()?;
1018 let return_type = if self.eat(&TokenKind::Arrow) {
1019 Some(self.parse_type()?)
1020 } else {
1021 None
1022 };
1023 let body = self.parse_block()?;
1024 Ok(FnDecl {
1025 name,
1026 is_async,
1027 generics,
1028 receiver,
1029 params,
1030 return_type,
1031 body,
1032 span: start.to(self.prev_span()),
1033 })
1034 }
1035
1036 fn parse_generic_params(&mut self) -> PResult<Vec<GenericParam>> {
1041 if !self.eat(&TokenKind::Lt) {
1042 return Ok(Vec::new());
1043 }
1044 self.grouped(|parser| {
1045 let mut generics = Vec::new();
1046 while !parser.at(&TokenKind::Gt) && !parser.is_eof() {
1047 generics.push(parser.parse_generic_param()?);
1048 if !parser.eat(&TokenKind::Comma) {
1049 break;
1050 }
1051 }
1052 parser.expect(&TokenKind::Gt, "`>`")?;
1053 Ok(generics)
1054 })
1055 }
1056
1057 fn parse_generic_param(&mut self) -> PResult<GenericParam> {
1059 let start = self.span();
1060 let name = self.expect_ident()?;
1061 let mut bounds = Vec::new();
1062 if self.eat(&TokenKind::Colon) {
1063 loop {
1064 bounds.push(self.expect_ident()?);
1065 if !self.eat(&TokenKind::Plus) {
1066 break;
1067 }
1068 }
1069 }
1070 Ok(GenericParam {
1071 name,
1072 bounds,
1073 span: start.to(self.prev_span()),
1074 })
1075 }
1076
1077 fn parse_param_list(&mut self) -> PResult<(Option<Receiver>, Vec<Param>)> {
1080 self.grouped(Parser::parse_param_list_inner)
1081 }
1082
1083 fn parse_param_list_inner(&mut self) -> PResult<(Option<Receiver>, Vec<Param>)> {
1084 let mut receiver = None;
1085 let mut params = Vec::new();
1086 let mut first = true;
1087
1088 while !self.at(&TokenKind::RParen) && !self.is_eof() {
1089 if first {
1090 first = false;
1091 if let Some(parsed) = self.try_receiver() {
1092 receiver = Some(parsed);
1093 if !self.eat(&TokenKind::Comma) {
1094 break;
1095 }
1096 continue;
1097 }
1098 }
1099 params.push(self.parse_param()?);
1100 if !self.eat(&TokenKind::Comma) {
1101 break;
1102 }
1103 }
1104
1105 self.expect(&TokenKind::RParen, "`)`")?;
1106 Ok((receiver, params))
1107 }
1108
1109 fn try_receiver(&mut self) -> Option<Receiver> {
1110 let start = self.span();
1111 if self.at_keyword(Keyword::SelfValue) {
1112 self.bump();
1113 return Some(Receiver {
1114 is_var: false,
1115 span: start,
1116 });
1117 }
1118 if self.at_keyword(Keyword::Var)
1119 && matches!(self.peek_at(1), TokenKind::Keyword(Keyword::SelfValue))
1120 {
1121 self.bump();
1122 self.bump();
1123 return Some(Receiver {
1124 is_var: true,
1125 span: start.to(self.prev_span()),
1126 });
1127 }
1128 None
1129 }
1130
1131 fn parse_param(&mut self) -> PResult<Param> {
1133 let start = self.span();
1134 let is_var = self.eat_keyword(Keyword::Var);
1135 let name = self.expect_ident()?;
1136 let ty = if self.eat(&TokenKind::Colon) {
1137 Some(self.parse_type()?)
1138 } else {
1139 None
1140 };
1141 let variadic = self.eat(&TokenKind::Ellipsis);
1142 let default = if self.eat(&TokenKind::Eq) {
1143 Some(self.parse_expr()?)
1144 } else {
1145 None
1146 };
1147 Ok(Param {
1148 is_var,
1149 name,
1150 ty,
1151 variadic,
1152 default,
1153 span: start.to(self.prev_span()),
1154 })
1155 }
1156
1157 fn parse_struct_decl(&mut self) -> PResult<StructDecl> {
1161 let start = self.expect_keyword(Keyword::Struct, "`struct`")?;
1162 let name = self.expect_ident()?;
1163 let generics = self.parse_generic_params()?;
1164 let close = if self.eat(&TokenKind::LBrace) {
1165 TokenKind::RBrace
1166 } else if self.eat(&TokenKind::LParen) {
1167 TokenKind::RParen
1168 } else {
1169 return Err(self.unexpected("`{` or `(`"));
1170 };
1171
1172 let mut fields = Vec::new();
1173 while !self.at(&close) && !self.is_eof() {
1174 let doc = self.collect_doc();
1175 if self.at(&close) {
1176 if let Some((_, span)) = doc {
1177 self.dangling_doc(span);
1178 }
1179 break;
1180 }
1181 let field_start = self.span();
1182 let field_name = self.expect_ident()?;
1183 self.expect(&TokenKind::Colon, "`:`")?;
1184 let ty = self.parse_type()?;
1185 fields.push(Field {
1186 doc: doc.map(|(text, _)| text),
1187 name: field_name,
1188 ty,
1189 span: field_start.to(self.prev_span()),
1190 });
1191 self.eat(&TokenKind::Comma);
1192 }
1193 self.expect(&close, "`}`")?;
1194
1195 Ok(StructDecl {
1196 name,
1197 generics,
1198 fields,
1199 span: start.to(self.prev_span()),
1200 })
1201 }
1202
1203 fn parse_enum_decl(&mut self) -> PResult<EnumDecl> {
1206 let start = self.expect_keyword(Keyword::Enum, "`enum`")?;
1207 let name = self.expect_ident()?;
1208 let generics = self.parse_generic_params()?;
1209 self.expect(&TokenKind::LBrace, "`{`")?;
1210
1211 let mut cases = Vec::new();
1212 while !self.at(&TokenKind::RBrace) && !self.is_eof() {
1213 let doc = self.collect_doc();
1214 if self.at(&TokenKind::RBrace) {
1215 if let Some((_, span)) = doc {
1216 self.dangling_doc(span);
1217 }
1218 break;
1219 }
1220 let case_start = self.span();
1221 let case_name = self.expect_ident()?;
1222 let mut payload = Vec::new();
1223 if self.eat(&TokenKind::LParen) {
1224 while !self.at(&TokenKind::RParen) && !self.is_eof() {
1225 payload.push(self.parse_type()?);
1226 if !self.eat(&TokenKind::Comma) {
1227 break;
1228 }
1229 }
1230 self.expect(&TokenKind::RParen, "`)`")?;
1231 }
1232 cases.push(EnumCase {
1233 doc: doc.map(|(text, _)| text),
1234 name: case_name,
1235 payload,
1236 span: case_start.to(self.prev_span()),
1237 });
1238 self.eat(&TokenKind::Comma);
1239 }
1240 self.expect(&TokenKind::RBrace, "`}`")?;
1241
1242 Ok(EnumDecl {
1243 name,
1244 generics,
1245 cases,
1246 span: start.to(self.prev_span()),
1247 })
1248 }
1249
1250 fn parse_trait_decl(&mut self) -> PResult<TraitDecl> {
1255 let start = self.expect_keyword(Keyword::Trait, "`trait`")?;
1256 let name = self.expect_ident()?;
1257 self.expect(&TokenKind::LBrace, "`{`")?;
1258
1259 let mut methods = Vec::new();
1260 while !self.at(&TokenKind::RBrace) && !self.is_eof() {
1261 let doc = self.collect_doc();
1262 if self.at(&TokenKind::RBrace) {
1263 if let Some((_, span)) = doc {
1264 self.dangling_doc(span);
1265 }
1266 break;
1267 }
1268 match self.parse_trait_method(doc.map(|(text, _)| text)) {
1269 Ok(method) => methods.push(method),
1270 Err(Bail) => self.recover_to_item(true),
1271 }
1272 }
1273 self.expect(&TokenKind::RBrace, "`}`")?;
1274
1275 Ok(TraitDecl {
1276 name,
1277 methods,
1278 span: start.to(self.prev_span()),
1279 })
1280 }
1281
1282 fn parse_trait_method(&mut self, doc: Option<String>) -> PResult<TraitMethod> {
1285 let start = self.span();
1286 let is_async = self.eat_keyword(Keyword::Async);
1287 self.expect_keyword(Keyword::Fn, "`fn`")?;
1288 let name = self.expect_ident()?;
1289 self.expect(&TokenKind::LParen, "`(`")?;
1290 let (receiver, params) = self.parse_param_list()?;
1291 let return_type = if self.eat(&TokenKind::Arrow) {
1292 Some(self.parse_type()?)
1293 } else {
1294 None
1295 };
1296 let default = if self.at(&TokenKind::LBrace) && !self.at_statement_break() {
1299 Some(self.parse_block()?)
1300 } else {
1301 None
1302 };
1303 Ok(TraitMethod {
1304 doc,
1305 name,
1306 is_async,
1307 receiver,
1308 params,
1309 return_type,
1310 default,
1311 span: start.to(self.prev_span()),
1312 })
1313 }
1314
1315 fn parse_impl_block(&mut self) -> PResult<ImplBlock> {
1317 let start = self.expect_keyword(Keyword::Impl, "`impl`")?;
1318 let mut trait_name = None;
1319 let mut type_name = self.expect_ident()?;
1320 if self.eat_keyword(Keyword::For) {
1321 trait_name = Some(type_name);
1322 type_name = self.expect_ident()?;
1323 }
1324 let generics = self.parse_generic_params()?;
1325 self.expect(&TokenKind::LBrace, "`{`")?;
1326
1327 let mut items = Vec::new();
1328 while !self.at(&TokenKind::RBrace) && !self.is_eof() {
1329 let doc = self.collect_doc();
1330 if !self.at_item_start() {
1331 match doc {
1332 Some((_, span)) => self.dangling_doc(span),
1333 None => {
1334 self.unexpected("a declaration");
1335 }
1336 }
1337 self.recover_to_item(true);
1338 continue;
1339 }
1340 match self.parse_item(doc.map(|(text, _)| text)) {
1341 Ok(item) => {
1342 self.reject_nested_test(&item, "inside an `impl` block");
1343 items.push(item);
1344 }
1345 Err(Bail) => self.recover_to_item(true),
1346 }
1347 }
1348 self.expect(&TokenKind::RBrace, "`}`")?;
1349
1350 Ok(ImplBlock {
1351 trait_name,
1352 type_name,
1353 generics,
1354 items,
1355 span: start.to(self.prev_span()),
1356 })
1357 }
1358
1359 fn parse_type_alias(&mut self) -> PResult<TypeAlias> {
1360 let start = self.expect_keyword(Keyword::Type, "`type`")?;
1361 let name = self.expect_ident()?;
1362 let generics = self.parse_generic_params()?;
1363 self.expect(&TokenKind::Eq, "`=`")?;
1364 let ty = self.parse_type()?;
1365 Ok(TypeAlias {
1366 name,
1367 generics,
1368 ty,
1369 span: start.to(self.prev_span()),
1370 })
1371 }
1372}
1373
1374impl Parser<'_> {
1376 fn parse_type(&mut self) -> PResult<Type> {
1377 self.nested(Parser::parse_type_inner)
1378 }
1379
1380 fn parse_type_inner(&mut self) -> PResult<Type> {
1381 let start = self.span();
1382 let kind = match self.peek() {
1383 TokenKind::LParen => {
1384 self.bump();
1385 self.expect(&TokenKind::RParen, "`)`")?;
1386 TypeKind::Unit
1387 }
1388 TokenKind::Keyword(Keyword::Async | Keyword::Fn) => self.parse_fn_type()?,
1389 TokenKind::Keyword(Keyword::Dyn) => {
1390 self.bump();
1391 TypeKind::Dyn(self.expect_ident()?)
1392 }
1393 TokenKind::Ident(_) => {
1394 let mut path = vec![self.expect_ident()?];
1395 while self.at(&TokenKind::Dot) && matches!(self.peek_at(1), TokenKind::Ident(_)) {
1396 self.bump();
1397 path.push(self.expect_ident()?);
1398 }
1399 let args = if self.at(&TokenKind::Lt) {
1400 self.parse_type_args()?
1401 } else {
1402 Vec::new()
1403 };
1404 TypeKind::Named { path, args }
1405 }
1406 _ => return Err(self.unexpected("a type")),
1407 };
1408 Ok(Type {
1409 kind,
1410 span: start.to(self.prev_span()),
1411 })
1412 }
1413
1414 fn parse_fn_type(&mut self) -> PResult<TypeKind> {
1415 let is_async = self.eat_keyword(Keyword::Async);
1416 self.expect_keyword(Keyword::Fn, "`fn`")?;
1417 self.expect(&TokenKind::LParen, "`(`")?;
1418 let params = self.grouped(|parser| {
1419 let mut params = Vec::new();
1420 while !parser.at(&TokenKind::RParen) && !parser.is_eof() {
1421 params.push(parser.parse_fn_type_param()?);
1422 if !parser.eat(&TokenKind::Comma) {
1423 break;
1424 }
1425 }
1426 parser.expect(&TokenKind::RParen, "`)`")?;
1427 Ok(params)
1428 })?;
1429 let return_type = if self.eat(&TokenKind::Arrow) {
1430 Some(Box::new(self.parse_type()?))
1431 } else {
1432 None
1433 };
1434 Ok(TypeKind::Fn {
1435 is_async,
1436 params,
1437 return_type,
1438 })
1439 }
1440
1441 fn parse_fn_type_param(&mut self) -> PResult<Param> {
1444 let start = self.span();
1445 let is_var = self.eat_keyword(Keyword::Var);
1446 if matches!(self.peek(), TokenKind::Ident(_)) && self.peek_at(1) == &TokenKind::Colon {
1447 let name = self.expect_ident()?;
1448 self.bump();
1449 let ty = self.parse_type()?;
1450 let variadic = self.eat(&TokenKind::Ellipsis);
1451 return Ok(Param {
1452 is_var,
1453 name,
1454 ty: Some(ty),
1455 variadic,
1456 default: None,
1457 span: start.to(self.prev_span()),
1458 });
1459 }
1460 let ty = self.parse_type()?;
1461 let variadic = self.eat(&TokenKind::Ellipsis);
1462 let span = start.to(self.prev_span());
1463 Ok(Param {
1464 is_var,
1465 name: Spanned::new(String::new(), span),
1466 ty: Some(ty),
1467 variadic,
1468 default: None,
1469 span,
1470 })
1471 }
1472
1473 fn parse_type_args(&mut self) -> PResult<Vec<Type>> {
1476 self.expect(&TokenKind::Lt, "`<`")?;
1477 self.grouped(|parser| {
1478 let mut args = Vec::new();
1479 while !parser.at(&TokenKind::Gt) && !parser.is_eof() {
1480 args.push(parser.parse_type()?);
1481 if !parser.eat(&TokenKind::Comma) {
1482 break;
1483 }
1484 }
1485 parser.expect(&TokenKind::Gt, "`>`")?;
1486 Ok(args)
1487 })
1488 }
1489}
1490
1491impl Parser<'_> {
1493 fn parse_block(&mut self) -> PResult<Block> {
1496 self.nested(Parser::parse_block_inner)
1497 }
1498
1499 fn parse_block_inner(&mut self) -> PResult<Block> {
1500 let start = self.span();
1501 self.expect(&TokenKind::LBrace, "`{`")?;
1502
1503 let mut statements = Vec::new();
1504 self.ungrouped(|parser| {
1505 parser.scoped(false, |parser| {
1506 while !parser.at(&TokenKind::RBrace) && !parser.is_eof() {
1507 match parser.parse_stmt() {
1508 Ok(stmt) => {
1509 parser.check_detached_trailing_closure(&stmt);
1510 statements.push(stmt);
1511 }
1512 Err(Bail) => parser.recover_in_block(),
1513 }
1514 }
1515 })
1516 });
1517
1518 let end = self.span();
1519 self.expect(&TokenKind::RBrace, "`}`")?;
1520
1521 let mut tail = None;
1522 if matches!(
1523 statements.last(),
1524 Some(Stmt {
1525 kind: StmtKind::Expr(_),
1526 ..
1527 })
1528 ) {
1529 if let Some(Stmt {
1530 kind: StmtKind::Expr(value),
1531 ..
1532 }) = statements.pop()
1533 {
1534 tail = Some(Box::new(value));
1535 }
1536 }
1537
1538 Ok(Block {
1539 statements,
1540 tail,
1541 span: start.to(end),
1542 })
1543 }
1544
1545 fn check_detached_trailing_closure(&mut self, stmt: &Stmt) {
1551 if !matches!(
1552 &stmt.kind,
1553 StmtKind::Expr(Expr {
1554 kind: ExprKind::Ident(_) | ExprKind::Field { .. },
1555 ..
1556 })
1557 ) {
1558 return;
1559 }
1560 if !self.at(&TokenKind::LBrace) || !self.at_statement_break() {
1561 return;
1562 }
1563 let span = self.span();
1564 self.error(
1565 Diagnostic::error(
1566 "cove::parse::newline_before_trailing_closure",
1567 "a newline ended the statement before this `{`",
1568 )
1569 .at(span)
1570 .label(stmt.span, "this expression is already complete")
1571 .rule(
1572 "A newline ends a statement when the expression before it is complete, so a \
1573 trailing closure begins on the same line as the call it belongs to.",
1574 )
1575 .help("Move `{` up onto the previous line."),
1576 );
1577 }
1578
1579 fn parse_stmt(&mut self) -> PResult<Stmt> {
1580 let doc = self.collect_doc();
1581
1582 if self.at_item_start() {
1583 let item = self.parse_item(doc.map(|(text, _)| text))?;
1584 self.reject_nested_test(&item, "inside a block");
1585 let span = item.span;
1586 return Ok(Stmt {
1587 kind: StmtKind::Item(Box::new(item)),
1588 span,
1589 });
1590 }
1591 if let Some((_, span)) = doc {
1592 self.dangling_doc(span);
1593 }
1594
1595 if self.at_keyword(Keyword::Let) || self.at_keyword(Keyword::Var) {
1596 return self.parse_let_stmt();
1597 }
1598
1599 let value = self.parse_expr()?;
1600 Ok(Stmt {
1601 span: value.span,
1602 kind: StmtKind::Expr(value),
1603 })
1604 }
1605
1606 fn parse_let_stmt(&mut self) -> PResult<Stmt> {
1608 let start = self.span();
1609 let is_var = self.at_keyword(Keyword::Var);
1610 self.bump();
1611 let name = self.expect_ident()?;
1612 let ty = if self.eat(&TokenKind::Colon) {
1613 Some(self.parse_type()?)
1614 } else {
1615 None
1616 };
1617 self.expect(&TokenKind::Eq, "`=`")?;
1618 let value = self.parse_expr()?;
1619 Ok(Stmt {
1620 kind: StmtKind::Let {
1621 is_var,
1622 name,
1623 ty,
1624 value,
1625 },
1626 span: start.to(self.prev_span()),
1627 })
1628 }
1629}
1630
1631impl Parser<'_> {
1633 fn parse_expr(&mut self) -> PResult<Expr> {
1634 self.nested(Parser::parse_assign)
1635 }
1636
1637 fn parse_assign(&mut self) -> PResult<Expr> {
1638 let target = self.parse_or()?;
1639 if self.at_statement_break() {
1640 return Ok(target);
1641 }
1642 let op = match self.peek() {
1643 TokenKind::Eq => None,
1644 TokenKind::PlusEq => Some(BinaryOp::Add),
1645 TokenKind::MinusEq => Some(BinaryOp::Sub),
1646 TokenKind::StarEq => Some(BinaryOp::Mul),
1647 TokenKind::SlashEq => Some(BinaryOp::Div),
1648 TokenKind::PercentEq => Some(BinaryOp::Rem),
1649 _ => return Ok(target),
1650 };
1651 self.bump();
1652 let value = self.nested(Parser::parse_assign)?;
1653
1654 if !is_place_expr(&target) {
1655 self.error(
1656 Diagnostic::error(
1657 "cove::parse::invalid_assignment_target",
1658 "this expression cannot be assigned to",
1659 )
1660 .at(target.span)
1661 .rule("Assignment writes to a place: a name, or a field of a place.")
1662 .help("Assign to a variable or a field, such as `self.count = 1`."),
1663 );
1664 }
1665
1666 let span = target.span.to(value.span);
1667 Ok(expr(
1668 ExprKind::Assign {
1669 op,
1670 target: Box::new(target),
1671 value: Box::new(value),
1672 },
1673 span,
1674 ))
1675 }
1676
1677 fn parse_or(&mut self) -> PResult<Expr> {
1678 self.chained(|parser| {
1679 let mut lhs = parser.parse_and()?;
1680 while parser.at(&TokenKind::PipePipe) && !parser.at_statement_break() {
1681 parser.bump();
1682 parser.link()?;
1683 let rhs = parser.parse_and()?;
1684 lhs = binary(BinaryOp::Or, lhs, rhs);
1685 }
1686 Ok(lhs)
1687 })
1688 }
1689
1690 fn parse_and(&mut self) -> PResult<Expr> {
1691 self.chained(|parser| {
1692 let mut lhs = parser.parse_comparison()?;
1693 while parser.at(&TokenKind::AmpAmp) && !parser.at_statement_break() {
1694 parser.bump();
1695 parser.link()?;
1696 let rhs = parser.parse_comparison()?;
1697 lhs = binary(BinaryOp::And, lhs, rhs);
1698 }
1699 Ok(lhs)
1700 })
1701 }
1702
1703 fn parse_comparison(&mut self) -> PResult<Expr> {
1704 self.chained(|parser| {
1705 let mut lhs = parser.parse_range()?;
1706 loop {
1707 if parser.at_statement_break() {
1708 return Ok(lhs);
1709 }
1710 let op = match parser.peek() {
1711 TokenKind::EqEq => BinaryOp::Eq,
1712 TokenKind::BangEq => BinaryOp::Ne,
1713 TokenKind::Lt => BinaryOp::Lt,
1714 TokenKind::LtEq => BinaryOp::Le,
1715 TokenKind::Gt => BinaryOp::Gt,
1716 TokenKind::GtEq => BinaryOp::Ge,
1717 TokenKind::Keyword(Keyword::Is) => BinaryOp::Is,
1722 _ => return Ok(lhs),
1723 };
1724 parser.bump();
1725 parser.link()?;
1726 let rhs = parser.parse_range()?;
1727 lhs = binary(op, lhs, rhs);
1728 }
1729 })
1730 }
1731
1732 fn parse_range(&mut self) -> PResult<Expr> {
1734 let start = self.parse_additive()?;
1735 if self.at_statement_break() {
1736 return Ok(start);
1737 }
1738 let inclusive_end = match self.peek() {
1739 TokenKind::DotDot => true,
1740 TokenKind::DotDotLt => false,
1741 _ => return Ok(start),
1742 };
1743 self.bump();
1744 let end = self.parse_additive()?;
1745 let span = start.span.to(end.span);
1746 Ok(expr(
1747 ExprKind::Range {
1748 start: Box::new(start),
1749 end: Box::new(end),
1750 inclusive_end,
1751 },
1752 span,
1753 ))
1754 }
1755
1756 fn parse_additive(&mut self) -> PResult<Expr> {
1757 self.chained(|parser| {
1758 let mut lhs = parser.parse_multiplicative()?;
1759 loop {
1760 if parser.at_statement_break() {
1761 return Ok(lhs);
1762 }
1763 let op = match parser.peek() {
1764 TokenKind::Plus => BinaryOp::Add,
1765 TokenKind::Minus => BinaryOp::Sub,
1766 _ => return Ok(lhs),
1767 };
1768 parser.bump();
1769 parser.link()?;
1770 let rhs = parser.parse_multiplicative()?;
1771 lhs = binary(op, lhs, rhs);
1772 }
1773 })
1774 }
1775
1776 fn parse_multiplicative(&mut self) -> PResult<Expr> {
1777 self.chained(|parser| {
1778 let mut lhs = parser.parse_unary()?;
1779 loop {
1780 if parser.at_statement_break() {
1781 return Ok(lhs);
1782 }
1783 let op = match parser.peek() {
1784 TokenKind::Star => BinaryOp::Mul,
1785 TokenKind::Slash => BinaryOp::Div,
1786 TokenKind::Percent => BinaryOp::Rem,
1787 _ => return Ok(lhs),
1788 };
1789 parser.bump();
1790 parser.link()?;
1791 let rhs = parser.parse_unary()?;
1792 lhs = binary(op, lhs, rhs);
1793 }
1794 })
1795 }
1796
1797 fn parse_unary(&mut self) -> PResult<Expr> {
1805 let start = self.span();
1806 let op = match self.peek() {
1807 TokenKind::Bang => Some(UnaryOp::Not),
1808 TokenKind::Minus => Some(UnaryOp::Neg),
1809 TokenKind::Keyword(Keyword::Await) => None,
1810 _ => return self.parse_postfix(),
1811 };
1812 match op {
1813 Some(op) => {
1814 self.bump();
1815 let operand = self.nested(Parser::parse_unary)?;
1816 let span = start.to(operand.span);
1817 Ok(expr(
1818 ExprKind::Unary {
1819 op,
1820 operand: Box::new(operand),
1821 },
1822 span,
1823 ))
1824 }
1825 None => {
1826 self.bump();
1827 let operand = self.parse_postfix()?;
1828 let operand_span = operand.span;
1829 Ok(match operand.kind {
1830 ExprKind::Try(inner) => {
1831 let await_span = start.to(inner.span);
1832 let awaited = expr(ExprKind::Await(inner), await_span);
1833 expr(ExprKind::Try(Box::new(awaited)), start.to(operand_span))
1834 }
1835 _ => expr(ExprKind::Await(Box::new(operand)), start.to(operand_span)),
1836 })
1837 }
1838 }
1839 }
1840
1841 fn parse_postfix(&mut self) -> PResult<Expr> {
1842 self.chained(|parser| {
1843 let mut value = parser.parse_primary()?;
1844 loop {
1845 let stop = parser.at_statement_break();
1849 match parser.peek() {
1850 TokenKind::Dot => {
1851 parser.link()?;
1852 parser.bump();
1853 let name = parser.expect_member_name()?;
1854 let span = value.span.to(name.span);
1855 value = expr(
1856 ExprKind::Field {
1857 base: Box::new(value),
1858 name,
1859 },
1860 span,
1861 );
1862 }
1863 TokenKind::LParen if !stop => {
1864 parser.link()?;
1865 parser.bump();
1866 let args = parser.parse_args()?;
1867 value = parser.finish_call(value, Vec::new(), args)?;
1868 }
1869 TokenKind::Question => {
1870 parser.link()?;
1871 let span = value.span.to(parser.span());
1872 parser.bump();
1873 value = expr(ExprKind::Try(Box::new(value)), span);
1874 }
1875 TokenKind::Lt if !stop => {
1876 parser.link()?;
1877 match parser.try_generic_call(value)? {
1878 Ok(call) => value = call,
1879 Err(unchanged) => return Ok(unchanged),
1880 }
1881 }
1882 TokenKind::LBrace
1883 if !stop
1884 && !parser.no_trailing_closure
1885 && can_take_trailing_closure(&value) =>
1886 {
1887 parser.link()?;
1888 let closure = parser.parse_trailing_closure()?;
1889 let span = value.span.to(closure.span);
1890 value = expr(
1891 ExprKind::Call {
1892 callee: Box::new(value),
1893 generics: Vec::new(),
1894 args: Vec::new(),
1895 trailing: Some(Box::new(closure)),
1896 },
1897 span,
1898 );
1899 }
1900 _ => return Ok(value),
1901 }
1902 }
1903 })
1904 }
1905
1906 fn finish_call(&mut self, callee: Expr, generics: Vec<Type>, args: Vec<Arg>) -> PResult<Expr> {
1908 let mut span = callee.span.to(self.prev_span());
1909 let trailing = if !self.no_trailing_closure
1910 && self.at(&TokenKind::LBrace)
1911 && !self.at_statement_break()
1912 {
1913 let closure = self.parse_trailing_closure()?;
1914 span = span.to(closure.span);
1915 Some(Box::new(closure))
1916 } else {
1917 None
1918 };
1919 Ok(expr(
1920 ExprKind::Call {
1921 callee: Box::new(callee),
1922 generics,
1923 args,
1924 trailing,
1925 },
1926 span,
1927 ))
1928 }
1929
1930 fn parse_trailing_closure(&mut self) -> PResult<Expr> {
1932 let body = self.parse_block()?;
1933 let span = body.span;
1934 Ok(expr(
1935 ExprKind::Lambda {
1936 is_async: false,
1937 params: Vec::new(),
1938 body,
1939 },
1940 span,
1941 ))
1942 }
1943
1944 #[allow(clippy::type_complexity)]
1949 fn try_generic_call(&mut self, callee: Expr) -> PResult<Result<Expr, Expr>> {
1950 let saved_pos = self.pos;
1951 let saved_diagnostics = self.diagnostics.len();
1952
1953 let generics = match self.parse_type_args() {
1954 Ok(generics) if self.at(&TokenKind::LParen) => generics,
1955 _ => {
1956 self.pos = saved_pos;
1957 self.diagnostics.truncate(saved_diagnostics);
1958 return Ok(Err(callee));
1959 }
1960 };
1961
1962 self.bump();
1963 let args = self.parse_args()?;
1964 Ok(Ok(self.finish_call(callee, generics, args)?))
1965 }
1966
1967 fn parse_args(&mut self) -> PResult<Vec<Arg>> {
1970 self.grouped(|parser| parser.scoped(false, Parser::parse_arg_list))
1971 }
1972
1973 fn parse_arg_list(&mut self) -> PResult<Vec<Arg>> {
1974 let mut args: Vec<Arg> = Vec::new();
1975 let mut first_label: Option<Span> = None;
1976
1977 while !self.at(&TokenKind::RParen) && !self.is_eof() {
1978 let start = self.span();
1979 let label = if matches!(self.peek(), TokenKind::Ident(_))
1980 && self.peek_at(1) == &TokenKind::Colon
1981 {
1982 let label = self.expect_ident()?;
1983 self.bump();
1984 Some(label)
1985 } else {
1986 None
1987 };
1988
1989 match (&label, first_label) {
1990 (Some(label), None) => first_label = Some(label.span),
1991 (None, Some(previous)) => self.error(
1992 Diagnostic::error(
1993 "cove::parse::positional_after_label",
1994 "a positional argument cannot follow a labeled argument",
1995 )
1996 .at(start)
1997 .label(previous, "the first labeled argument is here")
1998 .rule(
1999 "Positional arguments may precede labeled arguments; after the first \
2000 label, every remaining argument is labeled.",
2001 )
2002 .help("Give this argument its parameter label, such as `name: value`."),
2003 ),
2004 _ => {}
2005 }
2006
2007 let is_var = self.eat_keyword(Keyword::Var);
2008 let spread = self.eat(&TokenKind::Ellipsis);
2009 let value = self.parse_expr()?;
2010 args.push(Arg {
2011 label,
2012 is_var,
2013 spread,
2014 value,
2015 span: start.to(self.prev_span()),
2016 });
2017
2018 if !self.eat(&TokenKind::Comma) {
2019 break;
2020 }
2021 }
2022
2023 self.expect(&TokenKind::RParen, "`)`")?;
2024 Ok(args)
2025 }
2026
2027 fn parse_array_elements(&mut self) -> PResult<Vec<Expr>> {
2029 let mut elements = Vec::new();
2030 while !self.at(&TokenKind::RBracket) && !self.is_eof() {
2031 elements.push(self.parse_expr()?);
2032 if !self.eat(&TokenKind::Comma) {
2033 break;
2034 }
2035 }
2036 self.expect(&TokenKind::RBracket, "`]`")?;
2037 Ok(elements)
2038 }
2039
2040 fn parse_primary(&mut self) -> PResult<Expr> {
2041 let start = self.span();
2042 let kind = self.peek().clone();
2043 match kind {
2044 TokenKind::Int(value) => {
2045 self.bump();
2046 Ok(expr(ExprKind::Int(value), start))
2047 }
2048 TokenKind::Float(value) => {
2049 self.bump();
2050 Ok(expr(ExprKind::Float(value), start))
2051 }
2052 TokenKind::Bool(value) => {
2053 self.bump();
2054 Ok(expr(ExprKind::Bool(value), start))
2055 }
2056 TokenKind::Duration(value) => {
2057 self.bump();
2058 Ok(expr(ExprKind::Duration(value), start))
2059 }
2060 TokenKind::Str(parts) => {
2061 self.bump();
2062 let parts = self.parse_str_parts(&parts);
2063 Ok(expr(ExprKind::Str(parts), start))
2064 }
2065 TokenKind::Ident(name) => {
2066 self.bump();
2067 Ok(expr(ExprKind::Ident(name), start))
2068 }
2069 TokenKind::Keyword(Keyword::SelfValue) => {
2070 self.bump();
2071 Ok(expr(ExprKind::Ident("self".into()), start))
2072 }
2073 TokenKind::LParen => {
2074 self.bump();
2075 if self.at(&TokenKind::RParen) {
2076 self.bump();
2077 return Ok(expr(ExprKind::Unit, start.to(self.prev_span())));
2078 }
2079 let inner = self.grouped(|parser| parser.scoped(false, Parser::parse_expr))?;
2080 self.expect(&TokenKind::RParen, "`)`")?;
2081 Ok(expr(inner.kind, start.to(self.prev_span())))
2082 }
2083 TokenKind::LBracket => {
2084 self.bump();
2085 let elements =
2086 self.grouped(|parser| parser.scoped(false, Parser::parse_array_elements))?;
2087 Ok(expr(
2088 ExprKind::ArrayLit(elements),
2089 start.to(self.prev_span()),
2090 ))
2091 }
2092 TokenKind::LBrace => {
2093 let block = self.parse_block()?;
2094 let span = block.span;
2095 Ok(expr(ExprKind::Block(block), span))
2096 }
2097 TokenKind::Keyword(Keyword::If) => self.parse_if(),
2098 TokenKind::Keyword(Keyword::Match) => self.parse_match(),
2099 TokenKind::Keyword(Keyword::For) => self.parse_for(),
2100 TokenKind::Keyword(Keyword::While) => self.parse_while(),
2101 TokenKind::Keyword(Keyword::Scope) => self.parse_scope(),
2102 TokenKind::Keyword(Keyword::Return) => {
2103 self.bump();
2104 let value = if self.at_operand() {
2105 Some(Box::new(self.parse_expr()?))
2106 } else {
2107 None
2108 };
2109 Ok(expr(ExprKind::Return(value), start.to(self.prev_span())))
2110 }
2111 TokenKind::Keyword(Keyword::Break) => {
2112 self.bump();
2113 let value = if self.at_operand() {
2114 Some(Box::new(self.parse_expr()?))
2115 } else {
2116 None
2117 };
2118 Ok(expr(ExprKind::Break(value), start.to(self.prev_span())))
2119 }
2120 TokenKind::Keyword(Keyword::Continue) => {
2121 self.bump();
2122 Ok(expr(ExprKind::Continue, start.to(self.prev_span())))
2123 }
2124 TokenKind::Keyword(Keyword::Fn | Keyword::Async) => self.parse_lambda(),
2125 _ => Err(self.expected_expression()),
2126 }
2127 }
2128
2129 fn at_operand(&self) -> bool {
2149 !self.tokens[self.pos].preceded_by_newline && self.can_start_expr()
2150 }
2151
2152 fn can_start_expr(&self) -> bool {
2153 matches!(
2154 self.peek(),
2155 TokenKind::Int(_)
2156 | TokenKind::Float(_)
2157 | TokenKind::Bool(_)
2158 | TokenKind::Duration(_)
2159 | TokenKind::Str(_)
2160 | TokenKind::Ident(_)
2161 | TokenKind::LParen
2162 | TokenKind::LBracket
2163 | TokenKind::LBrace
2164 | TokenKind::Bang
2165 | TokenKind::Minus
2166 | TokenKind::Keyword(
2167 Keyword::If
2168 | Keyword::Match
2169 | Keyword::For
2170 | Keyword::While
2171 | Keyword::Scope
2172 | Keyword::Fn
2173 | Keyword::Async
2174 | Keyword::Await
2175 | Keyword::Return
2176 | Keyword::Break
2177 | Keyword::Continue
2178 | Keyword::SelfValue
2179 )
2180 )
2181 }
2182
2183 fn parse_if(&mut self) -> PResult<Expr> {
2184 let start = self.expect_keyword(Keyword::If, "`if`")?;
2185 let condition = self.scoped(true, |parser| parser.parse_expr())?;
2186 let then_branch = self.parse_block()?;
2187 let else_branch = if self.eat_keyword(Keyword::Else) {
2188 if self.at_keyword(Keyword::If) {
2189 Some(Box::new(self.parse_if()?))
2190 } else {
2191 let block = self.parse_block()?;
2192 let span = block.span;
2193 Some(Box::new(expr(ExprKind::Block(block), span)))
2194 }
2195 } else {
2196 None
2197 };
2198 Ok(expr(
2199 ExprKind::If {
2200 condition: Box::new(condition),
2201 then_branch,
2202 else_branch,
2203 },
2204 start.to(self.prev_span()),
2205 ))
2206 }
2207
2208 fn parse_match(&mut self) -> PResult<Expr> {
2209 let start = self.expect_keyword(Keyword::Match, "`match`")?;
2210 let scrutinee = self.scoped(true, |parser| parser.parse_expr())?;
2211 self.expect(&TokenKind::LBrace, "`{`")?;
2212 let arms = self.scoped(false, |parser| {
2213 let mut arms = Vec::new();
2214 while !parser.at(&TokenKind::RBrace) && !parser.is_eof() {
2215 let arm_start = parser.span();
2216 let pattern = parser.parse_pattern()?;
2217 parser.expect(&TokenKind::FatArrow, "`=>`")?;
2218 let body = parser.parse_expr()?;
2219 arms.push(MatchArm {
2220 pattern,
2221 body,
2222 span: arm_start.to(parser.prev_span()),
2223 });
2224 parser.eat(&TokenKind::Comma);
2225 }
2226 Ok(arms)
2227 })?;
2228 self.expect(&TokenKind::RBrace, "`}`")?;
2229 Ok(expr(
2230 ExprKind::Match {
2231 scrutinee: Box::new(scrutinee),
2232 arms,
2233 },
2234 start.to(self.prev_span()),
2235 ))
2236 }
2237
2238 fn parse_for(&mut self) -> PResult<Expr> {
2239 let start = self.expect_keyword(Keyword::For, "`for`")?;
2240 let binding = self.expect_ident()?;
2241 self.expect_keyword(Keyword::In, "`in`")?;
2242 let iterable = self.scoped(true, |parser| parser.parse_expr())?;
2243 let body = self.parse_block()?;
2244 Ok(expr(
2245 ExprKind::For {
2246 binding,
2247 iterable: Box::new(iterable),
2248 body,
2249 },
2250 start.to(self.prev_span()),
2251 ))
2252 }
2253
2254 fn parse_while(&mut self) -> PResult<Expr> {
2255 let start = self.expect_keyword(Keyword::While, "`while`")?;
2256 let condition = self.scoped(true, |parser| parser.parse_expr())?;
2257 let body = self.parse_block()?;
2258 Ok(expr(
2259 ExprKind::While {
2260 condition: Box::new(condition),
2261 body,
2262 },
2263 start.to(self.prev_span()),
2264 ))
2265 }
2266
2267 fn parse_scope(&mut self) -> PResult<Expr> {
2268 let start = self.expect_keyword(Keyword::Scope, "`scope`")?;
2269 let name = self.expect_ident()?;
2270 let body = self.parse_block()?;
2271 Ok(expr(
2272 ExprKind::Scope { name, body },
2273 start.to(self.prev_span()),
2274 ))
2275 }
2276
2277 fn parse_lambda(&mut self) -> PResult<Expr> {
2280 let start = self.span();
2281 let is_async = self.eat_keyword(Keyword::Async);
2282 self.expect_keyword(Keyword::Fn, "`fn`")?;
2283 let params = if self.eat(&TokenKind::LParen) {
2284 let (receiver, params) = self.scoped(false, |parser| parser.parse_param_list())?;
2285 if let Some(receiver) = receiver {
2286 self.error(
2287 Diagnostic::error(
2288 "cove::parse::self_outside_method",
2289 "`self` is only a parameter of a method",
2290 )
2291 .at(receiver.span)
2292 .rule("A `self` receiver belongs to a function declared inside `impl`.")
2293 .help("Remove `self`, or move this function into an `impl` block."),
2294 );
2295 }
2296 params
2297 } else {
2298 Vec::new()
2299 };
2300 let body = self.scoped(false, |parser| parser.parse_block())?;
2301 Ok(expr(
2302 ExprKind::Lambda {
2303 is_async,
2304 params,
2305 body,
2306 },
2307 start.to(self.prev_span()),
2308 ))
2309 }
2310}
2311
2312fn binary(op: BinaryOp, lhs: Expr, rhs: Expr) -> Expr {
2313 let span = lhs.span.to(rhs.span);
2314 expr(
2315 ExprKind::Binary {
2316 op,
2317 lhs: Box::new(lhs),
2318 rhs: Box::new(rhs),
2319 },
2320 span,
2321 )
2322}
2323
2324impl Parser<'_> {
2326 fn parse_pattern(&mut self) -> PResult<Pattern> {
2333 self.nested(Parser::parse_pattern_inner)
2334 }
2335
2336 fn parse_pattern_inner(&mut self) -> PResult<Pattern> {
2337 let start = self.span();
2338 match self.peek() {
2339 TokenKind::Underscore => {
2340 self.bump();
2341 Ok(Pattern {
2342 kind: PatternKind::Wildcard,
2343 span: start,
2344 })
2345 }
2346 TokenKind::Int(_)
2347 | TokenKind::Float(_)
2348 | TokenKind::Bool(_)
2349 | TokenKind::Duration(_)
2350 | TokenKind::Str(_) => {
2351 let literal = self.parse_primary()?;
2352 let span = literal.span;
2353 Ok(Pattern {
2354 kind: PatternKind::Literal(literal),
2355 span,
2356 })
2357 }
2358 TokenKind::Minus => {
2359 let literal = self.parse_unary()?;
2360 let span = literal.span;
2361 Ok(Pattern {
2362 kind: PatternKind::Literal(literal),
2363 span,
2364 })
2365 }
2366 TokenKind::Ident(_) => {
2367 let mut path = vec![self.expect_ident()?];
2368 while self.at(&TokenKind::Dot) {
2369 self.bump();
2370 path.push(self.expect_ident()?);
2371 }
2372
2373 let mut payload = Vec::new();
2374 let has_payload = self.at(&TokenKind::LParen);
2375 if has_payload {
2376 self.bump();
2377 self.grouped(|parser| {
2378 while !parser.at(&TokenKind::RParen) && !parser.is_eof() {
2379 payload.push(parser.parse_pattern()?);
2380 if !parser.eat(&TokenKind::Comma) {
2381 break;
2382 }
2383 }
2384 parser.expect(&TokenKind::RParen, "`)`")
2385 })?;
2386 }
2387
2388 let is_variant = path.len() > 1
2389 || has_payload
2390 || path[0]
2391 .node
2392 .chars()
2393 .next()
2394 .is_some_and(|first| first.is_uppercase());
2395
2396 let span = start.to(self.prev_span());
2397 let kind = if is_variant {
2398 PatternKind::Variant { path, payload }
2399 } else {
2400 PatternKind::Binding(path.remove(0).node)
2401 };
2402 Ok(Pattern { kind, span })
2403 }
2404 _ => Err(self.unexpected("a pattern")),
2405 }
2406 }
2407}
2408
2409impl Parser<'_> {
2411 fn parse_str_parts(&mut self, parts: &[StringPart]) -> Vec<StrPart> {
2412 let mut resolved = Vec::new();
2413 for part in parts {
2414 match part {
2415 StringPart::Text(text) => resolved.push(StrPart::Text(text.clone())),
2416 StringPart::Interpolation { source, span } => {
2417 if let Some(value) = self.parse_interpolation(source, *span) {
2418 resolved.push(StrPart::Interpolation(value));
2419 }
2420 }
2421 }
2422 }
2423 resolved
2424 }
2425
2426 fn parse_interpolation(&mut self, source: &str, span: Span) -> Option<Expr> {
2432 if source.trim().is_empty() {
2433 self.error(
2434 Diagnostic::error(
2435 "cove::parse::empty_interpolation",
2436 "string interpolation contains no expression",
2437 )
2438 .at(span)
2439 .rule("`{ }` inside a string literal interpolates exactly one expression.")
2440 .help("Write an expression between the braces, or escape them as `\\{` and `\\}`."),
2441 );
2442 return None;
2443 }
2444
2445 let mut scratch = SourceMap::new();
2446 let scratch_file = scratch.add("<interpolation>", source.to_string());
2447 let tokens = match lexer::lex(&scratch, scratch_file) {
2448 Ok(tokens) => tokens,
2449 Err(diagnostics) => {
2450 for diagnostic in diagnostics {
2451 let rebased = rebase_diagnostic(diagnostic, self.file, span.start);
2452 self.error(rebased);
2453 }
2454 return None;
2455 }
2456 };
2457 let tokens = tokens
2458 .into_iter()
2459 .map(|token| rebase_token(token, self.file, span.start))
2460 .collect();
2461
2462 let mut inner = Parser::new(self.sources, self.file, tokens);
2463 inner.depth = self.depth;
2469 let value = inner.parse_expr().ok();
2470 if value.is_some() && !inner.is_eof() {
2471 let found = inner.peek().describe();
2472 let rest = inner.span();
2473 inner.error(
2474 Diagnostic::error(
2475 "cove::parse::unexpected_token",
2476 format!("expected end of interpolation, found {found}"),
2477 )
2478 .at(rest)
2479 .rule("`{ }` inside a string literal interpolates exactly one expression."),
2480 );
2481 }
2482 let failed = !inner.diagnostics.is_empty();
2483 self.diagnostics.append(&mut inner.diagnostics);
2484 if failed {
2485 None
2486 } else {
2487 value
2488 }
2489 }
2490}
2491
2492#[cfg(test)]
2493mod tests {
2494 use super::*;
2495 use std::path::{Path, PathBuf};
2496
2497 fn parse_source(source: &str) -> (SourceMap, Result<SourceUnit, Vec<Diagnostic>>) {
2498 let mut sources = SourceMap::new();
2499 let file = sources.add("test.cove", source);
2500 let result = match lexer::lex(&sources, file) {
2501 Ok(tokens) => parse(&sources, file, tokens),
2502 Err(diagnostics) => Err(diagnostics),
2503 };
2504 (sources, result)
2505 }
2506
2507 fn ok(source: &str) -> SourceUnit {
2508 let (sources, result) = parse_source(source);
2509 match result {
2510 Ok(unit) => unit,
2511 Err(diagnostics) => {
2512 let rendered: String = diagnostics
2513 .iter()
2514 .map(|diagnostic| cove_diag::render(&sources, diagnostic))
2515 .collect();
2516 panic!("expected `{source}` to parse:\n{rendered}");
2517 }
2518 }
2519 }
2520
2521 fn errors(source: &str) -> Vec<Diagnostic> {
2522 let (_, result) = parse_source(source);
2523 match result {
2524 Ok(_) => panic!("expected `{source}` to fail"),
2525 Err(diagnostics) => diagnostics,
2526 }
2527 }
2528
2529 fn codes(diagnostics: &[Diagnostic]) -> Vec<&str> {
2530 diagnostics.iter().map(|d| d.code.as_str()).collect()
2531 }
2532
2533 fn fn_decl(item: &Item) -> &FnDecl {
2534 match &item.kind {
2535 ItemKind::Fn(decl) => decl,
2536 other => panic!("expected a function, found {other:?}"),
2537 }
2538 }
2539
2540 fn tail_expr(source: &str) -> Expr {
2542 let unit = ok(&format!("fn main() {{\n{source}\n}}"));
2543 let decl = fn_decl(&unit.items[0]);
2544 *decl
2545 .body
2546 .tail
2547 .clone()
2548 .unwrap_or_else(|| panic!("`{source}` produced no tail expression"))
2549 }
2550
2551 #[test]
2552 fn parses_a_test_declaration() {
2553 let unit = ok("test fn greetsByName() -> Result<Unit, Error> { Ok(()) }");
2554 let item = &unit.items[0];
2555 assert!(item.is_test);
2556 assert!(!item.exported);
2557 assert_eq!(fn_decl(item).name.node, "greetsByName");
2558 }
2559
2560 #[test]
2561 fn rejects_an_exported_test_written_either_way_round() {
2562 for source in [
2563 "export test fn t() -> Result<Unit, Error> { Ok(()) }",
2564 "test export fn t() -> Result<Unit, Error> { Ok(()) }",
2565 ] {
2566 let diagnostics = errors(source);
2567 assert_eq!(
2568 codes(&diagnostics),
2569 ["cove::parse::exported_test"],
2570 "{source}"
2571 );
2572 assert!(diagnostics[0].message.contains("may not be exported"));
2573 assert!(diagnostics[0]
2574 .rule
2575 .as_ref()
2576 .expect("the diagnostic states its rule")
2577 .contains("only caller"));
2578 }
2579 }
2580
2581 #[test]
2582 fn rejects_a_modifier_written_twice() {
2583 let diagnostics = errors("export export fn f() {}");
2584 assert_eq!(codes(&diagnostics), ["cove::parse::repeated_modifier"]);
2585 assert!(diagnostics[0].message.contains("`export` is written twice"));
2586 }
2587
2588 #[test]
2591 fn parses_an_opaque_export_written_either_way_round() {
2592 for source in [
2593 "export opaque struct User { id: Int }",
2594 "opaque export struct User { id: Int }",
2595 ] {
2596 let unit = ok(source);
2597 let item = &unit.items[0];
2598 assert!(item.exported, "{source}");
2599 assert!(item.is_opaque, "{source}");
2600 }
2601 }
2602
2603 #[test]
2604 fn a_plain_export_is_not_opaque() {
2605 let unit = ok("export struct User { id: Int }");
2606 assert!(!unit.items[0].is_opaque);
2607 }
2608
2609 #[test]
2610 fn rejects_opaque_on_a_declaration_that_is_not_a_struct() {
2611 for source in [
2612 "export opaque enum Status { Pending }",
2613 "export opaque fn f() {}",
2614 "export opaque type Handler = fn() -> Int",
2615 ] {
2616 let diagnostics = errors(source);
2617 assert_eq!(
2618 codes(&diagnostics),
2619 ["cove::parse::opaque_not_a_struct"],
2620 "{source}"
2621 );
2622 }
2623 }
2624
2625 #[test]
2628 fn rejects_opaque_without_export() {
2629 let diagnostics = errors("opaque struct User { id: Int }");
2630 assert_eq!(codes(&diagnostics), ["cove::parse::opaque_not_exported"]);
2631 assert!(diagnostics[0].message.contains("not exported"));
2632 }
2633
2634 #[test]
2635 fn rejects_opaque_written_twice() {
2636 let diagnostics = errors("export opaque opaque struct User { id: Int }");
2637 assert_eq!(codes(&diagnostics), ["cove::parse::repeated_modifier"]);
2638 assert!(diagnostics[0].message.contains("`opaque` is written twice"));
2639 }
2640
2641 #[test]
2642 fn rejects_test_on_a_declaration_that_is_not_a_function() {
2643 let diagnostics = errors("test struct Point { x: Int }");
2644 assert_eq!(codes(&diagnostics), ["cove::parse::test_not_a_function"]);
2645 }
2646
2647 #[test]
2648 fn rejects_a_test_declared_inside_an_impl_block() {
2649 let diagnostics = errors(
2650 "impl Point {
2651 test fn t() -> Result<Unit, Error> { Ok(()) }
2652}",
2653 );
2654 assert_eq!(codes(&diagnostics), ["cove::parse::nested_test"]);
2655 assert!(diagnostics[0].message.contains("`impl` block"));
2656 }
2657
2658 #[test]
2659 fn rejects_a_test_declared_inside_a_block() {
2660 let diagnostics = errors(
2661 "fn main() {
2662 test fn t() -> Result<Unit, Error> { Ok(()) }
2663}",
2664 );
2665 assert_eq!(codes(&diagnostics), ["cove::parse::nested_test"]);
2666 }
2667
2668 #[test]
2669 fn test_is_a_keyword_only_in_front_of_a_declaration() {
2670 let unit = ok("fn main() {
2672 suite.test()
2673}");
2674 assert_eq!(unit.items.len(), 1);
2675 }
2676
2677 #[test]
2678 fn parses_uses_and_items_in_any_order() {
2679 let unit = ok("use http\nfn a() {}\nuse console.println\nfn b() {}");
2680 assert_eq!(unit.uses.len(), 2);
2681 assert_eq!(unit.uses[0].path.len(), 1);
2682 assert_eq!(unit.uses[1].path[1].node, "println");
2683 assert_eq!(unit.items.len(), 2);
2684 }
2685
2686 #[test]
2687 fn parses_function_declarations() {
2688 let unit = ok("export async fn run<T, U>(name: String, items: T... , retries: Int = 3) -> Result<Unit, Error> { Ok(()) }");
2689 let item = &unit.items[0];
2690 assert!(item.exported);
2691 let decl = fn_decl(item);
2692 assert!(decl.is_async);
2693 assert_eq!(decl.name.node, "run");
2694 assert_eq!(decl.generics.len(), 2);
2695 assert!(decl.receiver.is_none());
2696 assert_eq!(decl.params.len(), 3);
2697 assert!(decl.params[1].variadic);
2698 assert!(decl.params[2].default.is_some());
2699 assert!(decl.return_type.is_some());
2700 }
2701
2702 #[test]
2703 fn parses_struct_in_brace_and_paren_form() {
2704 let braced = ok("export struct App {\n repository: Repo\n metrics: Shared<Metrics>\n}");
2705 let ItemKind::Struct(decl) = &braced.items[0].kind else {
2706 panic!("expected a struct");
2707 };
2708 assert_eq!(decl.fields.len(), 2);
2709
2710 let parens = ok("export struct Booking(id: BookingId, status: BookingStatus)");
2711 let ItemKind::Struct(decl) = &parens.items[0].kind else {
2712 panic!("expected a struct");
2713 };
2714 assert_eq!(decl.fields.len(), 2);
2715 assert_eq!(decl.fields[1].name.node, "status");
2716 }
2717
2718 #[test]
2719 fn parses_enum_cases_with_and_without_commas() {
2720 let unit =
2721 ok("enum ConfigError {\n InvalidPort(String)\n Missing,\n Pair(Int, String)\n}");
2722 let ItemKind::Enum(decl) = &unit.items[0].kind else {
2723 panic!("expected an enum");
2724 };
2725 assert_eq!(decl.cases.len(), 3);
2726 assert_eq!(decl.cases[0].payload.len(), 1);
2727 assert!(decl.cases[1].payload.is_empty());
2728 assert_eq!(decl.cases[2].payload.len(), 2);
2729 }
2730
2731 #[test]
2732 fn parses_impl_blocks_with_receivers() {
2733 let unit = ok("impl Metrics {\n /// Records one request.\n fn record(var self, failed: Bool) { self.requests += 1 }\n fn read(self) -> Int { self.requests }\n}");
2734 let ItemKind::Impl(block) = &unit.items[0].kind else {
2735 panic!("expected an impl");
2736 };
2737 assert_eq!(block.type_name.node, "Metrics");
2738 assert_eq!(block.items.len(), 2);
2739 let first = fn_decl(&block.items[0]);
2740 assert_eq!(block.items[0].doc.as_deref(), Some("Records one request."));
2741 assert!(first.receiver.expect("receiver").is_var);
2742 assert_eq!(first.params.len(), 1);
2743 assert!(!fn_decl(&block.items[1]).receiver.expect("receiver").is_var);
2744 }
2745
2746 #[test]
2747 fn parses_a_trait_with_required_and_defaulted_methods() {
2748 let unit = ok(
2749 "/// Renders itself.\nexport trait Display {\n /// The full form.\n fn describe(self) -> String\n\n /// A short form.\n fn label(self) -> String { self.describe() }\n\n fn make(width: Int) -> Int\n}",
2750 );
2751 let item = &unit.items[0];
2752 assert!(item.exported);
2753 assert_eq!(item.doc.as_deref(), Some("Renders itself."));
2754 let ItemKind::Trait(decl) = &item.kind else {
2755 panic!("expected a trait");
2756 };
2757 assert_eq!(decl.name.node, "Display");
2758 assert_eq!(decl.methods.len(), 3);
2759 assert_eq!(decl.methods[0].doc.as_deref(), Some("The full form."));
2760 assert!(decl.methods[0].receiver.is_some());
2761 assert!(decl.methods[0].default.is_none());
2762 assert!(decl.methods[1].default.is_some());
2763 assert!(decl.methods[2].receiver.is_none());
2765 assert_eq!(decl.methods[2].params.len(), 1);
2766 }
2767
2768 #[test]
2769 fn parses_a_conformance_and_an_inherent_impl() {
2770 let unit = ok("impl Display for Booking {\n fn describe(self) -> String { \"b\" }\n}\n\nimpl Booking {\n fn id(self) -> Int { 1 }\n}");
2771 let ItemKind::Impl(conformance) = &unit.items[0].kind else {
2772 panic!("expected an impl");
2773 };
2774 assert_eq!(
2775 conformance.trait_name.as_ref().map(|n| n.node.as_str()),
2776 Some("Display")
2777 );
2778 assert_eq!(conformance.type_name.node, "Booking");
2779 let ItemKind::Impl(inherent) = &unit.items[1].kind else {
2780 panic!("expected an impl");
2781 };
2782 assert!(inherent.trait_name.is_none());
2783 assert_eq!(inherent.type_name.node, "Booking");
2784 }
2785
2786 #[test]
2787 fn parses_one_bound_and_several_bounds_on_a_type_parameter() {
2788 let unit = ok("fn render<T: Display, U, V: Display + Ordered>(value: T) { }");
2789 let decl = fn_decl(&unit.items[0]);
2790 assert_eq!(decl.generics.len(), 3);
2791 assert_eq!(decl.generics[0].name.node, "T");
2792 assert_eq!(decl.generics[0].bounds.len(), 1);
2793 assert_eq!(decl.generics[0].bounds[0].node, "Display");
2794 assert!(decl.generics[1].bounds.is_empty());
2795 assert_eq!(decl.generics[2].bounds.len(), 2);
2796 assert_eq!(decl.generics[2].bounds[1].node, "Ordered");
2797 }
2798
2799 #[test]
2800 fn parses_dyn_as_a_type() {
2801 let unit = ok("fn renderAll(values: Array<dyn Display>) -> dyn Display { values }");
2802 let decl = fn_decl(&unit.items[0]);
2803 let ty = decl.params[0].ty.as_ref().expect("a written type");
2804 assert_eq!(ty.to_string(), "Array<dyn Display>");
2805 let TypeKind::Dyn(name) = &decl.return_type.as_ref().expect("a return type").kind else {
2806 panic!("expected a `dyn` return type");
2807 };
2808 assert_eq!(name.node, "Display");
2809 }
2810
2811 #[test]
2812 fn rejects_dyn_without_a_trait_name() {
2813 assert_eq!(
2814 codes(&errors("fn go(value: dyn) { }")),
2815 ["cove::parse::unexpected_token"]
2816 );
2817 }
2818
2819 #[test]
2820 fn parses_type_alias_with_function_type() {
2821 let unit = ok(
2822 "export type Handler = async fn(request: http.Request) -> Result<http.Response, Error>",
2823 );
2824 let ItemKind::TypeAlias(alias) = &unit.items[0].kind else {
2825 panic!("expected a type alias");
2826 };
2827 let TypeKind::Fn {
2828 is_async,
2829 params,
2830 return_type,
2831 } = &alias.ty.kind
2832 else {
2833 panic!("expected a function type");
2834 };
2835 assert!(is_async);
2836 assert_eq!(params.len(), 1);
2837 assert_eq!(params[0].name.node, "request");
2838 assert!(return_type.is_some());
2839 }
2840
2841 #[test]
2842 fn parses_unnamed_function_type_parameters_and_unit() {
2843 let unit = ok("type Predicate = fn(String, Int) -> ()");
2844 let ItemKind::TypeAlias(alias) = &unit.items[0].kind else {
2845 panic!("expected a type alias");
2846 };
2847 let TypeKind::Fn {
2848 params,
2849 return_type,
2850 ..
2851 } = &alias.ty.kind
2852 else {
2853 panic!("expected a function type");
2854 };
2855 assert_eq!(params.len(), 2);
2856 assert!(params[0].name.node.is_empty());
2857 assert!(matches!(
2858 return_type.as_deref().map(|ty| &ty.kind),
2859 Some(TypeKind::Unit)
2860 ));
2861 }
2862
2863 #[test]
2864 fn joins_consecutive_doc_comments() {
2865 let unit = ok("/// First line.\n/// Second line.\nexport fn a() {}");
2866 assert_eq!(
2867 unit.items[0].doc.as_deref(),
2868 Some("First line.\nSecond line.")
2869 );
2870 }
2871
2872 #[test]
2873 fn attaches_doc_comments_to_fields_and_cases() {
2874 let unit =
2875 ok("struct S {\n /// The port.\n port: Int\n}\nenum E {\n /// A case.\n Case\n}");
2876 let ItemKind::Struct(decl) = &unit.items[0].kind else {
2877 panic!("expected a struct");
2878 };
2879 assert_eq!(decl.fields[0].doc.as_deref(), Some("The port."));
2880 let ItemKind::Enum(decl) = &unit.items[1].kind else {
2881 panic!("expected an enum");
2882 };
2883 assert_eq!(decl.cases[0].doc.as_deref(), Some("A case."));
2884 }
2885
2886 #[test]
2887 fn dangling_doc_comment_is_an_error() {
2888 let diagnostics = errors("/// Nothing follows this.\n");
2889 assert_eq!(codes(&diagnostics), ["cove::parse::dangling_doc_comment"]);
2890 }
2891
2892 #[test]
2893 fn parses_nested_generic_types() {
2894 let unit = ok("struct S { field: Map<String, Array<Result<Vector<Int>, Error>>> }");
2895 let ItemKind::Struct(decl) = &unit.items[0].kind else {
2896 panic!("expected a struct");
2897 };
2898 let TypeKind::Named { path, args } = &decl.fields[0].ty.kind else {
2899 panic!("expected a named type");
2900 };
2901 assert_eq!(path[0].node, "Map");
2902 assert_eq!(args.len(), 2);
2903 let TypeKind::Named { args: inner, .. } = &args[1].kind else {
2904 panic!("expected a named type");
2905 };
2906 let TypeKind::Named { args: inner, .. } = &inner[0].kind else {
2907 panic!("expected a named type");
2908 };
2909 assert_eq!(inner.len(), 2);
2910 }
2911
2912 #[test]
2913 fn parses_dotted_type_paths() {
2914 let unit = ok("fn f(request: http.Request) -> http.Response<Body> { request }");
2915 let decl = fn_decl(&unit.items[0]);
2916 let TypeKind::Named { path, .. } = &decl.params[0].ty.as_ref().unwrap().kind else {
2917 panic!("expected a named type");
2918 };
2919 assert_eq!(path.len(), 2);
2920 assert_eq!(path[1].node, "Request");
2921 }
2922
2923 #[test]
2924 fn parses_labeled_var_and_spread_arguments() {
2925 let positional = tail_expr("f(a, var d, ...e)");
2926 let ExprKind::Call { args, .. } = &positional.kind else {
2927 panic!("expected a call");
2928 };
2929 assert_eq!(args.len(), 3);
2930 assert!(args.iter().all(|arg| arg.label.is_none()));
2931 assert!(args[1].is_var);
2932 assert!(args[2].spread);
2933
2934 let labeled = tail_expr("f(a, b: c, d: var e, rest: ...g)");
2935 let ExprKind::Call { args, .. } = &labeled.kind else {
2936 panic!("expected a call");
2937 };
2938 assert_eq!(args.len(), 4);
2939 assert!(args[0].label.is_none());
2940 assert_eq!(args[1].label.as_ref().unwrap().node, "b");
2941 assert!(args[2].is_var);
2942 assert!(args[3].spread);
2943 assert_eq!(args[3].label.as_ref().unwrap().node, "rest");
2944 }
2945
2946 #[test]
2947 fn positional_argument_after_label_is_an_error() {
2948 let diagnostics = errors("fn main() { f(a: 1, 2) }");
2949 assert_eq!(codes(&diagnostics), ["cove::parse::positional_after_label"]);
2950 assert!(diagnostics[0].rule.is_some());
2951 assert!(diagnostics[0].help.is_some());
2952 }
2953
2954 #[test]
2955 fn generic_call_arguments_are_disambiguated_from_comparison() {
2956 let call = tail_expr("api.fetch<Array<Booking>>(\"/bookings\")");
2957 let ExprKind::Call { generics, args, .. } = &call.kind else {
2958 panic!("expected a call");
2959 };
2960 assert_eq!(generics.len(), 1);
2961 assert_eq!(args.len(), 1);
2962
2963 let empty = tail_expr("request.json<CreateBookingRequest>()");
2964 let ExprKind::Call { generics, args, .. } = &empty.kind else {
2965 panic!("expected a call");
2966 };
2967 assert_eq!(generics.len(), 1);
2968 assert!(args.is_empty());
2969
2970 let comparison = tail_expr("a < b");
2971 assert!(matches!(
2972 comparison.kind,
2973 ExprKind::Binary {
2974 op: BinaryOp::Lt,
2975 ..
2976 }
2977 ));
2978
2979 let mixed = tail_expr("a < b && c > d");
2980 assert!(matches!(
2981 mixed.kind,
2982 ExprKind::Binary {
2983 op: BinaryOp::And,
2984 ..
2985 }
2986 ));
2987 }
2988
2989 #[test]
2990 fn parses_the_three_trailing_closure_shapes() {
2991 let bare = tail_expr("tasks.spawn { 1 }");
2992 let ExprKind::Call { args, trailing, .. } = &bare.kind else {
2993 panic!("expected a call");
2994 };
2995 assert!(args.is_empty());
2996 assert!(matches!(
2997 trailing.as_deref().map(|value| &value.kind),
2998 Some(ExprKind::Lambda {
2999 is_async: false,
3000 ..
3001 })
3002 ));
3003
3004 let after_args = tail_expr("clock.timeout(500ms) { 1 }");
3005 let ExprKind::Call { args, trailing, .. } = &after_args.kind else {
3006 panic!("expected a call");
3007 };
3008 assert_eq!(args.len(), 1);
3009 assert!(trailing.is_some());
3010
3011 let then_try = tail_expr("value.recover { ConfigError.InvalidPort(raw) }?");
3012 let ExprKind::Try(inner) = &then_try.kind else {
3013 panic!("expected `?`");
3014 };
3015 assert!(matches!(inner.kind, ExprKind::Call { .. }));
3016 }
3017
3018 #[test]
3019 fn control_flow_headers_do_not_take_trailing_closures() {
3020 let conditional = tail_expr("if ready { 1 } else if other { 2 } else { 3 }");
3021 let ExprKind::If {
3022 condition,
3023 else_branch,
3024 ..
3025 } = &conditional.kind
3026 else {
3027 panic!("expected an if");
3028 };
3029 assert!(matches!(condition.kind, ExprKind::Ident(_)));
3030 assert!(matches!(
3031 else_branch.as_deref().map(|value| &value.kind),
3032 Some(ExprKind::If { .. })
3033 ));
3034
3035 let loop_expr = tail_expr("for item in items.all() { item }");
3036 let ExprKind::For { iterable, .. } = &loop_expr.kind else {
3037 panic!("expected a for loop");
3038 };
3039 assert!(matches!(
3040 iterable.kind,
3041 ExprKind::Call { trailing: None, .. }
3042 ));
3043
3044 let while_expr = tail_expr("while running { step() }");
3045 assert!(matches!(while_expr.kind, ExprKind::While { .. }));
3046
3047 let scrutinee = tail_expr("match value { _ => 1 }");
3048 let ExprKind::Match { scrutinee, .. } = &scrutinee.kind else {
3049 panic!("expected a match");
3050 };
3051 assert!(matches!(scrutinee.kind, ExprKind::Ident(_)));
3052 }
3053
3054 #[test]
3055 fn parses_every_pattern_form() {
3056 let value = tail_expr(
3057 "match value {\n _ => 1\n other => 2\n \"debug\" => 3\n 1 => 4\n true => 5\n Ok(inner) => 6\n LogLevel.Debug => 7\n ConfigError.InvalidPort(raw) => 8\n}",
3058 );
3059 let ExprKind::Match { arms, .. } = &value.kind else {
3060 panic!("expected a match");
3061 };
3062 assert_eq!(arms.len(), 8);
3063 assert!(matches!(arms[0].pattern.kind, PatternKind::Wildcard));
3064 assert!(matches!(&arms[1].pattern.kind, PatternKind::Binding(name) if name == "other"));
3065 assert!(matches!(arms[2].pattern.kind, PatternKind::Literal(_)));
3066 assert!(matches!(arms[3].pattern.kind, PatternKind::Literal(_)));
3067 assert!(matches!(arms[4].pattern.kind, PatternKind::Literal(_)));
3068 let PatternKind::Variant { path, payload } = &arms[5].pattern.kind else {
3069 panic!("expected a variant");
3070 };
3071 assert_eq!(path[0].node, "Ok");
3072 assert_eq!(payload.len(), 1);
3073 let PatternKind::Variant { path, payload } = &arms[6].pattern.kind else {
3074 panic!("expected a variant");
3075 };
3076 assert_eq!(path.len(), 2);
3077 assert!(payload.is_empty());
3078 assert!(matches!(arms[7].pattern.kind, PatternKind::Variant { .. }));
3079 }
3080
3081 #[test]
3082 fn match_arms_accept_blocks_returns_and_trailing_commas() {
3083 let value = tail_expr("match value {\n Ok(v) => { v }\n Err(e) => return Err(e),\n}");
3084 let ExprKind::Match { arms, .. } = &value.kind else {
3085 panic!("expected a match");
3086 };
3087 assert_eq!(arms.len(), 2);
3088 assert!(matches!(arms[0].body.kind, ExprKind::Block(_)));
3089 assert!(matches!(arms[1].body.kind, ExprKind::Return(Some(_))));
3090 }
3091
3092 #[test]
3093 fn await_binds_tighter_than_a_trailing_question_mark() {
3094 let value = tail_expr("await handler(event)?");
3095 let ExprKind::Try(inner) = &value.kind else {
3096 panic!("expected a `?`");
3097 };
3098 let ExprKind::Await(call) = &inner.kind else {
3099 panic!("expected an await");
3100 };
3101 assert!(matches!(call.kind, ExprKind::Call { .. }));
3102 }
3103
3104 #[test]
3105 fn await_alone_has_no_try() {
3106 let value = tail_expr("await handler(event)");
3107 let ExprKind::Await(call) = &value.kind else {
3108 panic!("expected an await");
3109 };
3110 assert!(matches!(call.kind, ExprKind::Call { .. }));
3111 }
3112
3113 #[test]
3114 fn await_binds_tighter_than_binary_operators() {
3115 let sum = tail_expr("await a() + b");
3116 let ExprKind::Binary { op, lhs, .. } = &sum.kind else {
3117 panic!("expected an addition");
3118 };
3119 assert_eq!(*op, BinaryOp::Add);
3120 assert!(matches!(lhs.kind, ExprKind::Await(_)));
3121 }
3122
3123 #[test]
3128 fn await_with_a_question_mark_mid_chain_keeps_it_inside_the_chain() {
3129 let value = tail_expr("await f()?.g()");
3130 let ExprKind::Await(inner) = &value.kind else {
3131 panic!("expected an await");
3132 };
3133 let ExprKind::Call { callee, .. } = &inner.kind else {
3134 panic!("expected a call to `g`");
3135 };
3136 let ExprKind::Field { base, name } = &callee.kind else {
3137 panic!("expected a field access");
3138 };
3139 assert_eq!(name.node, "g");
3140 let ExprKind::Try(call) = &base.kind else {
3141 panic!("expected a `?`");
3142 };
3143 assert!(matches!(call.kind, ExprKind::Call { .. }));
3144 }
3145
3146 #[test]
3147 fn await_is_also_an_ordinary_member_name() {
3148 let value = tail_expr("bookings.await()?");
3149 let ExprKind::Try(call) = &value.kind else {
3150 panic!("expected a `?`");
3151 };
3152 let ExprKind::Call { callee, .. } = &call.kind else {
3153 panic!("expected a call");
3154 };
3155 let ExprKind::Field { name, .. } = &callee.kind else {
3156 panic!("expected a field");
3157 };
3158 assert_eq!(name.node, "await");
3159 }
3160
3161 #[test]
3162 fn ranges_are_distinct_from_float_literals() {
3163 let exclusive = tail_expr("0..<attempts");
3164 let ExprKind::Range { inclusive_end, .. } = &exclusive.kind else {
3165 panic!("expected a range");
3166 };
3167 assert!(!inclusive_end);
3168
3169 let inclusive = tail_expr("0..count");
3170 let ExprKind::Range { inclusive_end, .. } = &inclusive.kind else {
3171 panic!("expected a range");
3172 };
3173 assert!(inclusive_end);
3174
3175 assert!(matches!(tail_expr("0.5").kind, ExprKind::Float(_)));
3176 assert!(matches!(tail_expr("500ms").kind, ExprKind::Duration(_)));
3177 }
3178
3179 #[test]
3180 fn precedence_runs_from_assignment_to_postfix() {
3181 let value = tail_expr("total = a + b * c == d && e || f");
3182 let ExprKind::Assign { op, value, .. } = &value.kind else {
3183 panic!("expected an assignment");
3184 };
3185 assert!(op.is_none());
3186 assert!(matches!(
3187 value.kind,
3188 ExprKind::Binary {
3189 op: BinaryOp::Or,
3190 ..
3191 }
3192 ));
3193
3194 let compound = tail_expr("self.requests += 1");
3195 let ExprKind::Assign { op, target, .. } = &compound.kind else {
3196 panic!("expected an assignment");
3197 };
3198 assert_eq!(*op, Some(BinaryOp::Add));
3199 assert!(matches!(target.kind, ExprKind::Field { .. }));
3200
3201 let unary = tail_expr("!ready");
3202 assert!(matches!(
3203 unary.kind,
3204 ExprKind::Unary {
3205 op: UnaryOp::Not,
3206 ..
3207 }
3208 ));
3209 }
3210
3211 #[test]
3212 fn parses_is_at_the_same_precedence_as_comparison() {
3213 let value = tail_expr("a is b && c == d");
3214 let ExprKind::Binary {
3215 op: BinaryOp::And,
3216 lhs,
3217 rhs,
3218 } = &value.kind
3219 else {
3220 panic!("expected `&&` at the top, binding `is` and `==` tighter");
3221 };
3222 assert!(matches!(
3223 lhs.kind,
3224 ExprKind::Binary {
3225 op: BinaryOp::Is,
3226 ..
3227 }
3228 ));
3229 assert!(matches!(
3230 rhs.kind,
3231 ExprKind::Binary {
3232 op: BinaryOp::Eq,
3233 ..
3234 }
3235 ));
3236 }
3237
3238 #[test]
3239 fn parses_primary_expression_forms() {
3240 assert!(matches!(tail_expr("()").kind, ExprKind::Unit));
3241 assert!(matches!(tail_expr("(1 + 2)").kind, ExprKind::Binary { .. }));
3242 assert!(matches!(tail_expr("[1, 2]").kind, ExprKind::ArrayLit(_)));
3243 assert!(matches!(tail_expr("[]").kind, ExprKind::ArrayLit(_)));
3244 assert!(matches!(tail_expr("self").kind, ExprKind::Ident(_)));
3245 assert!(matches!(tail_expr("return").kind, ExprKind::Return(None)));
3246 assert!(matches!(tail_expr("break").kind, ExprKind::Break(None)));
3247 assert!(matches!(
3248 tail_expr("break 1").kind,
3249 ExprKind::Break(Some(_))
3250 ));
3251 assert!(matches!(tail_expr("continue").kind, ExprKind::Continue));
3252 assert!(matches!(tail_expr("{ 1 }").kind, ExprKind::Block(_)));
3253 assert!(matches!(
3254 tail_expr("scope tasks { 1 }").kind,
3255 ExprKind::Scope { .. }
3256 ));
3257 }
3258
3259 #[test]
3260 fn parses_lambda_forms() {
3261 let plain = tail_expr("fn(request) { request }");
3262 let ExprKind::Lambda {
3263 is_async, params, ..
3264 } = &plain.kind
3265 else {
3266 panic!("expected a lambda");
3267 };
3268 assert!(!is_async);
3269 assert_eq!(params.len(), 1);
3270 assert!(params[0].ty.is_none());
3271
3272 let mutating = tail_expr("fn(var metrics) { metrics }");
3273 let ExprKind::Lambda { params, .. } = &mutating.kind else {
3274 panic!("expected a lambda");
3275 };
3276 assert!(params[0].is_var);
3277
3278 let parameterless = tail_expr("async fn { 1 }");
3279 let ExprKind::Lambda {
3280 is_async, params, ..
3281 } = ¶meterless.kind
3282 else {
3283 panic!("expected a lambda");
3284 };
3285 assert!(is_async);
3286 assert!(params.is_empty());
3287 }
3288
3289 #[test]
3290 fn blocks_take_their_last_expression_as_a_value() {
3291 let unit = ok("fn f() -> Int {\n let a = 1\n a + 1\n}");
3292 let body = &fn_decl(&unit.items[0]).body;
3293 assert_eq!(body.statements.len(), 1);
3294 assert!(matches!(body.statements[0].kind, StmtKind::Let { .. }));
3295 assert!(matches!(
3296 body.tail.as_deref().map(|value| &value.kind),
3297 Some(ExprKind::Binary { .. })
3298 ));
3299
3300 let unit = ok("fn f() {\n a()\n b()\n}");
3301 let body = &fn_decl(&unit.items[0]).body;
3302 assert_eq!(body.statements.len(), 1);
3303 assert!(body.tail.is_some());
3304
3305 let unit = ok("fn f() {\n let a = 1\n}");
3306 let body = &fn_decl(&unit.items[0]).body;
3307 assert_eq!(body.statements.len(), 1);
3308 assert!(body.tail.is_none());
3309 }
3310
3311 #[test]
3312 fn statements_include_bindings_and_nested_items() {
3313 let unit = ok("fn f() {\n let a: Int = 1\n var b = 2\n fn helper() {}\n helper()\n}");
3314 let body = &fn_decl(&unit.items[0]).body;
3315 assert!(matches!(
3316 &body.statements[0].kind,
3317 StmtKind::Let {
3318 is_var: false,
3319 ty: Some(_),
3320 ..
3321 }
3322 ));
3323 assert!(matches!(
3324 body.statements[1].kind,
3325 StmtKind::Let { is_var: true, .. }
3326 ));
3327 assert!(matches!(body.statements[2].kind, StmtKind::Item(_)));
3328 assert!(body.tail.is_some());
3329 }
3330
3331 #[test]
3332 fn parses_string_interpolation() {
3333 let value = tail_expr("\"Hello, {name}! {a + b}\"");
3334 let ExprKind::Str(parts) = &value.kind else {
3335 panic!("expected a string");
3336 };
3337 assert_eq!(parts.len(), 4);
3338 assert!(matches!(&parts[0], StrPart::Text(text) if text == "Hello, "));
3339 assert!(matches!(
3340 &parts[1],
3341 StrPart::Interpolation(Expr {
3342 kind: ExprKind::Ident(_),
3343 ..
3344 })
3345 ));
3346 assert!(matches!(
3347 &parts[3],
3348 StrPart::Interpolation(Expr {
3349 kind: ExprKind::Binary { .. },
3350 ..
3351 })
3352 ));
3353 }
3354
3355 #[test]
3356 fn interpolation_spans_are_rebased_onto_the_original_file() {
3357 let source = "fn main() {\n \"count: {name}\"\n}";
3358 let unit = ok(source);
3359 let tail = fn_decl(&unit.items[0]).body.tail.as_deref().unwrap();
3360 let ExprKind::Str(parts) = &tail.kind else {
3361 panic!("expected a string");
3362 };
3363 let StrPart::Interpolation(value) = &parts[1] else {
3364 panic!("expected an interpolation");
3365 };
3366 let start = source.find("name").unwrap() as u32;
3367 assert_eq!(value.span.start, start);
3368 assert_eq!(value.span.end, start + 4);
3369 }
3370
3371 #[test]
3372 fn diagnostics_inside_an_interpolation_point_into_the_original_file() {
3373 let source = "fn main() {\n \"count: {name ] rest}\"\n}";
3374 let diagnostics = errors(source);
3375 assert_eq!(codes(&diagnostics), ["cove::parse::unexpected_token"]);
3376 let span = diagnostics[0].primary.expect("a primary span");
3377 assert_eq!(span.start as usize, source.find(']').unwrap());
3378 assert_eq!(span.file, FileId(0));
3379 }
3380
3381 #[test]
3382 fn empty_interpolation_is_an_error() {
3383 let diagnostics = errors("fn main() { \"a { } b\" }");
3384 assert_eq!(codes(&diagnostics), ["cove::parse::empty_interpolation"]);
3385 }
3386
3387 #[test]
3388 fn recovers_from_a_broken_statement_and_keeps_parsing() {
3389 let diagnostics = errors("fn a() { let = 1 }\nfn b() { let = 2 }");
3390 assert_eq!(
3391 codes(&diagnostics),
3392 [
3393 "cove::parse::unexpected_token",
3394 "cove::parse::unexpected_token"
3395 ]
3396 );
3397 }
3398
3399 #[test]
3400 fn recovers_from_a_broken_item_at_the_next_declaration() {
3401 let diagnostics = errors("fn a( {}\nstruct S { x: Int }\nenum E { A }\nfn ! {}");
3402 assert_eq!(diagnostics.len(), 2);
3403 assert!(diagnostics
3404 .iter()
3405 .all(|d| d.code == "cove::parse::unexpected_token"));
3406 }
3407
3408 #[test]
3409 fn reports_a_statement_that_is_not_a_declaration_at_the_top_level() {
3410 let diagnostics = errors("let x = 1\nfn a() {}");
3411 assert_eq!(codes(&diagnostics), ["cove::parse::unexpected_token"]);
3412 assert!(diagnostics[0].message.contains("expected a declaration"));
3413 }
3414
3415 #[test]
3416 fn rejects_assignment_to_a_non_place() {
3417 let diagnostics = errors("fn a() { f() = 1 }");
3418 assert_eq!(
3419 codes(&diagnostics),
3420 ["cove::parse::invalid_assignment_target"]
3421 );
3422 }
3423
3424 #[test]
3425 fn reports_several_independent_errors_in_one_run() {
3426 let diagnostics = errors("fn a() { f(x: 1, 2) }\n/// dangling\n1\nfn b() { let = 1 }");
3427 assert_eq!(
3428 codes(&diagnostics),
3429 [
3430 "cove::parse::positional_after_label",
3431 "cove::parse::dangling_doc_comment",
3432 "cove::parse::unexpected_token"
3433 ]
3434 );
3435 }
3436
3437 #[test]
3438 fn unexpected_token_names_what_was_expected_and_found() {
3439 let diagnostics = errors("fn a(1) {}");
3440 assert_eq!(
3441 diagnostics[0].message,
3442 "expected identifier, found integer literal"
3443 );
3444 }
3445
3446 fn body_stmts(source: &str) -> Vec<Stmt> {
3450 let unit = ok(&format!("fn main() {{\n{source}\n}}"));
3451 let body = fn_decl(&unit.items[0]).body.clone();
3452 let mut statements = body.statements;
3453 if let Some(tail) = body.tail {
3454 statements.push(Stmt {
3455 span: tail.span,
3456 kind: StmtKind::Expr(*tail),
3457 });
3458 }
3459 statements
3460 }
3461
3462 fn stmt_expr(stmt: &Stmt) -> &Expr {
3463 match &stmt.kind {
3464 StmtKind::Expr(value) => value,
3465 other => panic!("expected an expression statement, found {other:?}"),
3466 }
3467 }
3468
3469 #[test]
3470 fn a_newline_ends_a_call_statement() {
3471 let statements = body_stmts("println(\"x\")\n()");
3472 assert_eq!(statements.len(), 2);
3473 assert!(matches!(
3474 stmt_expr(&statements[0]).kind,
3475 ExprKind::Call { .. }
3476 ));
3477 assert!(matches!(stmt_expr(&statements[1]).kind, ExprKind::Unit));
3478 }
3479
3480 #[test]
3481 fn a_newline_ends_a_statement_before_a_block() {
3482 let statements = body_stmts("let n = compute()\n{ n }");
3483 assert_eq!(statements.len(), 2);
3484 let StmtKind::Let { value, .. } = &statements[0].kind else {
3485 panic!("expected a binding");
3486 };
3487 assert!(matches!(value.kind, ExprKind::Call { trailing: None, .. }));
3488 assert!(matches!(stmt_expr(&statements[1]).kind, ExprKind::Block(_)));
3489 }
3490
3491 #[test]
3492 fn a_newline_ends_a_match_arm_body() {
3493 let value = tail_expr(
3494 "match x {\n 1 => \"one\"\n -1 => \"minus one\"\n 2 => \"two\"\n _ => \"other\"\n}",
3495 );
3496 let ExprKind::Match { arms, .. } = &value.kind else {
3497 panic!("expected a match");
3498 };
3499 assert_eq!(arms.len(), 4);
3500 let PatternKind::Literal(literal) = &arms[1].pattern.kind else {
3501 panic!("expected a literal pattern");
3502 };
3503 assert!(matches!(
3504 literal.kind,
3505 ExprKind::Unary {
3506 op: UnaryOp::Neg,
3507 ..
3508 }
3509 ));
3510 for arm in arms {
3511 assert!(matches!(arm.body.kind, ExprKind::Str(_)));
3512 }
3513 }
3514
3515 #[test]
3519 fn a_newline_ends_a_break_that_has_no_operand() {
3520 let statements = body_stmts("break\nseen = 99");
3521 assert_eq!(statements.len(), 2);
3522 assert!(matches!(
3523 stmt_expr(&statements[0]).kind,
3524 ExprKind::Break(None)
3525 ));
3526 assert!(matches!(
3527 stmt_expr(&statements[1]).kind,
3528 ExprKind::Assign { .. }
3529 ));
3530 }
3531
3532 #[test]
3535 fn a_newline_ends_a_return_that_has_no_operand() {
3536 let statements = body_stmts("return\nanswer = 99");
3537 assert_eq!(statements.len(), 2);
3538 assert!(matches!(
3539 stmt_expr(&statements[0]).kind,
3540 ExprKind::Return(None)
3541 ));
3542 assert!(matches!(
3543 stmt_expr(&statements[1]).kind,
3544 ExprKind::Assign { .. }
3545 ));
3546 }
3547
3548 #[test]
3552 fn a_newline_ends_a_bare_keyword_before_an_operator() {
3553 for (source, keyword) in [
3554 ("break\n-1", "break"),
3555 ("continue\n-1", "continue"),
3556 ("return\n-1", "return"),
3557 ] {
3558 let statements = body_stmts(source);
3559 assert_eq!(statements.len(), 2, "`{keyword}` swallowed the next line");
3560 assert!(matches!(
3561 stmt_expr(&statements[1]).kind,
3562 ExprKind::Unary {
3563 op: UnaryOp::Neg,
3564 ..
3565 }
3566 ));
3567 }
3568 }
3569
3570 #[test]
3573 fn an_operand_that_starts_on_the_keyword_line_may_span_lines() {
3574 let statements = body_stmts("return someCall(\n a,\n b,\n)");
3575 assert_eq!(statements.len(), 1);
3576 let ExprKind::Return(Some(value)) = &stmt_expr(&statements[0]).kind else {
3577 panic!("expected a `return` with an operand");
3578 };
3579 let ExprKind::Call { args, .. } = &value.kind else {
3580 panic!("expected a call");
3581 };
3582 assert_eq!(args.len(), 2);
3583
3584 let broken = body_stmts("break someCall(\n a,\n b,\n)");
3585 assert_eq!(broken.len(), 1);
3586 let ExprKind::Break(Some(value)) = &stmt_expr(&broken[0]).kind else {
3587 panic!("expected a `break` with an operand");
3588 };
3589 assert!(matches!(value.kind, ExprKind::Call { .. }));
3590 }
3591
3592 #[test]
3595 fn an_operand_on_the_same_line_still_belongs_to_the_keyword() {
3596 let broken = body_stmts("break value");
3597 assert_eq!(broken.len(), 1);
3598 assert!(matches!(
3599 stmt_expr(&broken[0]).kind,
3600 ExprKind::Break(Some(_))
3601 ));
3602
3603 let returned = body_stmts("return value");
3604 assert_eq!(returned.len(), 1);
3605 assert!(matches!(
3606 stmt_expr(&returned[0]).kind,
3607 ExprKind::Return(Some(_))
3608 ));
3609 }
3610
3611 #[test]
3615 fn a_group_does_not_let_a_keyword_reach_the_next_line() {
3616 let statements = body_stmts("let f = fn() {\n break\n seen = 99\n}");
3617 assert_eq!(statements.len(), 1);
3618 let StmtKind::Let { value, .. } = &statements[0].kind else {
3619 panic!("expected a binding");
3620 };
3621 let ExprKind::Lambda { body, .. } = &value.kind else {
3622 panic!("expected a lambda");
3623 };
3624 assert_eq!(body.statements.len(), 1);
3625 assert!(matches!(
3626 body.statements[0].kind,
3627 StmtKind::Expr(Expr {
3628 kind: ExprKind::Break(None),
3629 ..
3630 })
3631 ));
3632 }
3633
3634 #[test]
3637 fn a_method_chain_may_be_split_across_lines() {
3638 let statements = body_stmts("let result = value\n .map(f)\n .unwrapOr(0)");
3639 assert_eq!(statements.len(), 1);
3640 let StmtKind::Let { value, .. } = &statements[0].kind else {
3641 panic!("expected a binding");
3642 };
3643 let ExprKind::Call { callee, .. } = &value.kind else {
3644 panic!("expected a call");
3645 };
3646 let ExprKind::Field { name, .. } = &callee.kind else {
3647 panic!("expected a field");
3648 };
3649 assert_eq!(name.node, "unwrapOr");
3650 }
3651
3652 #[test]
3653 fn newlines_inside_parentheses_and_brackets_do_not_end_a_statement() {
3654 let call = tail_expr("request(\n url: endpoint,\n timeout: 5s\n)");
3655 let ExprKind::Call { args, .. } = &call.kind else {
3656 panic!("expected a call");
3657 };
3658 assert_eq!(args.len(), 2);
3659
3660 let array = tail_expr("[\n 1,\n 2,\n 3\n]");
3661 let ExprKind::ArrayLit(elements) = &array.kind else {
3662 panic!("expected an array literal");
3663 };
3664 assert_eq!(elements.len(), 3);
3665
3666 let parenthesised = tail_expr("(\n 1\n + 2\n)");
3667 assert!(matches!(parenthesised.kind, ExprKind::Binary { .. }));
3668
3669 let generic = tail_expr("api.fetch<\n Array<Booking>\n>(\n \"/bookings\"\n)");
3670 let ExprKind::Call { generics, args, .. } = &generic.kind else {
3671 panic!("expected a call");
3672 };
3673 assert_eq!(generics.len(), 1);
3674 assert_eq!(args.len(), 1);
3675 }
3676
3677 #[test]
3678 fn newlines_inside_declaration_headers_and_field_lists_do_not_end_a_statement() {
3679 let unit = ok("fn f<\n T\n>(\n a: T,\n b: Int = 1\n) -> Int {\n b\n}");
3680 let decl = fn_decl(&unit.items[0]);
3681 assert_eq!(decl.generics.len(), 1);
3682 assert_eq!(decl.params.len(), 2);
3683
3684 let braced = ok("struct S {\n a: Int\n b: Map<\n String,\n Int\n >\n}");
3685 let ItemKind::Struct(decl) = &braced.items[0].kind else {
3686 panic!("expected a struct");
3687 };
3688 assert_eq!(decl.fields.len(), 2);
3689
3690 let parens = ok("struct P(\n a: Int,\n b: Int\n)");
3691 let ItemKind::Struct(decl) = &parens.items[0].kind else {
3692 panic!("expected a struct");
3693 };
3694 assert_eq!(decl.fields.len(), 2);
3695 }
3696
3697 #[test]
3700 fn a_block_inside_a_group_still_ends_statements_at_newlines() {
3701 let call = tail_expr("spawn(fn() {\n a()\n b()\n})");
3702 let ExprKind::Call { args, .. } = &call.kind else {
3703 panic!("expected a call");
3704 };
3705 let ExprKind::Lambda { body, .. } = &args[0].value.kind else {
3706 panic!("expected a lambda");
3707 };
3708 assert_eq!(body.statements.len(), 1);
3709 assert!(body.tail.is_some());
3710 }
3711
3712 #[test]
3713 fn else_attaches_across_a_line_break() {
3714 let plain = tail_expr("if cond {\n}\nelse {\n}");
3715 let ExprKind::If { else_branch, .. } = &plain.kind else {
3716 panic!("expected an if");
3717 };
3718 assert!(matches!(
3719 else_branch.as_deref().map(|value| &value.kind),
3720 Some(ExprKind::Block(_))
3721 ));
3722
3723 let chained = tail_expr("if a {\n}\nelse if b {\n}\nelse {\n}");
3724 let ExprKind::If { else_branch, .. } = &chained.kind else {
3725 panic!("expected an if");
3726 };
3727 assert!(matches!(
3728 else_branch.as_deref().map(|value| &value.kind),
3729 Some(ExprKind::If { .. })
3730 ));
3731 }
3732
3733 #[test]
3734 fn a_match_arm_may_put_its_pattern_body_and_arrow_on_separate_lines() {
3735 let value = tail_expr("match x {\n Ok(v)\n =>\n v\n Err(e) => 0\n}");
3736 let ExprKind::Match { arms, .. } = &value.kind else {
3737 panic!("expected a match");
3738 };
3739 assert_eq!(arms.len(), 2);
3740 assert!(matches!(arms[0].body.kind, ExprKind::Ident(_)));
3741 }
3742
3743 #[test]
3747 fn a_binary_operator_continues_only_from_the_end_of_a_line() {
3748 let continued = tail_expr("a +\n b");
3749 assert!(matches!(continued.kind, ExprKind::Binary { .. }));
3750
3751 let split = errors("fn main() {\n a\n+ b\n}");
3752 assert_eq!(codes(&split), ["cove::parse::newline_ended_statement"]);
3753 assert!(split[0].rule.is_some());
3754 assert!(split[0].help.is_some());
3755
3756 let header = errors("fn main() {\n if a\n && b {\n }\n}");
3759 assert!(header[0].rule.is_some());
3760 assert!(header[0].help.is_some());
3761
3762 let assignment = body_stmts("total =\n 1");
3763 assert_eq!(assignment.len(), 1);
3764 assert!(matches!(
3765 stmt_expr(&assignment[0]).kind,
3766 ExprKind::Assign { .. }
3767 ));
3768 }
3769
3770 #[test]
3773 fn a_leading_minus_starts_a_new_statement() {
3774 let statements = body_stmts("a\n- b");
3775 assert_eq!(statements.len(), 2);
3776 assert!(matches!(
3777 stmt_expr(&statements[1]).kind,
3778 ExprKind::Unary {
3779 op: UnaryOp::Neg,
3780 ..
3781 }
3782 ));
3783 }
3784
3785 #[test]
3786 fn a_detached_trailing_closure_explains_the_newline_rule() {
3787 let diagnostics = errors("fn main() {\n tasks.spawn\n { work() }\n}");
3788 assert_eq!(
3789 codes(&diagnostics),
3790 ["cove::parse::newline_before_trailing_closure"]
3791 );
3792 assert!(diagnostics[0].rule.is_some());
3793 assert!(diagnostics[0].help.is_some());
3794
3795 let attached = tail_expr("tasks.spawn { work() }");
3797 assert!(matches!(
3798 attached.kind,
3799 ExprKind::Call {
3800 trailing: Some(_),
3801 ..
3802 }
3803 ));
3804 }
3805 const OUTER_LEVELS: usize = 2;
3808
3809 #[test]
3810 fn nesting_up_to_the_limit_parses() {
3811 let depth = MAX_NESTING_DEPTH as usize - OUTER_LEVELS;
3812 ok(&format!(
3813 "fn main() {{\n{}1{}\n}}",
3814 "(".repeat(depth),
3815 ")".repeat(depth)
3816 ));
3817 }
3818
3819 #[test]
3824 fn nesting_past_the_limit_is_a_diagnostic() {
3825 let past = MAX_NESTING_DEPTH as usize + 1;
3826 let sources = [
3827 format!(
3828 "fn main() {{\n{}1{}\n}}",
3829 "(".repeat(past),
3830 ")".repeat(past)
3831 ),
3832 format!(
3833 "fn main() {{\n{}1{}\n}}",
3834 "{".repeat(past),
3835 "}".repeat(past)
3836 ),
3837 format!(
3838 "fn main() {{\n{}1{}\n}}",
3839 "[".repeat(past),
3840 "]".repeat(past)
3841 ),
3842 format!("fn main() {{\n{}1\n}}", "-".repeat(past)),
3843 format!("fn main() {{\n a = {}1\n}}", "a = ".repeat(past)),
3844 format!(
3845 "fn f(a: {}Int{}) {{}}",
3846 "Array<".repeat(past),
3847 ">".repeat(past)
3848 ),
3849 format!(
3850 "fn main() {{\n match x {{\n {}y{} => 1\n }}\n}}",
3851 "Some(".repeat(past),
3852 ")".repeat(past)
3853 ),
3854 format!("fn main() {{\n 1{}\n}}", " + 1".repeat(past)),
3857 format!("fn main() {{\n a{}\n}}", ".b".repeat(past)),
3858 format!("fn main() {{\n a{}\n}}", "?".repeat(past)),
3859 ];
3860 for source in sources {
3861 let diagnostics = errors(&source);
3862 let first = &diagnostics[0];
3863 assert_eq!(first.code, "cove::parse::nesting_too_deep");
3864 assert!(first.message.contains("64"), "{}", first.message);
3865 assert!(
3866 first.primary.is_some(),
3867 "the limit reports where it was passed"
3868 );
3869 assert!(
3870 first.rule.is_some(),
3871 "the limit states the rule it enforces"
3872 );
3873 assert!(first.help.is_some(), "the limit says what to do instead");
3874 }
3875 }
3876
3877 #[test]
3881 fn nesting_far_past_the_limit_still_reports_and_returns() {
3882 let past = 100_000;
3883 let source = format!(
3884 "fn main() {{\n{}1{}\n}}",
3885 "(".repeat(past),
3886 ")".repeat(past)
3887 );
3888 let diagnostics = errors(&source);
3889 assert_eq!(codes(&diagnostics), vec!["cove::parse::nesting_too_deep"]);
3890 }
3891
3892 #[test]
3895 fn a_string_of_nothing_but_open_braces_is_a_lexical_error() {
3896 let source = format!("fn main() {{\n \"{}\"\n}}", "{".repeat(100_000));
3897 let diagnostics = errors(&source);
3898 assert_eq!(
3899 codes(&diagnostics),
3900 vec!["cove::lex::unterminated_interpolation"]
3901 );
3902 }
3903
3904 fn collect_cove_files(dir: &Path, out: &mut Vec<PathBuf>) {
3905 let entries = std::fs::read_dir(dir)
3906 .unwrap_or_else(|error| panic!("cannot read {}: {error}", dir.display()));
3907 for entry in entries {
3908 let path = entry.expect("a directory entry").path();
3909 if path.is_dir() {
3910 collect_cove_files(&path, out);
3911 } else if path.extension().is_some_and(|ext| ext == "cove") {
3912 out.push(path);
3913 }
3914 }
3915 }
3916
3917 #[test]
3918 fn every_example_program_parses() {
3919 let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../examples");
3920 let mut files = Vec::new();
3921 collect_cove_files(&root, &mut files);
3922 files.sort();
3923 assert!(
3924 files.len() >= 7,
3925 "expected the example programs to be found"
3926 );
3927
3928 for path in files {
3929 let relative = path
3930 .strip_prefix(&root)
3931 .expect("a path under examples")
3932 .to_string_lossy()
3933 .replace('\\', "/");
3934 let text = std::fs::read_to_string(&path).expect("readable example");
3935 let mut sources = SourceMap::new();
3936 let file = sources.add(path.clone(), text);
3937 let result = crate::parse_file(&sources, file);
3938 if let Err(diagnostics) = result {
3939 let rendered: String = diagnostics
3940 .iter()
3941 .map(|diagnostic| cove_diag::render(&sources, diagnostic))
3942 .collect();
3943 panic!("{relative} failed to parse:\n{rendered}");
3944 }
3945 }
3946 }
3947}