1use crate::symbol::{sentential_form, Symbol, SymbolError};
11use crate::tokenizer;
12use crate::tokenizer::TokenizerError;
13use serde::{Deserialize, Serialize};
14use std::collections::HashSet;
15use std::error::Error;
16use std::fmt;
17
18#[derive(Debug, PartialEq, Eq, Clone, Hash)]
19pub enum ProductionError {
20 NoLhs,
23 NoRhs,
26 SymbolError(SymbolError),
29 FormatError(TokenizerError),
33}
34
35impl fmt::Display for ProductionError {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 match self {
38 ProductionError::NoLhs => write!(f, "ProductionError: no lhs in production"),
39 ProductionError::NoRhs => write!(f, "ProductionError: no rhs in production"),
40 ProductionError::SymbolError(e) => {
41 write!(f, "ProductionError: symbol error encountered = {}", e)
42 }
43 ProductionError::FormatError(e) => write!(
44 f,
45 "ProductionError: bad formatted string encountered, error = {}",
46 e
47 ),
48 }
49 }
50}
51
52impl Error for ProductionError {
53 fn source(&self) -> Option<&(dyn Error + 'static)> {
54 match self {
55 ProductionError::SymbolError(e) => Some(e),
56 ProductionError::FormatError(e) => Some(e),
57 _ => None,
58 }
59 }
60}
61
62impl std::convert::From<TokenizerError> for ProductionError {
63 fn from(e: TokenizerError) -> Self {
64 ProductionError::FormatError(e)
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq, Hash)]
72pub enum ProductionPredicate {
73 LhsEquals(Vec<Symbol>),
75 RhsEquals(Vec<Symbol>),
77 RhsLengthEquals(usize),
79 RhsIsSuffixOf(Vec<Symbol>),
81}
82
83impl ProductionPredicate {
84 pub fn test(&self, p: &Production) -> bool {
98 match self {
99 ProductionPredicate::LhsEquals(symbols) => p.lhs() == *symbols,
100 ProductionPredicate::RhsEquals(symbols) => p.rhs() == *symbols,
101 ProductionPredicate::RhsLengthEquals(length) => p.rhs().len() == *length,
102 ProductionPredicate::RhsIsSuffixOf(symbols) => p.rhs().ends_with(&symbols),
103 }
104 }
105}
106
107impl fmt::Display for ProductionPredicate {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 match self {
110 ProductionPredicate::LhsEquals(symbols) => write!(
111 f,
112 "ProductionPredicate: lhs == {}",
113 sentential_form(symbols.clone())
114 ),
115 ProductionPredicate::RhsEquals(symbols) => write!(
116 f,
117 "ProductionPredicate: rhs == {}",
118 sentential_form(symbols.clone())
119 ),
120 ProductionPredicate::RhsIsSuffixOf(symbols) => write!(
121 f,
122 "ProductionPredicate: rhs suffix == {}",
123 sentential_form(symbols.clone())
124 ),
125 ProductionPredicate::RhsLengthEquals(length) => {
126 write!(f, "ProductionPredicate: rhs length == {}", length)
127 }
128 }
129 }
130}
131
132#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord, Serialize, Deserialize)]
156pub struct Production {
157 lhs: Vec<Symbol>,
158 rhs: Vec<Symbol>,
159}
160
161impl fmt::Display for Production {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 for lhs in self.lhs() {
164 write!(f, "{} ", lhs)?;
165 }
166 write!(f, "->")?;
167 for rhs in self.rhs() {
168 write!(f, " {}", rhs)?;
169 }
170
171 Ok(())
172 }
173}
174
175impl std::convert::TryFrom<&str> for Production {
176 type Error = ProductionError;
177
178 fn try_from(value: &str) -> Result<Self, Self::Error> {
179 let p = Production::from_string(value)?;
180 let mut p_iter = p.iter();
181 if let Some(p) = p_iter.next() {
182 if p_iter.next().is_none() {
183 Ok(p.clone())
184 } else {
185 Err(ProductionError::FormatError(
186 TokenizerError::ProductionMultiple(value.to_string()),
187 ))
188 }
189 } else {
190 Err(ProductionError::FormatError(
191 TokenizerError::ProductionEmpty(value.to_string()),
192 ))
193 }
194 }
195}
196
197impl Production {
198 pub fn new<I>(lhs: I, rhs: I) -> Result<Production, ProductionError>
218 where
219 I: IntoIterator<Item = Symbol>,
220 {
221 let lhs: Vec<Symbol> = lhs.into_iter().collect();
222 let rhs: Vec<Symbol> = rhs.into_iter().collect();
223
224 if lhs.is_empty() {
225 return Err(ProductionError::NoLhs);
226 }
227 if rhs.is_empty() {
228 return Err(ProductionError::NoRhs);
229 }
230
231 Ok(Production { lhs: lhs, rhs: rhs })
232 }
233
234 pub fn new_from_string<'a, I>(lhs: I, rhs: I) -> Result<Production, ProductionError>
255 where
256 I: IntoIterator<Item = &'a str>,
257 {
258 let lhs = lhs.into_iter().try_fold(Vec::new(), |mut acc, s| {
259 let s = Symbol::new(s)?;
260 acc.push(s);
261 Ok(acc)
262 });
263 let rhs = rhs.into_iter().try_fold(Vec::new(), |mut acc, s| {
264 let s = Symbol::new(s)?;
265 acc.push(s);
266 Ok(acc)
267 });
268
269 match (lhs, rhs) {
270 (Ok(lhs), Ok(rhs)) => Production::new(lhs, rhs),
271 (Err(e), _) => Err(ProductionError::SymbolError(e)),
272 (_, Err(e)) => Err(ProductionError::SymbolError(e)),
273 }
274 }
275
276 pub fn lhs(&self) -> Vec<Symbol> {
289 self.lhs.clone()
290 }
291
292 pub fn rhs(&self) -> Vec<Symbol> {
305 self.rhs.clone()
306 }
307
308 pub fn symbols(&self) -> HashSet<Symbol> {
324 let mut symbols: Vec<Symbol> = self.lhs();
325 symbols.append(&mut self.rhs());
326 symbols.into_iter().collect()
327 }
328
329 pub fn from_string(string: &str) -> Result<Vec<Production>, ProductionError> {
356 tokenizer::productions_from_string(string)?
357 .iter()
358 .try_fold(Vec::new(), |mut acc, p| {
359 let p = Production::new_from_string::<Vec<&str>>(
360 p.0.iter().map(String::as_str).collect(),
361 p.1.iter().map(String::as_str).collect(),
362 )?;
363 acc.push(p);
364 Ok(acc)
365 })
366 }
367
368 pub fn from_iter<'a, I>(strings: I) -> Result<Vec<Production>, ProductionError>
396 where
397 I: IntoIterator<Item = &'a str>,
398 {
399 let mut p: Vec<Production> = Vec::new();
400
401 for string in strings {
402 p.append(&mut Production::from_string(string)?)
403 }
404
405 Ok(p)
406 }
407
408 pub fn such_that(predicate: ProductionPredicate) -> Box<dyn FnMut(&&Production) -> bool> {
433 Box::new(move |p| predicate.test(&p))
434 }
435}
436
437pub fn production(lhs: &str, rhs: &str) -> Production {
457 Production::new(
458 Symbol::from_string(lhs).unwrap(),
459 Symbol::from_string(rhs).unwrap(),
460 )
461 .unwrap()
462}
463
464pub fn productions(string: &str) -> Vec<Production> {
484 Production::from_string(string).unwrap()
485}
486
487pub fn production_table<I>(productions: I) -> String
503where
504 I: IntoIterator<Item = Production>,
505{
506 productions
507 .into_iter()
508 .enumerate()
509 .map(|(i, p)| format!("{}: {}", i, p))
510 .collect::<Vec<String>>()
511 .join("\n")
512}
513
514#[cfg(test)]
515mod tests {
516
517 use super::*;
518 use crate::symbol::symbol;
519 use std::convert::TryFrom;
520 use std::fmt::Write;
521
522 #[test]
525 fn from_string() {
526 let p_check = vec![
527 Production {
528 lhs: vec![symbol("S")],
529 rhs: vec![symbol("A"), symbol("B")],
530 },
531 Production {
532 lhs: vec![symbol("A")],
533 rhs: vec![symbol("a")],
534 },
535 Production {
536 lhs: vec![symbol("A")],
537 rhs: vec![symbol("B")],
538 },
539 Production {
540 lhs: vec![symbol("B")],
541 rhs: vec![symbol("b")],
542 },
543 ];
544
545 assert_eq!(
546 Production::from_string("S -> A B\nA -> a | B\nB -> b").unwrap(),
547 p_check,
548 "Parsed production rules are not those expected"
549 );
550 }
551
552 #[test]
553 fn from_string_error() {
554 let error = TokenizerError::ProductionNoRhs("S".to_string());
555 let result = Production::from_string("S ->\n -> a | B\nB -> b");
556
557 assert!(
558 result.is_err(),
559 "Production from string on test input should return error"
560 );
561 let e = result.unwrap_err();
562 assert_eq!(
563 e,
564 ProductionError::FormatError(error),
565 "Creation of productions from test input returned the wrong error"
566 );
567 }
568
569 #[test]
570 fn from_iter() {
571 let p_check = vec![
572 Production {
573 lhs: vec![symbol("S")],
574 rhs: vec![symbol("A"), symbol("B")],
575 },
576 Production {
577 lhs: vec![symbol("A")],
578 rhs: vec![symbol("a")],
579 },
580 Production {
581 lhs: vec![symbol("B")],
582 rhs: vec![symbol("a")],
583 },
584 Production {
585 lhs: vec![symbol("B")],
586 rhs: vec![symbol("b")],
587 },
588 ];
589
590 assert_eq!(
591 super::productions("S -> A B\nA -> a\nB -> a | b"),
592 p_check,
593 "Created production rules are not those expected"
594 );
595 }
596
597 #[test]
598 fn such_that() {
599 let filter = Production::such_that(ProductionPredicate::LhsEquals(vec![symbol("T")]));
600 let productions = Production::from_string("S -> A | B\nA -> a\nT -> t\nB -> B").unwrap();
601
602 let productions_iter = productions.clone();
603 let mut filtered = productions_iter.iter().filter(filter);
604
605 assert_eq!(
606 filtered.next(),
607 productions.get(3),
608 "Filtered productions on test input should return the T -> t production"
609 );
610 assert_eq!(
611 filtered.next(),
612 None,
613 "Filtered productions on test input should return no more productions"
614 );
615 }
616
617 #[test]
618 fn new() {
619 let p_check = Production {
620 lhs: vec![symbol("S")],
621 rhs: vec![symbol("A"), symbol("B")],
622 };
623
624 assert_eq!(
625 Production::new(p_check.lhs(), p_check.rhs()).unwrap(),
626 p_check,
627 "Created production rule is not the one expected"
628 );
629 }
630
631 #[test]
632 fn new_empty_side_lhs() {
633 let iter = vec![symbol("S")];
634
635 let result = Production::new(vec![], iter);
636 assert!(
637 result.is_err(),
638 "Creation of production rule should return an error"
639 );
640 let e = result.unwrap_err();
641 assert_eq!(
642 e,
643 ProductionError::NoLhs,
644 "Creation of production rule returned the wrong error"
645 );
646 }
647
648 #[test]
649 fn new_empty_side_rhs() {
650 let iter = vec![symbol("S")];
651
652 let result = Production::new(iter, vec![]);
653 assert!(
654 result.is_err(),
655 "Creation of production rule should return an error"
656 );
657 let e = result.unwrap_err();
658 assert_eq!(
659 e,
660 ProductionError::NoRhs,
661 "Creation of production rule returned the wrong error"
662 );
663 }
664
665 #[test]
666 fn new_from_string() {
667 let p_check = Production {
668 lhs: vec![symbol("S")],
669 rhs: vec![symbol("A"), symbol("B")],
670 };
671
672 assert_eq!(
673 Production::new_from_string(vec!["S"], vec!["A", "B"]).unwrap(),
674 p_check,
675 "Created production rule is not the one expected"
676 );
677 }
678
679 #[test]
680 fn new_from_string_error_lhs() {
681 let error = SymbolError::InvalidSymbol("\n".to_string());
682 let result = Production::new_from_string(vec!["\n"], vec!["A", "B"]);
683
684 assert!(
685 result.is_err(),
686 "Created production rule should return error"
687 );
688 let e = result.unwrap_err();
689 assert_eq!(
690 e,
691 ProductionError::SymbolError(error),
692 "Creation of production rule returned the wrong error"
693 );
694 }
695
696 #[test]
697 fn new_from_string_error_rhs() {
698 let error = SymbolError::InvalidSymbol("\n".to_string());
699 let result = Production::new_from_string(vec!["S"], vec!["\n"]);
700
701 assert!(
702 result.is_err(),
703 "Created production rule should return error"
704 );
705 let e = result.unwrap_err();
706 assert_eq!(
707 e,
708 ProductionError::SymbolError(error),
709 "Creation of production rule returned the wrong error"
710 );
711 }
712
713 #[test]
714 fn production_display() {
715 let mut buf = String::new();
716 let p = super::production("A", "B C");
717
718 let result = write!(buf, "{}", p);
719 assert!(result.is_ok());
720 assert_eq!(buf, "A -> B C")
721 }
722
723 #[test]
724 fn production_try_from() {
725 let result = Production::try_from("A -> B");
726 assert!(result.is_ok());
727 }
728
729 #[test]
730 fn production_try_from_multiple() {
731 let string = "A -> B\nA -> C";
732 let result = Production::try_from(string);
733 assert!(result.is_err());
734 let e = result.unwrap_err();
735 assert_eq!(
736 e,
737 ProductionError::FormatError(TokenizerError::ProductionMultiple(string.to_string()))
738 );
739 }
740
741 #[test]
742 fn production_try_from_error() {
743 let string = "A -> B -> C";
744 let result = Production::try_from(string);
745 assert!(result.is_err());
746 let e = result.unwrap_err();
747 assert_eq!(
748 e,
749 ProductionError::FormatError(TokenizerError::ProductionMultipleOneLine(0))
750 );
751 }
752
753 #[test]
754 fn production_try_from_no_productions() {
755 let result = Production::try_from("");
756 assert!(result.is_err());
757 let e = result.unwrap_err();
758 assert_eq!(
759 e,
760 ProductionError::FormatError(TokenizerError::ProductionEmpty("".to_string()))
761 );
762 }
763
764 #[test]
767 fn production_error_display_no_lhs() {
768 let mut buf = String::new();
769
770 let result = write!(buf, "{}", ProductionError::NoLhs);
771 assert!(result.is_ok());
772 assert_eq!(buf, "ProductionError: no lhs in production")
773 }
774
775 #[test]
776 fn production_error_display_no_rhs() {
777 let mut buf = String::new();
778
779 let result = write!(buf, "{}", ProductionError::NoRhs);
780 assert!(result.is_ok());
781 assert_eq!(buf, "ProductionError: no rhs in production")
782 }
783
784 #[test]
785 fn production_error_display_symbol_error() {
786 let mut buf = String::new();
787 let error = SymbolError::EmptySymbol;
788
789 let result = write!(buf, "{}", ProductionError::SymbolError(error.clone()));
790 assert!(result.is_ok());
791 assert_eq!(
792 buf,
793 format!("ProductionError: symbol error encountered = {}", error)
794 )
795 }
796
797 #[test]
798 fn production_error_display_format_error() {
799 let mut buf = String::new();
800 let error = TokenizerError::ProductionNoLhs;
801
802 let result = write!(buf, "{}", ProductionError::FormatError(error.clone()));
803 assert!(result.is_ok());
804 assert_eq!(
805 buf,
806 format!(
807 "ProductionError: bad formatted string encountered, error = {}",
808 error
809 )
810 )
811 }
812
813 #[test]
814 fn production_error_source() {
815 assert!(
816 ProductionError::FormatError(TokenizerError::ProductionNoLhs)
817 .source()
818 .is_some()
819 );
820 assert!(ProductionError::SymbolError(SymbolError::EmptySymbol)
821 .source()
822 .is_some());
823 }
824
825 #[test]
826 fn production_error_source_none() {
827 assert!(ProductionError::NoLhs.source().is_none());
828 assert!(ProductionError::NoRhs.source().is_none());
829 }
830
831 #[test]
834 fn predicate_lhs_equals() {
835 let predicate = ProductionPredicate::LhsEquals(vec![symbol("T")]);
836
837 assert!(
838 predicate.test(&Production {
839 lhs: vec![symbol("T")],
840 rhs: vec![]
841 }),
842 "Predicate should return true"
843 );
844 assert!(
845 !predicate.test(&Production {
846 lhs: vec![symbol("F")],
847 rhs: vec![]
848 }),
849 "Predicate should return false"
850 );
851 }
852
853 #[test]
854 fn predicate_rhs_equals() {
855 let predicate = ProductionPredicate::RhsEquals(vec![symbol("T")]);
856
857 assert!(
858 predicate.test(&Production {
859 lhs: vec![],
860 rhs: vec![symbol("T")]
861 }),
862 "Predicate should return true"
863 );
864 assert!(
865 !predicate.test(&Production {
866 lhs: vec![],
867 rhs: vec![symbol("F")]
868 }),
869 "Predicate should return false"
870 );
871 }
872
873 #[test]
874 fn predicate_rhs_length_equals() {
875 let predicate = ProductionPredicate::RhsLengthEquals(2);
876
877 assert!(
878 predicate.test(&Production {
879 lhs: vec![],
880 rhs: vec![symbol("T1"), symbol("T2")]
881 }),
882 "Predicate should return true"
883 );
884 assert!(
885 !predicate.test(&Production {
886 lhs: vec![],
887 rhs: vec![symbol("F")]
888 }),
889 "Predicate should return false"
890 );
891 }
892
893 #[test]
894 fn predicate_rhs_is_suffix_of() {
895 let predicate = ProductionPredicate::RhsIsSuffixOf(vec![symbol("T2"), symbol("T3")]);
896
897 assert!(
898 predicate.test(&Production {
899 lhs: vec![],
900 rhs: vec![symbol("T1"), symbol("T2"), symbol("T3")]
901 }),
902 "Predicate should return true"
903 );
904 assert!(
905 !predicate.test(&Production {
906 lhs: vec![],
907 rhs: vec![symbol("F")]
908 }),
909 "Predicate should return false"
910 );
911 }
912
913 #[test]
914 fn production_predicate_display_lhs_equals() {
915 let mut buf = String::new();
916
917 let result = write!(
918 buf,
919 "{}",
920 ProductionPredicate::LhsEquals(vec![symbol("A"), symbol("B")])
921 );
922 assert!(result.is_ok());
923 assert_eq!(buf, format!("ProductionPredicate: lhs == {}", "A B"))
924 }
925
926 #[test]
927 fn production_predicate_display_rhs_equals() {
928 let mut buf = String::new();
929
930 let result = write!(
931 buf,
932 "{}",
933 ProductionPredicate::RhsEquals(vec![symbol("A"), symbol("B")])
934 );
935 assert!(result.is_ok());
936 assert_eq!(buf, format!("ProductionPredicate: rhs == {}", "A B"))
937 }
938
939 #[test]
940 fn production_predicate_display_rhs_is_suffix_of() {
941 let mut buf = String::new();
942
943 let result = write!(
944 buf,
945 "{}",
946 ProductionPredicate::RhsIsSuffixOf(vec![symbol("A"), symbol("B")])
947 );
948 assert!(result.is_ok());
949 assert_eq!(buf, format!("ProductionPredicate: rhs suffix == {}", "A B"))
950 }
951
952 #[test]
953 fn production_predicate_display_rhs_length_equals() {
954 let mut buf = String::new();
955
956 let result = write!(buf, "{}", ProductionPredicate::RhsLengthEquals(2));
957 assert!(result.is_ok());
958 assert_eq!(buf, format!("ProductionPredicate: rhs length == {}", 2))
959 }
960
961 #[test]
964 fn production() {
965 let p_check = Production {
966 lhs: vec![symbol("S")],
967 rhs: vec![symbol("A"), symbol("B")],
968 };
969
970 assert_eq!(
971 super::production("S", "A B"),
972 p_check,
973 "Created production rule is not the one expected"
974 );
975 }
976
977 #[test]
978 fn productions() {
979 let p_check = vec![
980 Production {
981 lhs: vec![symbol("S")],
982 rhs: vec![symbol("A"), symbol("B")],
983 },
984 Production {
985 lhs: vec![symbol("A")],
986 rhs: vec![symbol("a")],
987 },
988 ];
989
990 assert_eq!(
991 super::productions("S -> A B\nA -> a"),
992 p_check,
993 "Created production rules are not those expected"
994 );
995 }
996
997 #[test]
998 fn production_table() {
999 let p = super::productions(
1000 "
1001 A -> B C
1002 B -> b
1003 ",
1004 );
1005 let result = super::production_table(p);
1006
1007 assert_eq!(result, "0: A -> B C\n1: B -> b");
1008 }
1009}