1use crate::ast::{
2 EnumDef, FieldDef, ImportSpec, ImportSpecifier, ImportStatement, Member, MonDocument, MonValue,
3 MonValueKind, Pair, StructDef, TypeDef, TypeDefinition, TypeSpec,
4};
5use crate::error::{MonError, ParserError};
6use crate::lexer::{Lexer, Token, TokenType};
7use miette::{GraphicalReportHandler, NamedSource, Report};
8use std::panic::Location;
9use std::sync::Arc;
10
11#[derive(Debug)]
13pub struct Parser<'a> {
14 source: Arc<NamedSource<String>>,
15 tokens: Vec<Token>,
16 position: usize,
17 source_text: &'a str,
18}
19
20impl<'a> Parser<'a> {
21 pub fn new(source_text: &'a str) -> Result<Self, MonError> {
31 Self::new_with_name(source_text, "source.mon".to_string())
32 }
33
34 pub fn new_with_name(source_text: &'a str, name: String) -> Result<Self, MonError> {
45 let source = Arc::new(NamedSource::new(name, source_text.to_string()));
46 let mut lexer = Lexer::new(source_text);
47 let tokens: Vec<Token> = lexer
48 .lex()
49 .into_iter()
50 .filter(|t| !matches!(t.ttype, TokenType::Whitespace | TokenType::Comment(_)))
51 .collect();
52
53 Ok(Self {
54 source,
55 tokens,
56 position: 0,
57 source_text,
58 })
59 }
60
61 pub fn parse_document(&mut self) -> Result<MonDocument, MonError> {
69 let mut imports: Vec<ImportStatement> = Vec::new();
70
71 while self.check(&TokenType::Import) {
73 let imp = self.parse_import_statement()?;
74 imports.push(imp);
75 }
76
77 let root = self.parse_object()?;
79
80 self.expect(&TokenType::Eof)?;
82 Ok(MonDocument { root, imports })
83 }
84
85 fn parse_object(&mut self) -> Result<MonValue, MonError> {
88 let start_token = self.current_token()?.clone();
89 self.expect(&TokenType::LBrace)?;
90 let mut members = Vec::new();
91 if !self.check(&TokenType::RBrace) {
92 members.push(self.parse_member()?);
94 while self.match_token(&TokenType::Comma) {
96 if self.check(&TokenType::RBrace) {
98 break;
99 }
100 members.push(self.parse_member()?);
101 }
102 }
103 let end_token = self.current_token()?.clone();
104 self.expect(&TokenType::RBrace)?;
105 Ok(MonValue {
106 kind: MonValueKind::Object(members),
107 anchor: None, pos_start: start_token.pos_start,
109 pos_end: end_token.pos_end,
110 })
111 }
112
113 fn parse_array(&mut self) -> Result<MonValue, MonError> {
116 let start_token = self.current_token()?.clone();
117 self.expect(&TokenType::LBracket)?;
118 let mut values = Vec::new();
119 if !self.check(&TokenType::RBracket) {
120 loop {
121 if self.check(&TokenType::Spread) {
122 let spread_start_token = self.current_token()?.clone();
123 let spread_name = self.parse_spread()?;
124 let spread_end_token = self.current_token_before_advance()?.clone(); values.push(MonValue {
126 kind: MonValueKind::ArraySpread(spread_name),
127 anchor: None,
128 pos_start: spread_start_token.pos_start,
129 pos_end: spread_end_token.pos_end,
130 });
131 } else {
132 values.push(self.parse_value()?);
133 }
134
135 if !self.match_token(&TokenType::Comma) {
136 break;
137 }
138 if self.check(&TokenType::RBracket) {
139 break; }
141 }
142 }
143 let end_token = self.current_token()?.clone();
144 self.expect(&TokenType::RBracket)?;
145 Ok(MonValue {
146 kind: MonValueKind::Array(values),
147 anchor: None,
148 pos_start: start_token.pos_start,
149 pos_end: end_token.pos_end,
150 })
151 }
152
153 fn parse_value(&mut self) -> Result<MonValue, MonError> {
156 let anchor = self.parse_optional_anchor()?;
157
158 let start_token = self.current_token()?.clone(); let mut value = match &start_token.ttype.clone() {
161 TokenType::LBrace => self.parse_object(),
163 TokenType::LBracket => self.parse_array(),
164 TokenType::String(s) => {
165 self.advance();
166 Ok(MonValue {
167 kind: MonValueKind::String(s.clone()),
168 anchor: None,
169 pos_start: start_token.pos_start,
170 pos_end: start_token.pos_end,
171 })
172 }
173 TokenType::Number(n) => {
174 self.advance();
175 Ok(MonValue {
176 kind: MonValueKind::Number(*n),
177 anchor: None,
178 pos_start: start_token.pos_start,
179 pos_end: start_token.pos_end,
180 })
181 }
182 TokenType::True => {
183 self.advance();
184 Ok(MonValue {
185 kind: MonValueKind::Boolean(true),
186 anchor: None,
187 pos_start: start_token.pos_start,
188 pos_end: start_token.pos_end,
189 })
190 }
191 TokenType::False => {
192 self.advance();
193 Ok(MonValue {
194 kind: MonValueKind::Boolean(false),
195 anchor: None,
196 pos_start: start_token.pos_start,
197 pos_end: start_token.pos_end,
198 })
199 }
200 TokenType::Null => {
201 self.advance();
202 Ok(MonValue {
203 kind: MonValueKind::Null,
204 anchor: None,
205 pos_start: start_token.pos_start,
206 pos_end: start_token.pos_end,
207 })
208 }
209 TokenType::Asterisk => self.parse_alias(),
210 TokenType::Dollar => self.parse_enum_value(),
211 _ => self.err_unexpected("a value"),
212 }?;
213
214 value.anchor = anchor;
215 Ok(value)
216 }
217
218 fn parse_member(&mut self) -> Result<Member, MonError> {
220 match self.current_token()?.ttype {
221 TokenType::Spread => self.parse_spread().map(Member::Spread),
222 TokenType::Identifier(_)
224 if self.peek_is(&TokenType::Colon) && self.peek_next_is(&TokenType::Hash) =>
225 {
226 self.parse_type_definition().map(Member::TypeDefinition)
227 }
228 _ => self.parse_pair().map(Member::Pair),
230 }
231 }
232
233 fn parse_pair(&mut self) -> Result<Pair, MonError> {
237 let mut anchor_from_key: Option<String> = None;
238
239 let key = if self.match_token(&TokenType::Ampersand) {
241 let key_name = self.parse_key()?;
242 anchor_from_key = Some(key_name.clone());
243 key_name
244 } else {
245 self.parse_key()?
246 };
247
248 let validation = self.parse_optional_validation()?;
249
250 if !self.match_token(&TokenType::Colon) && !self.match_token(&TokenType::Equals) {
251 return self.err_unexpected("':' or '=' after key");
252 }
253
254 let mut value = self.parse_value()?;
255
256 if let Some(anchor_name) = anchor_from_key {
260 value.anchor = Some(anchor_name);
261 }
262
263 Ok(Pair {
264 key,
265 value,
266 validation,
267 })
268 }
269
270 fn parse_key(&mut self) -> Result<String, MonError> {
274 let token = self.current_token()?;
275 let mut key_parts = Vec::new();
276
277 match &token.ttype {
278 TokenType::Identifier(s) | TokenType::String(s) => {
279 key_parts.push(s.clone());
280 self.advance();
281 }
282 _ => return self.err_unexpected("an identifier or string for a key"),
283 }
284
285 while self.match_token(&TokenType::Dot) {
287 let token = self.current_token()?;
288 if let TokenType::Identifier(s) = &token.ttype {
289 key_parts.push(s.clone());
290 self.advance();
291 } else {
292 return self.err_unexpected("an identifier after a dot in a key");
293 }
294 }
295
296 Ok(key_parts.join("."))
297 }
298
299 fn parse_optional_anchor(&mut self) -> Result<Option<String>, MonError> {
301 if self.match_token(&TokenType::Ampersand) {
302 let token = self.current_token()?;
303 if let TokenType::Identifier(name) = &token.ttype {
304 let name = name.clone();
305 self.advance();
306 Ok(Some(name))
307 } else {
308 self.err_unexpected("an identifier for the anchor name")
309 }
310 } else {
311 Ok(None)
312 }
313 }
314
315 fn parse_alias(&mut self) -> Result<MonValue, MonError> {
317 let start_token = self.current_token()?.clone();
318 self.expect(&TokenType::Asterisk)?;
319 let mut name = self.parse_key()?;
320 let mut end_pos = self.current_token_before_advance()?.pos_end; while self.match_token(&TokenType::Dot) {
323 name.push('.');
324 let key_part = self.parse_key()?;
325 end_pos = self.current_token_before_advance()?.pos_end; name.push_str(&key_part);
327 }
328 Ok(MonValue {
329 kind: MonValueKind::Alias(name),
330 anchor: None,
331 pos_start: start_token.pos_start,
332 pos_end: end_pos,
333 })
334 }
335
336 fn parse_spread(&mut self) -> Result<String, MonError> {
338 self.expect(&TokenType::Spread)?;
339 let alias = self.parse_alias()?;
340 if let MonValueKind::Alias(name) = alias.kind {
341 Ok(name)
342 } else {
343 self.err_unexpected("an alias after '...'")
345 }
346 }
347
348 fn parse_import_statement(&mut self) -> Result<ImportStatement, MonError> {
350 let start_token = self.current_token()?.clone(); self.expect(&TokenType::Import)?;
352
353 let spec = if self.match_token(&TokenType::Asterisk) {
354 self.expect(&TokenType::As)?;
356 let name = self.parse_key()?;
357 ImportSpec::Namespace(name)
358 } else {
359 self.expect(&TokenType::LBrace)?;
361 let mut specifiers = Vec::new();
362 if !self.check(&TokenType::RBrace) {
363 loop {
364 let is_anchor = self.match_token(&TokenType::Ampersand);
366 let name = self.parse_key()?;
367 specifiers.push(ImportSpecifier { name, is_anchor });
368 if !self.match_token(&TokenType::Comma) {
369 break;
370 }
371 if self.check(&TokenType::RBrace) {
372 break;
373 }
374 }
375 }
376 self.expect(&TokenType::RBrace)?;
377 ImportSpec::Named(specifiers)
378 };
379
380 self.expect(&TokenType::From)?;
381 let path_token = self.current_token()?.clone(); let path = self.parse_key()?;
383
384 Ok(ImportStatement {
385 path,
386 spec,
387 pos_start: start_token.pos_start,
388 pos_end: path_token.pos_end,
389 })
390 }
391
392 fn parse_type_definition(&mut self) -> Result<TypeDefinition, MonError> {
394 let name_token = self.current_token()?.clone();
395 let name = self.parse_key()?;
396 self.expect(&TokenType::Colon)?;
397 let hash_token = self.current_token()?.clone();
398 self.expect(&TokenType::Hash)?;
399
400 let token = self.current_token()?;
401 let (def_type, end_pos) = match &token.ttype {
402 TokenType::Identifier(s) if s == "struct" => {
403 self.advance();
404 let mut struct_def = self.parse_struct_definition()?;
405 let end_pos = struct_def.pos_end;
406 struct_def.pos_start = hash_token.pos_start;
407 Ok((TypeDef::Struct(struct_def), end_pos))
408 }
409 TokenType::Identifier(s) if s == "enum" => {
410 self.advance();
411 let mut enum_def = self.parse_enum_definition()?;
412 let end_pos = enum_def.pos_end;
413 enum_def.pos_start = hash_token.pos_start;
414 Ok((TypeDef::Enum(enum_def), end_pos))
415 }
416 _ => self.err_unexpected("'struct' or 'enum' keyword"),
417 }?;
418
419 Ok(TypeDefinition {
420 name,
421 name_span: (
422 name_token.pos_start,
423 name_token.pos_end - name_token.pos_start,
424 )
425 .into(),
426 def_type,
427 pos_start: name_token.pos_start,
428 pos_end: end_pos,
429 })
430 }
431
432 fn parse_struct_definition(&mut self) -> Result<StructDef, MonError> {
434 let start_token = self.current_token()?.clone();
435 self.expect(&TokenType::LBrace)?;
436 let mut fields = Vec::new();
437 if !self.check(&TokenType::RBrace) {
438 loop {
439 fields.push(self.parse_field_definition()?);
440 if !self.match_token(&TokenType::Comma) {
441 break;
442 }
443 if self.check(&TokenType::RBrace) {
444 break;
445 }
446 }
447 }
448 let end_token = self.current_token()?.clone();
449 self.expect(&TokenType::RBrace)?;
450 Ok(StructDef {
451 fields,
452 pos_start: start_token.pos_start,
453 pos_end: end_token.pos_end,
454 })
455 }
456
457 fn parse_field_definition(&mut self) -> Result<FieldDef, MonError> {
459 let name = self.parse_key()?;
460 self.expect(&TokenType::LParen)?;
461 let type_spec = self.parse_type_spec()?;
462 self.expect(&TokenType::RParen)?;
463
464 let default_value = if self.match_token(&TokenType::Equals) {
465 Some(self.parse_value()?)
466 } else {
467 None
468 };
469
470 Ok(FieldDef {
471 name,
472 type_spec,
473 default_value,
474 })
475 }
476
477 fn parse_enum_definition(&mut self) -> Result<EnumDef, MonError> {
479 let start_token = self.current_token()?.clone();
480 self.expect(&TokenType::LBrace)?;
481 let mut variants = Vec::new();
482 if !self.check(&TokenType::RBrace) {
483 loop {
484 variants.push(self.parse_key()?);
485 if !self.match_token(&TokenType::Comma) {
486 break;
487 }
488 if self.check(&TokenType::RBrace) {
489 break;
490 }
491 }
492 }
493 let end_token = self.current_token()?.clone();
494 self.expect(&TokenType::RBrace)?;
495 Ok(EnumDef {
496 variants,
497 pos_start: start_token.pos_start,
498 pos_end: end_token.pos_end,
499 })
500 }
501
502 fn parse_optional_validation(&mut self) -> Result<Option<TypeSpec>, MonError> {
504 if self.match_token(&TokenType::DoubleColon) {
505 self.parse_type_spec().map(Some)
506 } else {
507 Ok(None)
508 }
509 }
510
511 fn parse_type_spec(&mut self) -> Result<TypeSpec, MonError> {
513 let start_token = self.current_token()?.clone();
514 if self.check(&TokenType::LBracket) {
515 self.expect(&TokenType::LBracket)?;
517 let mut types = Vec::new();
518 if !self.check(&TokenType::RBracket) {
519 loop {
520 let mut type_spec = self.parse_type_spec()?;
521 if self.match_token(&TokenType::Spread) {
522 let end_token = self.current_token_before_advance()?.clone();
523 let span = (
524 type_spec.get_span().offset(),
525 end_token.pos_end - type_spec.get_span().offset(),
526 )
527 .into();
528 type_spec = TypeSpec::Spread(Box::new(type_spec), span);
529 }
530 types.push(type_spec);
531
532 if !self.match_token(&TokenType::Comma) {
533 break;
534 }
535 if self.check(&TokenType::RBracket) {
536 break;
537 }
538 }
539 }
540 let end_token = self.current_token()?.clone();
541 self.expect(&TokenType::RBracket)?;
542 let span = (
543 start_token.pos_start,
544 end_token.pos_end - start_token.pos_start,
545 )
546 .into();
547 Ok(TypeSpec::Collection(types, span))
548 } else {
549 let name = self.parse_key()?;
551 let end_token = self.current_token_before_advance()?.clone();
552 let span = (
553 start_token.pos_start,
554 end_token.pos_end - start_token.pos_start,
555 )
556 .into();
557 Ok(TypeSpec::Simple(name, span))
558 }
559 }
560
561 fn parse_enum_value(&mut self) -> Result<MonValue, MonError> {
563 let start_token = self.current_token()?.clone();
564 self.expect(&TokenType::Dollar)?;
565
566 let enum_token = self.current_token()?.clone();
568 let enum_name = if let TokenType::Identifier(s) = &enum_token.ttype {
569 let s = s.clone();
570 self.advance();
571 s
572 } else {
573 return self.err_unexpected("an identifier for enum name");
574 };
575
576 self.expect(&TokenType::Dot)?;
577
578 let variant_token = self.current_token()?.clone();
580 let variant_name = if let TokenType::Identifier(s) = &variant_token.ttype {
581 let s = s.clone();
582 self.advance();
583 s
584 } else {
585 return self.err_unexpected("an identifier for enum variant");
586 };
587
588 Ok(MonValue {
589 kind: MonValueKind::EnumValue { enum_name, variant_name },
590 anchor: None,
591 pos_start: start_token.pos_start,
592 pos_end: variant_token.pos_end,
593 })
594 }
595
596 fn current_token(&self) -> Result<&Token, MonError> {
599 self.tokens.get(self.position).ok_or_else(|| {
600 let pos = self.source_text.len().saturating_sub(1);
601 ParserError::UnexpectedEof {
602 src: (*self.source).clone().into(), span: (pos, 0).into(),
604 }
605 .into()
606 })
607 }
608
609 fn current_token_before_advance(&self) -> Result<&Token, MonError> {
610 self.tokens
611 .get(self.position.saturating_sub(1))
612 .ok_or_else(|| {
613 let pos = self.source_text.len().saturating_sub(1);
614 ParserError::UnexpectedEof {
615 src: (*self.source).clone().into(),
616 span: (pos, 0).into(),
617 }
618 .into()
619 })
620 }
621
622 fn advance(&mut self) {
623 if self.position < self.tokens.len() {
624 self.position += 1;
625 }
626 }
627
628 #[track_caller]
629 fn expect(&mut self, expected: &TokenType) -> Result<(), MonError> {
630 let token = self.current_token()?.clone();
631 if std::mem::discriminant(&token.ttype) == std::mem::discriminant(expected) {
632 self.advance();
633 Ok(())
634 } else {
635 self.err_unexpected(&format!("{expected:?}"))
636 }
637 }
638
639 fn match_token(&mut self, ttype: &TokenType) -> bool {
640 if self.check(ttype) {
641 self.advance();
642 true
643 } else {
644 false
645 }
646 }
647
648 fn check(&self, ttype: &TokenType) -> bool {
649 if let Ok(token) = self.current_token() {
650 std::mem::discriminant(&token.ttype) == std::mem::discriminant(ttype)
651 } else {
652 false
653 }
654 }
655
656 fn peek_is(&self, ttype: &TokenType) -> bool {
657 if let Some(token) = self.tokens.get(self.position + 1) {
658 std::mem::discriminant(&token.ttype) == std::mem::discriminant(ttype)
659 } else {
660 false
661 }
662 }
663
664 fn peek_next_is(&self, ttype: &TokenType) -> bool {
665 if let Some(token) = self.tokens.get(self.position + 2) {
666 std::mem::discriminant(&token.ttype) == std::mem::discriminant(ttype)
667 } else {
668 false
669 }
670 }
671
672 #[track_caller]
673 fn err_unexpected<T>(&self, expected: &str) -> Result<T, MonError> {
674 let token = self.current_token()?; print!("caller: {}", Location::caller());
676 Err(ParserError::UnexpectedToken {
677 src: (*self.source).clone().into(),
678 span: (token.pos_start, token.pos_end - token.pos_start).into(),
679 expected: expected.to_string(),
680 }
681 .into())
682 }
683}
684
685#[allow(dead_code)]
687fn pretty_result(out: Result<MonDocument, MonError>) -> String {
688 match out {
689 Ok(doc) => format!("{doc:#?}"), Err(err) => {
691 let report: Report = Report::new(err);
692 let handler = GraphicalReportHandler::new(); let mut buffer = String::new();
694 handler.render_report(&mut buffer, &*report).unwrap();
695 buffer
696 }
697 }
698}
699
700#[cfg(test)]
701#[allow(clippy::match_wildcard_for_single_variants)]
702mod tests {
703 use super::*;
704 use miette::Report;
705 use std::fs;
706
707 fn parse_ok(source: &str) -> MonDocument {
708 let mut parser = Parser::new_with_name(source, "test.mon".to_string()).unwrap();
709 match parser.parse_document() {
710 Ok(doc) => doc,
711 Err(err) => {
712 let report = Report::from(err);
713 print!("{report:?}");
714
715 panic!("{report:#}");
716 }
717 }
718 }
719
720 #[test]
721 fn test_empty_object() {
722 let doc = parse_ok("{}");
723 assert_eq!(doc.root.kind, MonValueKind::Object(vec![]));
724 }
725
726 #[test]
727 fn test_simple_pair() {
728 let doc = parse_ok(r#"{ key: "value" }"#);
729 let members = match doc.root.kind {
730 MonValueKind::Object(m) => m,
731 _ => panic!(),
732 };
733 assert_eq!(members.len(), 1);
734 match &members[0] {
735 Member::Pair(p) => {
736 assert_eq!(p.key, "key");
737 assert!(matches!(p.value.kind, MonValueKind::String(_)));
738 }
739 _ => panic!(),
740 }
741 }
742
743 #[test]
744 fn test_anchor_and_alias() {
745 let doc = parse_ok(r"{ &anchor1 : 123, key2: *anchor1 }");
746 let members = match doc.root.kind {
747 MonValueKind::Object(m) => m,
748 _ => panic!(),
749 };
750 assert_eq!(members.len(), 2);
751 match &members[0] {
752 Member::Pair(p) => {
753 assert_eq!(p.key, "anchor1");
754 assert_eq!(p.value.anchor, Some("anchor1".to_string()));
755 }
756 _ => panic!(),
757 }
758 match &members[1] {
759 Member::Pair(p) => {
760 assert_eq!(p.key, "key2");
761 assert!(matches!(p.value.kind, MonValueKind::Alias(_)));
762 }
763 _ => panic!(),
764 }
765 }
766
767 #[test]
768 fn test_spread() {
769 let doc = parse_ok(r"{ ...*my_anchor }");
770 let members = match doc.root.kind {
771 MonValueKind::Object(m) => m,
772 _ => panic!(),
773 };
774 assert_eq!(members.len(), 1);
775 match &members[0] {
776 Member::Spread(name) => assert_eq!(name, "my_anchor"),
777 _ => panic!(),
778 }
779 }
780
781 #[test]
782 fn test_namespace_import() {
783 let doc = parse_ok(r#"import * as my_schemas from "./schemas.mon" {}"#);
784 assert_eq!(doc.imports.len(), 1);
785 let i = &doc.imports[0];
786 assert_eq!(i.path, "./schemas.mon");
787 assert!(matches!(i.spec, ImportSpec::Namespace(ref s) if s == "my_schemas"));
788
789 let members = match doc.root.kind {
791 MonValueKind::Object(m) => m,
792 _ => panic!("Root was not an object"),
793 };
794 assert!(members.is_empty());
795 }
796
797 #[test]
798 fn test_named_import() {
799 let doc = parse_ok(r#"import { User, &Template } from "./file.mon" {}"#);
800 assert_eq!(doc.imports.len(), 1);
801 let i = &doc.imports[0];
802 assert_eq!(i.path, "./file.mon");
803 match &i.spec {
804 ImportSpec::Named(specs) => {
805 assert_eq!(specs.len(), 2);
806 assert_eq!(specs[0].name, "User");
807 assert!(!specs[0].is_anchor);
808 assert_eq!(specs[1].name, "Template");
809 assert!(specs[1].is_anchor);
810 }
811 _ => panic!(),
812 }
813 let members = match doc.root.kind {
815 MonValueKind::Object(m) => m,
816 _ => panic!("Root was not an object"),
817 };
818 assert!(members.is_empty());
819 }
820
821 #[test]
822 fn test_enum_definition() {
823 let doc = parse_ok(r"{ Status: #enum { Active, Inactive } }");
824 let members = match doc.root.kind {
825 MonValueKind::Object(m) => m,
826 _ => panic!(),
827 };
828 assert_eq!(members.len(), 1);
829 match &members[0] {
830 Member::TypeDefinition(t) => {
831 assert_eq!(t.name, "Status");
832 assert!(matches!(t.def_type, TypeDef::Enum(_)));
833 }
834 _ => panic!(),
835 }
836 }
837
838 #[test]
839 fn test_struct_definition() {
840 let doc = parse_ok(r#"{ User: #struct { id(Number), name(String) = "Guest" } }"#);
841 let members = match doc.root.kind {
842 MonValueKind::Object(m) => m,
843 _ => panic!(),
844 };
845 assert_eq!(members.len(), 1);
846 match &members[0] {
847 Member::TypeDefinition(t) => {
848 assert_eq!(t.name, "User");
849 match &t.def_type {
850 TypeDef::Struct(s) => {
851 assert_eq!(s.fields.len(), 2);
852 assert_eq!(s.fields[0].name, "id");
853 assert!(s.fields[1].default_value.is_some());
854 }
855 _ => panic!(),
856 }
857 }
858 _ => panic!(),
859 }
860 }
861
862 #[test]
863 fn test_validation_pair() {
864 let doc = parse_ok(r#"{ my_user :: User = { name: "Alice" } }"#);
865 let members = match doc.root.kind {
866 MonValueKind::Object(m) => m,
867 _ => panic!(),
868 };
869 assert_eq!(members.len(), 1);
870 match &members[0] {
871 Member::Pair(p) => {
872 assert_eq!(p.key, "my_user");
873 assert!(p.validation.is_some());
874 assert!(matches!(p.value.kind, MonValueKind::Object(_)));
875 }
876 _ => panic!(),
877 }
878 }
879
880 #[test]
881 #[ignore = "This test is for visual confirmation and is ignored by default."]
882 fn visual_conformation_from_golden() {
883 let contents = fs::read_to_string("tests/ok/golden.mon").unwrap();
884 let parsed = Parser::new_with_name(&contents, "test.mon".to_string())
885 .unwrap()
886 .parse_document();
887
888 print!("parsed: \n{}", pretty_result(parsed));
889 }
890
891 #[test]
892 fn test_all_mon_files() {
893 let tests_dir = "./tests";
894 let entries = fs::read_dir(tests_dir).expect("Failed to read tests directory");
895
896 for entry in entries {
897 let entry = entry.expect("Failed to read directory entry");
898 let path = entry.path();
899
900 if path.is_file() && path.extension().is_some_and(|ext| ext == "mon") {
901 println!("Parsing file: {path:?}");
902 let source = fs::read_to_string(&path)
903 .unwrap_or_else(|_| panic!("Failed to read file: {path:?}"));
904
905 let mut parser = Parser::new_with_name(&source, path.to_str().unwrap().to_string())
906 .expect("Lexer failed");
907
908 if let Err(err) = parser.parse_document() {
909 panic!("Failed to parse {:?}. Error: {:#?}", path, Report::new(err));
910 }
911 }
912 }
913 }
914}