metrale_grammar/fsm/
fsm_ops.rs1use super::fsm::Fsm;
9use super::with_start_end::FsmWithStartEnd;
10
11impl FsmWithStartEnd {
12 pub fn star(&self) -> FsmWithStartEnd {
14 let mut fsm = self.fsm.clone();
15 let new_start = fsm.add_state();
16 for end in 0..self.num_states() {
17 if self.is_end_state(end) {
18 fsm.add_epsilon_edge(end, new_start);
19 }
20 }
21 fsm.add_epsilon_edge(new_start, self.start);
22 let mut is_end = vec![false; self.num_states() + 1];
23 is_end[new_start] = true;
24 FsmWithStartEnd::new(fsm, new_start, is_end, false)
25 }
26
27 pub fn plus(&self) -> FsmWithStartEnd {
29 let mut fsm = self.fsm.clone();
30 for end in 0..self.num_states() {
31 if self.is_end_state(end) {
32 fsm.add_epsilon_edge(end, self.start);
33 }
34 }
35 FsmWithStartEnd::new(fsm, self.start, self.ends.clone(), false)
36 }
37
38 pub fn optional(&self) -> FsmWithStartEnd {
40 let mut fsm = self.fsm.clone();
41 for end in 0..self.num_states() {
42 if self.is_end_state(end) {
43 fsm.add_epsilon_edge(self.start, end);
44 break;
45 }
46 }
47 FsmWithStartEnd::new(fsm, self.start, self.ends.clone(), false)
48 }
49
50 pub fn union(fsms: &[FsmWithStartEnd]) -> FsmWithStartEnd {
52 if fsms.len() == 1 {
53 return fsms[0].clone();
54 }
55 debug_assert!(fsms.len() > 1, "Union of 0 FSMs is not allowed.");
56 let mut fsm = Fsm::with_states(1);
57 let start = 0;
58 let mut ends = vec![false];
59 for sub in fsms {
60 let mapping = fsm.add_fsm(&sub.fsm);
61 fsm.add_epsilon_edge(start, mapping[sub.start]);
62 for state in 0..sub.num_states() {
63 ends.push(sub.is_end_state(state));
64 }
65 }
66 FsmWithStartEnd::new(fsm, start, ends, false)
67 }
68
69 pub fn concat(fsms: &[FsmWithStartEnd]) -> FsmWithStartEnd {
71 if fsms.len() == 1 {
72 return fsms[0].clone();
73 }
74 debug_assert!(fsms.len() > 1, "Concatenation of 0 FSMs is not allowed.");
75 let mut fsm = Fsm::with_states(0);
76 let mut start = 0;
77 let mut ends: Vec<bool> = Vec::new();
78 let mut previous_ends: Vec<usize> = Vec::new();
79 let last = fsms.len() - 1;
80 for (i, sub) in fsms.iter().enumerate() {
81 let mapping = fsm.add_fsm(&sub.fsm);
82 if i == 0 {
83 start = mapping[sub.start];
84 } else {
85 let this_start = mapping[sub.start];
86 for &end in &previous_ends {
87 fsm.add_epsilon_edge(end, this_start);
88 }
89 }
90 if i == last {
91 ends = vec![false; fsm.num_states()];
92 for end in 0..sub.num_states() {
93 if sub.is_end_state(end) {
94 ends[mapping[end]] = true;
95 }
96 }
97 } else {
98 previous_ends.clear();
99 for end in 0..sub.num_states() {
100 if sub.is_end_state(end) {
101 previous_ends.push(mapping[end]);
102 }
103 }
104 }
105 }
106 FsmWithStartEnd::new(fsm, start, ends, false)
107 }
108}