1use crate::ast::{
60 EnumDef, FieldDef, ImportSpec, ImportSpecifier, ImportStatement, Member, MonDocument, MonValue,
61 MonValueKind, Pair, StructDef, TypeDef, TypeDefinition, TypeSpec,
62};
63use crate::error::{MonError, ParserError};
64use crate::lexer::{Lexer, Token, TokenType};
65use miette::{GraphicalReportHandler, NamedSource, Report};
66use std::panic::Location;
67use std::sync::Arc;
68
69#[derive(Debug)]
110pub struct Parser<'a> {
111 source: Arc<NamedSource<String>>,
112 tokens: Vec<Token>,
113 position: usize,
114 source_text: &'a str,
115}
116
117impl<'a> Parser<'a> {
118 pub fn new(source_text: &'a str) -> Result<Self, MonError> {
130 Self::new_with_name(source_text, "source.mon".to_string())
131 }
132
133 pub fn new_with_name(source_text: &'a str, name: String) -> Result<Self, MonError> {
146 let source = Arc::new(NamedSource::new(name, source_text.to_string()));
147 let mut lexer = Lexer::new(source_text);
148 let tokens: Vec<Token> = lexer
149 .lex()
150 .into_iter()
151 .filter(|t| !matches!(t.ttype, TokenType::Whitespace | TokenType::Comment(_)))
152 .collect();
153
154 Ok(Self {
155 source,
156 tokens,
157 position: 0,
158 source_text,
159 })
160 }
161
162 pub fn parse_document(&mut self) -> Result<MonDocument, MonError> {
173 let mut imports: Vec<ImportStatement> = Vec::new();
174
175 while self.check(&TokenType::Import) {
177 let imp = self.parse_import_statement()?;
178 imports.push(imp);
179 }
180
181 let root = self.parse_object()?;
183
184 self.expect(&TokenType::Eof)?;
186 Ok(MonDocument { root, imports })
187 }
188
189 fn parse_object(&mut self) -> Result<MonValue, MonError> {
192 let start_token = self.current_token()?.clone();
193 self.expect(&TokenType::LBrace)?;
194 let mut members = Vec::new();
195 if !self.check(&TokenType::RBrace) {
196 members.push(self.parse_member()?);
198 while self.match_token(&TokenType::Comma) {
200 if self.check(&TokenType::RBrace) {
202 break;
203 }
204 members.push(self.parse_member()?);
205 }
206 }
207 let end_token = self.current_token()?.clone();
208 self.expect(&TokenType::RBrace)?;
209 Ok(MonValue {
210 kind: MonValueKind::Object(members),
211 anchor: None, pos_start: start_token.pos_start,
213 pos_end: end_token.pos_end,
214 })
215 }
216
217 fn parse_array(&mut self) -> Result<MonValue, MonError> {
220 let start_token = self.current_token()?.clone();
221 self.expect(&TokenType::LBracket)?;
222 let mut values = Vec::new();
223 if !self.check(&TokenType::RBracket) {
224 loop {
225 if self.check(&TokenType::Spread) {
226 let spread_start_token = self.current_token()?.clone();
227 let spread_name = self.parse_spread()?;
228 let spread_end_token = self.current_token_before_advance()?.clone(); values.push(MonValue {
230 kind: MonValueKind::ArraySpread(spread_name),
231 anchor: None,
232 pos_start: spread_start_token.pos_start,
233 pos_end: spread_end_token.pos_end,
234 });
235 } else {
236 values.push(self.parse_value()?);
237 }
238
239 if !self.match_token(&TokenType::Comma) {
240 break;
241 }
242 if self.check(&TokenType::RBracket) {
243 break; }
245 }
246 }
247 let end_token = self.current_token()?.clone();
248 self.expect(&TokenType::RBracket)?;
249 Ok(MonValue {
250 kind: MonValueKind::Array(values),
251 anchor: None,
252 pos_start: start_token.pos_start,
253 pos_end: end_token.pos_end,
254 })
255 }
256
257 fn parse_value(&mut self) -> Result<MonValue, MonError> {
260 let anchor = self.parse_optional_anchor()?;
261
262 let start_token = self.current_token()?.clone(); let mut value = match &start_token.ttype.clone() {
265 TokenType::LBrace => self.parse_object(),
267 TokenType::LBracket => self.parse_array(),
268 TokenType::String(s) => {
269 self.advance();
270 Ok(MonValue {
271 kind: MonValueKind::String(s.clone()),
272 anchor: None,
273 pos_start: start_token.pos_start,
274 pos_end: start_token.pos_end,
275 })
276 }
277 TokenType::Number(n) => {
278 self.advance();
279 Ok(MonValue {
280 kind: MonValueKind::Number(*n),
281 anchor: None,
282 pos_start: start_token.pos_start,
283 pos_end: start_token.pos_end,
284 })
285 }
286 TokenType::True => {
287 self.advance();
288 Ok(MonValue {
289 kind: MonValueKind::Boolean(true),
290 anchor: None,
291 pos_start: start_token.pos_start,
292 pos_end: start_token.pos_end,
293 })
294 }
295 TokenType::False => {
296 self.advance();
297 Ok(MonValue {
298 kind: MonValueKind::Boolean(false),
299 anchor: None,
300 pos_start: start_token.pos_start,
301 pos_end: start_token.pos_end,
302 })
303 }
304 TokenType::Null => {
305 self.advance();
306 Ok(MonValue {
307 kind: MonValueKind::Null,
308 anchor: None,
309 pos_start: start_token.pos_start,
310 pos_end: start_token.pos_end,
311 })
312 }
313 TokenType::Asterisk => self.parse_alias(),
314 TokenType::Dollar => self.parse_enum_value(),
315 _ => self.err_unexpected("a value"),
316 }?;
317
318 value.anchor = anchor;
319 Ok(value)
320 }
321
322 fn parse_member(&mut self) -> Result<Member, MonError> {
324 match self.current_token()?.ttype {
325 TokenType::Spread => self.parse_spread().map(Member::Spread),
326 TokenType::Identifier(_)
328 if self.peek_is(&TokenType::Colon) && self.peek_next_is(&TokenType::Hash) =>
329 {
330 self.parse_type_definition().map(Member::TypeDefinition)
331 }
332 _ => self.parse_pair().map(Member::Pair),
334 }
335 }
336
337 fn parse_pair(&mut self) -> Result<Pair, MonError> {
341 let mut anchor_from_key: Option<String> = None;
342
343 let key = if self.match_token(&TokenType::Ampersand) {
345 let key_name = self.parse_key()?;
346 anchor_from_key = Some(key_name.clone());
347 key_name
348 } else {
349 self.parse_key()?
350 };
351
352 let validation = self.parse_optional_validation()?;
353
354 if !self.match_token(&TokenType::Colon) && !self.match_token(&TokenType::Equals) {
355 return self.err_unexpected("':' or '=' after key");
356 }
357
358 let mut value = self.parse_value()?;
359
360 if let Some(anchor_name) = anchor_from_key {
364 value.anchor = Some(anchor_name);
365 }
366
367 Ok(Pair {
368 key,
369 value,
370 validation,
371 })
372 }
373
374 fn parse_key(&mut self) -> Result<String, MonError> {
378 let token = self.current_token()?;
379 let mut key_parts = Vec::new();
380
381 match &token.ttype {
382 TokenType::Identifier(s) | TokenType::String(s) => {
383 key_parts.push(s.clone());
384 self.advance();
385 }
386 _ => return self.err_unexpected("an identifier or string for a key"),
387 }
388
389 while self.match_token(&TokenType::Dot) {
391 let token = self.current_token()?;
392 if let TokenType::Identifier(s) = &token.ttype {
393 key_parts.push(s.clone());
394 self.advance();
395 } else {
396 return self.err_unexpected("an identifier after a dot in a key");
397 }
398 }
399
400 Ok(key_parts.join("."))
401 }
402
403 fn parse_optional_anchor(&mut self) -> Result<Option<String>, MonError> {
405 if self.match_token(&TokenType::Ampersand) {
406 let token = self.current_token()?;
407 if let TokenType::Identifier(name) = &token.ttype {
408 let name = name.clone();
409 self.advance();
410 Ok(Some(name))
411 } else {
412 self.err_unexpected("an identifier for the anchor name")
413 }
414 } else {
415 Ok(None)
416 }
417 }
418
419 fn parse_alias(&mut self) -> Result<MonValue, MonError> {
421 let start_token = self.current_token()?.clone();
422 self.expect(&TokenType::Asterisk)?;
423 let mut name = self.parse_key()?;
424 let mut end_pos = self.current_token_before_advance()?.pos_end; while self.match_token(&TokenType::Dot) {
427 name.push('.');
428 let key_part = self.parse_key()?;
429 end_pos = self.current_token_before_advance()?.pos_end; name.push_str(&key_part);
431 }
432 Ok(MonValue {
433 kind: MonValueKind::Alias(name),
434 anchor: None,
435 pos_start: start_token.pos_start,
436 pos_end: end_pos,
437 })
438 }
439
440 fn parse_spread(&mut self) -> Result<String, MonError> {
442 self.expect(&TokenType::Spread)?;
443 let alias = self.parse_alias()?;
444 if let MonValueKind::Alias(name) = alias.kind {
445 Ok(name)
446 } else {
447 self.err_unexpected("an alias after '...' ")
449 }
450 }
451
452 fn parse_import_statement(&mut self) -> Result<ImportStatement, MonError> {
454 let start_token = self.current_token()?.clone(); self.expect(&TokenType::Import)?;
456
457 let spec = if self.match_token(&TokenType::Asterisk) {
458 self.expect(&TokenType::As)?;
460 let name = self.parse_key()?;
461 ImportSpec::Namespace(name)
462 } else {
463 self.expect(&TokenType::LBrace)?;
465 let mut specifiers = Vec::new();
466 if !self.check(&TokenType::RBrace) {
467 loop {
468 let is_anchor = self.match_token(&TokenType::Ampersand);
470 let name = self.parse_key()?;
471 specifiers.push(ImportSpecifier { name, is_anchor });
472 if !self.match_token(&TokenType::Comma) {
473 break;
474 }
475 if self.check(&TokenType::RBrace) {
476 break;
477 }
478 }
479 }
480 self.expect(&TokenType::RBrace)?;
481 ImportSpec::Named(specifiers)
482 };
483
484 self.expect(&TokenType::From)?;
485 let path_token = self.current_token()?.clone(); let path = self.parse_key()?;
487
488 Ok(ImportStatement {
489 path,
490 spec,
491 pos_start: start_token.pos_start,
492 pos_end: path_token.pos_end,
493 })
494 }
495
496 fn parse_type_definition(&mut self) -> Result<TypeDefinition, MonError> {
498 let name_token = self.current_token()?.clone();
499 let name = self.parse_key()?;
500 self.expect(&TokenType::Colon)?;
501 let hash_token = self.current_token()?.clone();
502 self.expect(&TokenType::Hash)?;
503
504 let token = self.current_token()?;
505 let (def_type, end_pos) = match &token.ttype {
506 TokenType::Identifier(s) if s == "struct" => {
507 self.advance();
508 let mut struct_def = self.parse_struct_definition()?;
509 let end_pos = struct_def.pos_end;
510 struct_def.pos_start = hash_token.pos_start;
511 Ok((TypeDef::Struct(struct_def), end_pos))
512 }
513 TokenType::Identifier(s) if s == "enum" => {
514 self.advance();
515 let mut enum_def = self.parse_enum_definition()?;
516 let end_pos = enum_def.pos_end;
517 enum_def.pos_start = hash_token.pos_start;
518 Ok((TypeDef::Enum(enum_def), end_pos))
519 }
520 _ => self.err_unexpected("'struct' or 'enum' keyword"),
521 }?;
522
523 Ok(TypeDefinition {
524 name,
525 name_span: (
526 name_token.pos_start,
527 name_token.pos_end - name_token.pos_start,
528 )
529 .into(),
530 def_type,
531 pos_start: name_token.pos_start,
532 pos_end: end_pos,
533 })
534 }
535
536 fn parse_struct_definition(&mut self) -> Result<StructDef, MonError> {
538 let start_token = self.current_token()?.clone();
539 self.expect(&TokenType::LBrace)?;
540 let mut fields = Vec::new();
541 if !self.check(&TokenType::RBrace) {
542 loop {
543 fields.push(self.parse_field_definition()?);
544 if !self.match_token(&TokenType::Comma) {
545 break;
546 }
547 if self.check(&TokenType::RBrace) {
548 break;
549 }
550 }
551 }
552 let end_token = self.current_token()?.clone();
553 self.expect(&TokenType::RBrace)?;
554 Ok(StructDef {
555 fields,
556 pos_start: start_token.pos_start,
557 pos_end: end_token.pos_end,
558 })
559 }
560
561 fn parse_field_definition(&mut self) -> Result<FieldDef, MonError> {
563 let name = self.parse_key()?;
564 self.expect(&TokenType::LParen)?;
565 let type_spec = self.parse_type_spec()?;
566 self.expect(&TokenType::RParen)?;
567
568 let default_value = if self.match_token(&TokenType::Equals) {
569 Some(self.parse_value()?)
570 } else {
571 None
572 };
573
574 Ok(FieldDef {
575 name,
576 type_spec,
577 default_value,
578 })
579 }
580
581 fn parse_enum_definition(&mut self) -> Result<EnumDef, MonError> {
583 let start_token = self.current_token()?.clone();
584 self.expect(&TokenType::LBrace)?;
585 let mut variants = Vec::new();
586 if !self.check(&TokenType::RBrace) {
587 loop {
588 variants.push(self.parse_key()?);
589 if !self.match_token(&TokenType::Comma) {
590 break;
591 }
592 if self.check(&TokenType::RBrace) {
593 break;
594 }
595 }
596 }
597 let end_token = self.current_token()?.clone();
598 self.expect(&TokenType::RBrace)?;
599 Ok(EnumDef {
600 variants,
601 pos_start: start_token.pos_start,
602 pos_end: end_token.pos_end,
603 })
604 }
605
606 fn parse_optional_validation(&mut self) -> Result<Option<TypeSpec>, MonError> {
608 if self.match_token(&TokenType::DoubleColon) {
609 self.parse_type_spec().map(Some)
610 } else {
611 Ok(None)
612 }
613 }
614
615 fn parse_type_spec(&mut self) -> Result<TypeSpec, MonError> {
617 let start_token = self.current_token()?.clone();
618 if self.check(&TokenType::LBracket) {
619 self.expect(&TokenType::LBracket)?;
621 let mut types = Vec::new();
622 if !self.check(&TokenType::RBracket) {
623 loop {
624 let mut type_spec = self.parse_type_spec()?;
625 if self.match_token(&TokenType::Spread) {
626 let end_token = self.current_token_before_advance()?.clone();
627 let span = (
628 type_spec.get_span().offset(),
629 end_token.pos_end - type_spec.get_span().offset(),
630 )
631 .into();
632 type_spec = TypeSpec::Spread(Box::new(type_spec), span);
633 }
634 types.push(type_spec);
635
636 if !self.match_token(&TokenType::Comma) {
637 break;
638 }
639 if self.check(&TokenType::RBracket) {
640 break;
641 }
642 }
643 }
644 let end_token = self.current_token()?.clone();
645 self.expect(&TokenType::RBracket)?;
646 let span = (
647 start_token.pos_start,
648 end_token.pos_end - start_token.pos_start,
649 )
650 .into();
651 Ok(TypeSpec::Collection(types, span))
652 } else {
653 let name = self.parse_key()?;
655 let end_token = self.current_token_before_advance()?.clone();
656 let span = (
657 start_token.pos_start,
658 end_token.pos_end - start_token.pos_start,
659 )
660 .into();
661 Ok(TypeSpec::Simple(name, span))
662 }
663 }
664
665 fn parse_enum_value(&mut self) -> Result<MonValue, MonError> {
667 let start_token = self.current_token()?.clone();
668 self.expect(&TokenType::Dollar)?;
669
670 let enum_token = self.current_token()?.clone();
672 let enum_name = if let TokenType::Identifier(s) = &enum_token.ttype {
673 let s = s.clone();
674 self.advance();
675 s
676 } else {
677 return self.err_unexpected("an identifier for enum name");
678 };
679
680 self.expect(&TokenType::Dot)?;
681
682 let variant_token = self.current_token()?.clone();
684 let variant_name = if let TokenType::Identifier(s) = &variant_token.ttype {
685 let s = s.clone();
686 self.advance();
687 s
688 } else {
689 return self.err_unexpected("an identifier for enum variant");
690 };
691
692 Ok(MonValue {
693 kind: MonValueKind::EnumValue {
694 enum_name,
695 variant_name,
696 },
697 anchor: None,
698 pos_start: start_token.pos_start,
699 pos_end: variant_token.pos_end,
700 })
701 }
702
703 fn current_token(&self) -> Result<&Token, MonError> {
706 self.tokens.get(self.position).ok_or_else(|| {
707 let pos = self.source_text.len().saturating_sub(1);
708 ParserError::UnexpectedEof {
709 src: (*self.source).clone().into(), span: (pos, 0).into(),
711 }
712 .into()
713 })
714 }
715
716 fn current_token_before_advance(&self) -> Result<&Token, MonError> {
717 self.tokens
718 .get(self.position.saturating_sub(1))
719 .ok_or_else(|| {
720 let pos = self.source_text.len().saturating_sub(1);
721 ParserError::UnexpectedEof {
722 src: (*self.source).clone().into(),
723 span: (pos, 0).into(),
724 }
725 .into()
726 })
727 }
728
729 fn advance(&mut self) {
730 if self.position < self.tokens.len() {
731 self.position += 1;
732 }
733 }
734
735 #[track_caller]
736 fn expect(&mut self, expected: &TokenType) -> Result<(), MonError> {
737 let token = self.current_token()?.clone();
738 if std::mem::discriminant(&token.ttype) == std::mem::discriminant(expected) {
739 self.advance();
740 Ok(())
741 } else {
742 self.err_unexpected(&format!("{expected:?}"))
743 }
744 }
745
746 fn match_token(&mut self, ttype: &TokenType) -> bool {
747 if self.check(ttype) {
748 self.advance();
749 true
750 } else {
751 false
752 }
753 }
754
755 fn check(&self, ttype: &TokenType) -> bool {
756 if let Ok(token) = self.current_token() {
757 std::mem::discriminant(&token.ttype) == std::mem::discriminant(ttype)
758 } else {
759 false
760 }
761 }
762
763 fn peek_is(&self, ttype: &TokenType) -> bool {
764 if let Some(token) = self.tokens.get(self.position + 1) {
765 std::mem::discriminant(&token.ttype) == std::mem::discriminant(ttype)
766 } else {
767 false
768 }
769 }
770
771 fn peek_next_is(&self, ttype: &TokenType) -> bool {
772 if let Some(token) = self.tokens.get(self.position + 2) {
773 std::mem::discriminant(&token.ttype) == std::mem::discriminant(ttype)
774 } else {
775 false
776 }
777 }
778
779 #[track_caller]
780 fn err_unexpected<T>(&self, expected: &str) -> Result<T, MonError> {
781 let token = self.current_token()?;
782 print!("caller: {}", Location::caller());
783 Err(ParserError::UnexpectedToken {
784 src: (*self.source).clone().into(),
785 span: (token.pos_start, token.pos_end - token.pos_start).into(),
786 expected: expected.to_string(),
787 }
788 .into())
789 }
790}
791
792#[allow(dead_code)]
794fn pretty_result(out: Result<MonDocument, MonError>) -> String {
795 match out {
796 Ok(doc) => format!("{doc:#?}"), Err(err) => {
798 let report: Report = Report::new(err);
799 let handler = GraphicalReportHandler::new(); let mut buffer = String::new();
801 handler.render_report(&mut buffer, &*report).unwrap();
802 buffer
803 }
804 }
805}
806
807#[cfg(test)]
808#[allow(clippy::match_wildcard_for_single_variants)]
809mod tests {
810 use super::*;
811 use miette::Report;
812
813 impl Member {
814 fn unwrap_pair(self) -> Pair {
815 match self {
816 Member::Pair(p) => p,
817 _ => panic!("Expected Pair, got {self:?}"),
818 }
819 }
820 fn unwrap_type_definition(self) -> TypeDefinition {
821 match self {
822 Member::TypeDefinition(td) => td,
823 _ => panic!("Expected TypeDefinition, got {self:?}"),
824 }
825 }
826 }
827
828 impl MonValueKind {
829 fn unwrap_object(self) -> Vec<Member> {
830 match self {
831 MonValueKind::Object(m) => m,
832 _ => panic!("Expected Object, got {self:?}"),
833 }
834 }
835 #[allow(dead_code)]
836 fn unwrap_array(self) -> Vec<MonValue> {
837 match self {
838 MonValueKind::Array(v) => v,
839 _ => panic!("Expected Array, got {self:?}"),
840 }
841 }
842 }
843
844 fn parse_ok(source: &str) -> MonDocument {
845 let mut parser = Parser::new_with_name(source, "test.mon".to_string()).unwrap();
846 match parser.parse_document() {
847 Ok(doc) => doc,
848 Err(err) => {
849 let report = Report::from(err);
850 panic!("Parsing failed when it should have succeeded:\n{report:?}");
851 }
852 }
853 }
854
855 #[test]
856 fn test_empty_object() {
857 let doc = parse_ok("{}");
858 assert_eq!(doc.root.kind, MonValueKind::Object(vec![]));
859 }
860
861 #[test]
862 fn test_simple_pair() {
863 let doc = parse_ok(r#"{ key: "value" }"#);
864 let members = match doc.root.kind {
865 MonValueKind::Object(m) => m,
866 _ => panic!(),
867 };
868 assert_eq!(members.len(), 1);
869 match &members[0] {
870 Member::Pair(p) => {
871 assert_eq!(p.key, "key");
872 assert!(matches!(p.value.kind, MonValueKind::String(_)));
873 }
874 _ => panic!(),
875 }
876 }
877
878 #[test]
879 fn test_anchor_and_alias() {
880 let doc = parse_ok(r#"{ &anchor1 : 123, key2: *anchor1 }"#);
881 let members = match doc.root.kind {
882 MonValueKind::Object(m) => m,
883 _ => panic!(),
884 };
885 assert_eq!(members.len(), 2);
886 match &members[0] {
887 Member::Pair(p) => {
888 assert_eq!(p.key, "anchor1");
889 assert_eq!(p.value.anchor, Some("anchor1".to_string()));
890 }
891 _ => panic!(),
892 }
893 match &members[1] {
894 Member::Pair(p) => {
895 assert_eq!(p.key, "key2");
896 assert!(matches!(p.value.kind, MonValueKind::Alias(_)));
897 }
898 _ => panic!(),
899 }
900 }
901
902 #[test]
903 fn test_spread() {
904 let doc = parse_ok(r#"{ ...*my_anchor }"#);
905 let members = match doc.root.kind {
906 MonValueKind::Object(m) => m,
907 _ => panic!(),
908 };
909 assert_eq!(members.len(), 1);
910 match &members[0] {
911 Member::Spread(name) => assert_eq!(name, "my_anchor"),
912 _ => panic!(),
913 }
914 }
915
916 #[test]
917 fn test_namespace_import() {
918 let doc = parse_ok(
919 r###"import * as schemas from "./schemas.mon"
920{
921 a: 1
922}"###,
923 );
924 assert!(!doc.imports.is_empty());
925 match &doc.imports[0].spec {
926 ImportSpec::Namespace(name) => assert_eq!(name, "schemas"),
927 _ => panic!("Expected namespace import"),
928 }
929 }
930
931 #[test]
932 fn test_trailing_comma_in_object() {
933 let doc = parse_ok("{ a: 1, b: 2, }");
934 let members = match doc.root.kind {
935 MonValueKind::Object(m) => m,
936 _ => panic!(),
937 };
938 assert_eq!(members.len(), 2);
939 }
940
941 #[test]
942 fn test_trailing_comma_in_array() {
943 let doc = parse_ok("{arr: [ 1, 2, ]}");
944 let members = doc.root.kind.unwrap_object();
945 let pair = members[0].clone().unwrap_pair();
946 let values = match pair.value.kind {
947 MonValueKind::Array(v) => v,
948 _ => panic!("Expected Array"),
949 };
950 assert_eq!(values.len(), 2);
951 }
952
953 #[test]
954 fn test_array_with_spread() {
955 let doc = parse_ok("{arr: [ 1, ...*other, 3 ]}");
956 let members = doc.root.kind.unwrap_object();
957 let pair = members[0].clone().unwrap_pair();
958 let values = match pair.value.kind {
959 MonValueKind::Array(v) => v,
960 _ => panic!("Expected Array"),
961 };
962 assert_eq!(values.len(), 3);
963 assert!(matches!(values[0].kind, MonValueKind::Number(_)));
964 assert!(matches!(values[1].kind, MonValueKind::ArraySpread(_)));
965 assert!(matches!(values[2].kind, MonValueKind::Number(_)));
966 }
967
968 #[test]
969 fn test_all_value_types() {
970 let doc = parse_ok(
971 r#"{
972 s: "string",
973 n: 123.45,
974 b1: true,
975 b2: false,
976 nu: null,
977 obj: {},
978 arr: [],
979 alias: *somewhere,
980 enum_val: $MyEnum.Variant
981 }"#,
982 );
983 let members = match doc.root.kind {
984 MonValueKind::Object(m) => m,
985 _ => panic!(),
986 };
987 assert_eq!(members.len(), 9);
988 assert!(matches!(
989 members[0].clone().unwrap_pair().value.kind,
990 MonValueKind::String(_)
991 ));
992 assert!(matches!(
993 members[1].clone().unwrap_pair().value.kind,
994 MonValueKind::Number(_)
995 ));
996 assert!(matches!(
997 members[2].clone().unwrap_pair().value.kind,
998 MonValueKind::Boolean(true)
999 ));
1000 assert!(matches!(
1001 members[3].clone().unwrap_pair().value.kind,
1002 MonValueKind::Boolean(false)
1003 ));
1004 assert!(matches!(
1005 members[4].clone().unwrap_pair().value.kind,
1006 MonValueKind::Null
1007 ));
1008 assert!(matches!(
1009 members[5].clone().unwrap_pair().value.kind,
1010 MonValueKind::Object(_)
1011 ));
1012 assert!(matches!(
1013 members[6].clone().unwrap_pair().value.kind,
1014 MonValueKind::Array(_)
1015 ));
1016 assert!(matches!(
1017 members[7].clone().unwrap_pair().value.kind,
1018 MonValueKind::Alias(_)
1019 ));
1020 assert!(matches!(
1021 members[8].clone().unwrap_pair().value.kind,
1022 MonValueKind::EnumValue { .. }
1023 ));
1024 }
1025
1026 #[test]
1027 fn test_dotted_key() {
1028 let doc = parse_ok(r#"{ a.b.c: 1 }"#);
1029 let pair = doc.root.kind.unwrap_object().remove(0).unwrap_pair();
1030 assert_eq!(pair.key, "a.b.c");
1031 }
1032
1033 #[test]
1034 fn test_string_key() {
1035 let doc = parse_ok(r#"{ "a-b-c": 1 }"#);
1036 let pair = doc.root.kind.unwrap_object().remove(0).unwrap_pair();
1037 assert_eq!(pair.key, "a-b-c");
1038 }
1039
1040 #[test]
1041 fn test_pair_with_equals() {
1042 let doc = parse_ok(r#"{ key = 1 }"#);
1043 let pair = doc.root.kind.unwrap_object().remove(0).unwrap_pair();
1044 assert_eq!(pair.key, "key");
1045 assert!(matches!(pair.value.kind, MonValueKind::Number(_)));
1046 }
1047
1048 #[test]
1049 fn test_named_imports() {
1050 let doc = parse_ok(
1051 r#"import { A, &B, C } from "./types.mon"
1052{
1053 x: 1
1054}"#,
1055 );
1056 assert!(!doc.imports.is_empty());
1057 match &doc.imports[0].spec {
1058 ImportSpec::Named(specifiers) => {
1059 assert_eq!(specifiers.len(), 3);
1060 assert_eq!(specifiers[0].name, "A");
1061 assert!(!specifiers[0].is_anchor);
1062 assert_eq!(specifiers[1].name, "B");
1063 assert!(specifiers[1].is_anchor);
1064 assert_eq!(specifiers[2].name, "C");
1065 assert!(!specifiers[2].is_anchor);
1066 }
1067 _ => panic!("Expected named import"),
1068 }
1069 }
1070
1071 #[test]
1072 fn test_struct_type_definition() {
1073 let doc = parse_ok(
1074 r#"{
1075User: #struct {
1076 name(String),
1077 age(Number) = 30,
1078}
1079}"#,
1080 );
1081 let members = doc.root.kind.unwrap_object();
1082 let td = members[0].clone().unwrap_type_definition();
1083 match td.def_type {
1084 TypeDef::Struct(s) => {
1085 assert_eq!(s.fields.len(), 2);
1086 assert_eq!(s.fields[0].name, "name");
1087 assert!(s.fields[0].default_value.is_none());
1088 assert_eq!(s.fields[1].name, "age");
1089 assert!(s.fields[1].default_value.is_some());
1090 }
1091 _ => panic!("Expected struct definition"),
1092 }
1093 }
1094
1095 #[test]
1096 fn test_enum_type_definition() {
1097 let doc = parse_ok(
1098 r#"{
1099Status: #enum { Active, Inactive, Pending }
1100}"#,
1101 );
1102 let members = doc.root.kind.unwrap_object();
1103 let td = members[0].clone().unwrap_type_definition();
1104 match td.def_type {
1105 TypeDef::Enum(e) => {
1106 assert_eq!(e.variants, vec!["Active", "Inactive", "Pending"]);
1107 }
1108 _ => panic!("Expected enum definition"),
1109 }
1110 }
1111
1112 #[test]
1113 fn test_validation_on_pair() {
1114 let doc = parse_ok(r#"{ key :: Number = 42 }"#);
1115 let pair = doc.root.kind.unwrap_object().remove(0).unwrap_pair();
1116
1117 assert_eq!(
1119 pair.validation.unwrap(),
1120 TypeSpec::Simple("Number".into(), (9, 6).into())
1121 )
1122 }
1123
1124 #[test]
1125 fn test_nested_objects_and_arrays() {
1126 let doc = parse_ok(r#"{ obj: { a: 1, b: 2 }, arr: [1, 2, 3] }"#);
1127 let members = doc.root.kind.unwrap_object();
1128 let obj_val = members[0].clone().unwrap_pair().value;
1129 assert!(matches!(obj_val.kind, MonValueKind::Object(_)));
1130 let arr_val = members[1].clone().unwrap_pair().value;
1131 assert!(matches!(arr_val.kind, MonValueKind::Array(_)));
1132 }
1133
1134 #[test]
1135 fn test_enum_value_in_object() {
1136 let doc = parse_ok(r#"{ status: $Status.Active }"#);
1137 let pair = doc.root.kind.unwrap_object().remove(0).unwrap_pair();
1138 match pair.value.kind {
1139 MonValueKind::EnumValue {
1140 enum_name,
1141 variant_name,
1142 } => {
1143 assert_eq!(enum_name, "Status");
1144 assert_eq!(variant_name, "Active");
1145 }
1146 _ => panic!("Expected enum value"),
1147 }
1148 }
1149
1150 #[test]
1151 fn test_complex_document() {
1152 let doc = parse_ok(
1153 r#"
1154import { &A, B } from "./types.mon"
1155
1156{
1157 &anchor1: { x: 1 },
1158 key2: *anchor1,
1159 list: [1, 2, 3, ...*B],
1160 status: $Status.Active
1161}"#,
1162 );
1163 assert_eq!(doc.imports.len(), 1);
1164 let members = doc.root.kind.unwrap_object();
1165 assert_eq!(members.len(), 4);
1166 }
1167}