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