Skip to main content

rattle_items_match/
machine.rs

1use crate::ActualVal;
2use crate::ConditionsVal;
3use crate::ExpectedVal;
4use crate::MachineBuilder;
5use crate::MachineState;
6use crate::MatchingResult;
7use crate::RangeIncludesMaxVal;
8use crate::{Condition, Controls, MachineVal, Operator};
9
10impl<T> Default for MachineBuilder<T>
11where
12    T: std::clone::Clone,
13{
14    fn default() -> Self {
15        MachineBuilder {
16            actual: None,
17            expected: None,
18        }
19    }
20}
21
22impl<T> MachineBuilder<T>
23where
24    T: std::clone::Clone,
25{
26    //! Create `MachineVal`.  
27    //! `MachineVal` を作成します。  
28    pub fn build(&self) -> MachineVal<T> {
29        MachineVal {
30            actual: self.actual.clone().unwrap(),
31            expected: self.expected.clone().unwrap(),
32        }
33    }
34
35    /// Set an actual.  
36    pub fn actual<'a>(&'a mut self, item: &ActualVal<T>) -> &'a mut Self {
37        self.actual = Some(item.clone());
38        self
39    }
40    /// Set an expected.  
41    pub fn expected<'a>(&'a mut self, item: &ExpectedVal<T>) -> &'a mut Self {
42        self.expected = Some(item.clone());
43        self
44    }
45}
46
47impl<T> MachineVal<T>
48where
49    T: std::cmp::PartialEq + std::cmp::PartialOrd,
50{
51    /// Compare actual and expected for an exact match.  
52    /// 完全一致するかどうか actual と expected を比較します。  
53    pub fn exec(&self) -> bool {
54        let mut machine_state = MachineState::default();
55
56        for (i, act) in self.actual.get_items().iter().enumerate() {
57            machine_state.actual_index = i;
58            if machine_state.actual_index + 1 == self.actual.len() {
59                machine_state.is_final = true;
60            }
61
62            // TODO expected_index カーソルを勧めるのはあとで。
63            if let Some(mut exp) = self.expected.get(machine_state.expected_index) {
64                match self.matching2(&mut machine_state, act, &mut exp) {
65                    MatchingResult::Matched => {
66                        // println!("(trace.30) マッチしたという判断。ループ続行。");
67                        machine_state.expected_index += 1;
68                        machine_state.matched_length_in_repeat = 0; // reset.
69                        machine_state.matched_length_in_seq = 0; // reset.
70                    }
71                    MatchingResult::NotMatch => {
72                        // println!("(trace.35) マッチしていないという判断。");
73                        return false;
74                    }
75                    MatchingResult::Ongoing => {
76                        // println!("(trace.38) マッチ中という判断。ループ続行。");
77                    }
78                }
79            } else {
80                // マッチしていないという判断。
81                // println!("(trace.44) マッチしていないという判断。");
82                return false;
83            }
84        }
85
86        // 失敗していなければ成功という判断。
87        // println!("(trace.51) 失敗していなければ成功という判断。");
88        return true;
89    }
90
91    pub fn matching2(
92        &self,
93        machine_state: &mut MachineState,
94        act: &T,
95        exp: &Controls<T>,
96    ) -> MatchingResult
97    where
98        T: std::cmp::PartialEq + std::cmp::PartialOrd,
99    {
100        match exp {
101            Controls::Once(exp) => match exp {
102                Operator::Or(any) => self.matching4_any(machine_state, act, any),
103                Operator::One(exp) => self.matching4_one(machine_state, act, exp),
104            },
105            Controls::Repeat(rep) => {
106                if rep.is_cutoff(machine_state.matched_length_in_repeat) {
107                    //  || self.is_final
108                    match self.matching3_quantity(machine_state, act, &rep.op) {
109                        MatchingResult::NotMatch => {
110                            // println!("(trace.85) rep={}", rep);
111                            return MatchingResult::NotMatch;
112                        }
113                        MatchingResult::Matched | MatchingResult::Ongoing => {
114                            machine_state.matched_length_in_repeat += 1;
115                            if rep.is_cutoff(machine_state.matched_length_in_repeat) {
116                                /*
117                                // println!(
118                                    "(trace.93) Cutoff. 上限までマッチしたので切上げ。 rep={}",
119                                    rep
120                                );
121                                */
122                                return MatchingResult::Matched;
123                            } else if rep.is_success(machine_state.matched_length_in_repeat) {
124                                // println!("(trace.87) rep={}", rep);
125                                return MatchingResult::Matched;
126                            } else {
127                                // println!("(trace.90) fail. rep={}", rep);
128                                return MatchingResult::NotMatch;
129                            }
130                        }
131                    }
132                } else {
133                    match self.matching3_quantity(machine_state, act, &rep.op) {
134                        MatchingResult::NotMatch => {
135                            if rep.is_cutoff(machine_state.matched_length_in_repeat) {
136                                /*
137                                // println!(
138                                    "(trace.93) Cutoff. 上限までマッチしたので切上げ。 rep={}",
139                                    rep
140                                );
141                                */
142                                return MatchingResult::Matched;
143                            } else if rep.is_success(machine_state.matched_length_in_repeat) {
144                                /*
145                                // println!(
146                                    "(trace.104) マッチしなくなったところで再判定。 rep={}",
147                                    rep
148                                );
149                                // */
150                                return MatchingResult::Matched;
151                            } else {
152                                // println!("(trace.107) fail. rep={}", rep);
153                                return MatchingResult::NotMatch;
154                            }
155                        }
156                        MatchingResult::Matched => {
157                            machine_state.matched_length_in_repeat += 1;
158                            // println!("(trace.112) マッチ中なので続行。 rep={}", rep);
159                            return MatchingResult::Ongoing;
160                        }
161                        MatchingResult::Ongoing => {
162                            machine_state.matched_length_in_repeat += 1;
163                            // println!("(trace.115) rep={}", rep);
164                            return MatchingResult::Ongoing;
165                        }
166                    }
167                }
168            }
169        }
170    }
171
172    pub fn matching3_quantity(
173        &self,
174        machine_state: &mut MachineState,
175        act: &T,
176        exp: &Operator<T>,
177    ) -> MatchingResult
178    where
179        T: std::cmp::PartialEq + std::cmp::PartialOrd,
180    {
181        match exp {
182            Operator::Or(any) => self.matching4_any(machine_state, act, any),
183            Operator::One(exp) => self.matching4_one(machine_state, act, exp),
184        }
185    }
186
187    fn matching4_any(
188        &self,
189        machine_state: &mut MachineState,
190        act: &T,
191        any: &ConditionsVal<T>,
192    ) -> MatchingResult
193    where
194        T: std::cmp::PartialEq + std::cmp::PartialOrd,
195    {
196        for cnd in &any.conditions {
197            match self.matching4_el(machine_state, act, cnd) {
198                MatchingResult::Matched => return MatchingResult::Matched,
199                MatchingResult::Ongoing => return MatchingResult::Ongoing,
200                MatchingResult::NotMatch => {} // 続行。
201            }
202        }
203        // println!("(trace.67) Anyでぜんぶ不一致。");
204        return MatchingResult::NotMatch;
205    }
206    fn matching4_el(
207        &self,
208        machine_state: &mut MachineState,
209        act: &T,
210        el: &Condition<T>,
211    ) -> MatchingResult {
212        match el {
213            Condition::Pin(exa) => {
214                if *exa == *act {
215                    // println!("(trace.138) matching_any/matched.");
216                    MatchingResult::Matched
217                } else {
218                    MatchingResult::NotMatch
219                }
220            }
221            Condition::RangeIncludesMax(rng) => self.matching5_range_contains_max(act, rng),
222            Condition::Seq(vec) => self.matching5_seq(machine_state, act, vec),
223        }
224    }
225    fn matching4_one(
226        &self,
227        machine_state: &mut MachineState,
228        act: &T,
229        nd: &Condition<T>,
230    ) -> MatchingResult
231    where
232        T: std::cmp::PartialEq + std::cmp::PartialOrd,
233    {
234        return self.matching4_el(machine_state, act, nd);
235    }
236    fn matching5_seq(
237        &self,
238        machine_state: &mut MachineState,
239        act: &T,
240        vec: &Vec<T>,
241    ) -> MatchingResult {
242        let result = if machine_state.matched_length_in_seq < vec.len() + 1 {
243            // Ongoing.
244            let el = &vec[machine_state.matched_length_in_seq];
245            if *el == *act {
246                // println!("(trace.72)");
247                MatchingResult::Ongoing
248            } else {
249                // println!("(trace.75)");
250                MatchingResult::NotMatch
251            }
252        } else if machine_state.matched_length_in_seq < vec.len() {
253            // Last
254            let el = &vec[machine_state.matched_length_in_seq];
255            if *el == *act {
256                // println!("(trace.72)");
257                MatchingResult::Matched
258            } else {
259                // println!("(trace.75)");
260                MatchingResult::NotMatch
261            }
262        } else {
263            // Last or more.
264            panic!("(233) Out of bounds in sequence."); //TODO
265        };
266        machine_state.matched_length_in_seq += 1;
267        return result;
268    }
269    fn matching5_range_contains_max(&self, act: &T, rng: &RangeIncludesMaxVal<T>) -> MatchingResult
270    where
271        T: std::cmp::PartialEq + std::cmp::PartialOrd,
272    {
273        if let Some(min) = &rng.min {
274            if *act < *min {
275                return MatchingResult::NotMatch;
276            }
277        }
278        if let Some(max) = &rng.max {
279            if *max < *act {
280                return MatchingResult::NotMatch;
281            }
282        }
283        return MatchingResult::Matched;
284    }
285}
286/*
287impl<T> fmt::Display for MachineVal<T> {
288    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
289        let mut buf = String::new();
290        buf.push_str(&format!("actual_index={} ", self.actual_index));
291        buf.push_str(&format!("expected_index={} ", self.expected_index));
292        buf.push_str(&format!(
293            "matched_length_in_repeat={} ",
294            self.matched_length_in_repeat
295        ));
296        write!(f, "{}", buf)
297    }
298}
299impl<T> fmt::Debug for MachineVal<T> {
300    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
301        let mut buf = String::new();
302        buf.push_str(&format!("actual_index={} ", self.actual_index));
303        buf.push_str(&format!("expected_index={:?} ", self.expected_index));
304        buf.push_str(&format!(
305            "matched_length_in_repeat={} ",
306            self.matched_length_in_repeat
307        ));
308        write!(f, "{}", buf)
309    }
310}
311*/
312
313impl Default for MachineState {
314    fn default() -> Self {
315        MachineState {
316            actual_index: 0,
317            expected_index: 0,
318            is_final: false,
319            matched_length_in_repeat: 0,
320            matched_length_in_seq: 0,
321        }
322    }
323}