rusty_systems/symbols/
iterator.rs1use super::*;
2use std::iter::FromIterator;
3use crate::prelude::ProductionString;
4use crate::productions::{Production, ProductionBody, ProductionHead};
5
6pub trait SymbolIterable {
8 fn all_symbols_iter(&self) -> impl Iterator<Item=Symbol>;
10
11 fn all_symbols<C: FromIterator<Symbol>>(&self) -> C {
17 self.all_symbols_iter().collect()
18 }
19}
20
21
22impl SymbolIterable for ProductionString {
23 fn all_symbols_iter(&self) -> impl Iterator<Item=Symbol> {
24 self.iter().cloned()
25 }
26}
27
28impl SymbolIterable for ProductionHead {
29 fn all_symbols_iter(&self) -> impl Iterator<Item=Symbol> {
30 let pre : Box<dyn Iterator<Item=Symbol>> = match self.pre_context() {
31 None => Box::new(std::iter::empty()),
32 Some(val) => Box::new(val.all_symbols_iter())
33 };
34
35 let target = std::iter::once(self.target()).cloned();
36
37 let post : Box<dyn Iterator<Item=Symbol>> = match self.post_context() {
38 None => Box::new(std::iter::empty()),
39 Some(val) => Box::new(val.all_symbols_iter())
40 };
41
42 pre.chain(target).chain(post)
43 }
44}
45
46impl SymbolIterable for ProductionBody {
47 #[inline]
48 fn all_symbols_iter(&self) -> impl Iterator<Item=Symbol> {
49 self.string().all_symbols_iter()
50 }
51}
52
53impl SymbolIterable for Production {
54 fn all_symbols_iter(&self) -> impl Iterator<Item=Symbol> {
55 let mut result : Box<dyn Iterator<Item=Symbol>> = Box::new(self.head().all_symbols_iter());
56
57 for i in self.all_bodies() {
58 result = Box::new(result.chain(i.all_symbols_iter()));
59 }
60
61 result
62 }
63}
64
65#[cfg(test)]
66mod test {
67 use super::*;
68 use crate::parser::{parse_prod_string, parse_production};
69
70 #[test]
71 fn can_iterate_over_string() {
72 let string = parse_prod_string("A B B C D").unwrap();
73
74 let mut iter = string.all_symbols_iter();
75
76 assert_eq!(iter.next().unwrap().code, get_code("A").unwrap());
77 assert_eq!(iter.next().unwrap().code, get_code("B").unwrap());
78 assert_eq!(iter.next().unwrap().code, get_code("B").unwrap());
79 assert_eq!(iter.next().unwrap().code, get_code("C").unwrap());
80 assert_eq!(iter.next().unwrap().code, get_code("D").unwrap());
81
82 let b : Vec<_> = string.all_symbols();
83 assert_eq!(b.len(), 5);
84 }
85
86
87 #[test]
88 fn can_iterate_over_production() {
89 let production = parse_production("Pre < Target > Post -> A B C C").unwrap();
90
91 let mut iter = production.all_symbols_iter();
92
93 assert_eq!(iter.next().unwrap().code, get_code("Pre").unwrap());
94 assert_eq!(iter.next().unwrap().code, get_code("Target").unwrap());
95 assert_eq!(iter.next().unwrap().code, get_code("Post").unwrap());
96 assert_eq!(iter.next().unwrap().code, get_code("A").unwrap());
97 assert_eq!(iter.next().unwrap().code, get_code("B").unwrap());
98 assert_eq!(iter.next().unwrap().code, get_code("C").unwrap());
99 assert_eq!(iter.next().unwrap().code, get_code("C").unwrap());
100
101 let b : Vec<_> = production.all_symbols();
102 assert_eq!(b.len(), 7);
103
104 let b : HashSet<_> = production.all_symbols();
105 assert_eq!(b.len(), 6);
106 }
107
108}