metrale_grammar/fsm/builder/
regex_leaf.rs1use crate::fsm::fsm::Fsm;
10use crate::fsm::with_start_end::FsmWithStartEnd;
11
12pub fn handle_escapes(regex: &[u8], start: usize) -> Vec<(i32, i32)> {
15 let c = regex[start + 1];
16 match c {
17 b'n' => vec![('\n' as i32, '\n' as i32)],
18 b't' => vec![('\t' as i32, '\t' as i32)],
19 b'r' => vec![('\r' as i32, '\r' as i32)],
20 b'0' => vec![(0, 0)],
21 b's' => vec![(0, ' ' as i32)],
22 b'S' => vec![(' ' as i32 + 1, 0x00FF)],
23 b'd' => vec![('0' as i32, '9' as i32)],
24 b'D' => vec![(0, '0' as i32 - 1), ('9' as i32 + 1, 0x00FF)],
25 b'w' => vec![
26 ('0' as i32, '9' as i32),
27 ('a' as i32, 'z' as i32),
28 ('A' as i32, 'Z' as i32),
29 ('_' as i32, '_' as i32),
30 ],
31 b'W' => vec![
32 (0, '0' as i32 - 1),
33 ('9' as i32 + 1, 'A' as i32 - 1),
34 ('Z' as i32 + 1, '_' as i32 - 1),
35 ('_' as i32 + 1, 'a' as i32 - 1),
36 ('z' as i32 + 1, 0x00FF),
37 ],
38 other => vec![(other as i32, other as i32)],
39 }
40}
41
42pub fn build_leaf_fsm(regex: &[u8]) -> FsmWithStartEnd {
46 let bytes = regex;
47 let mut result = FsmWithStartEnd::new(Fsm::with_states(0), 0, Vec::new(), true);
48
49 let is_class = !bytes.is_empty() && bytes[0] == b'[' && bytes[bytes.len() - 1] == b']';
50
51 if !is_class {
52 build_literal_leaf(&mut result, bytes);
53 } else {
54 build_class_leaf(&mut result, bytes);
55 }
56 result
57}
58
59fn build_literal_leaf(result: &mut FsmWithStartEnd, bytes: &[u8]) {
61 result.add_state();
62 let mut i = 0;
63 while i < bytes.len() {
64 if bytes[i] != b'\\' {
65 let from = result.num_states() - 1;
66 if bytes[i] == b'.' {
70 result.fsm_mut().add_edge(from, from + 1, 0, 0xFF);
71 } else {
72 let b = bytes[i] as i16;
73 result.fsm_mut().add_edge(from, from + 1, b, b);
74 }
75 result.add_state();
76 i += 1;
77 continue;
78 }
79 let escapes = handle_escapes(bytes, i);
80 let from = result.num_states() - 1;
81 for (lo, hi) in escapes {
82 result
83 .fsm_mut()
84 .add_edge(from, from + 1, lo as u8 as i16, hi as u8 as i16);
85 }
86 result.add_state();
87 i += 2;
88 }
89 let last = result.num_states() - 1;
90 result.add_end_state(last);
91}
92
93fn build_class_leaf(result: &mut FsmWithStartEnd, bytes: &[u8]) {
96 result.add_state();
97 result.add_state();
98 result.add_end_state(1);
99 let reverse = bytes.len() > 1 && bytes[1] == b'^';
100
101 let start_idx = if reverse { 2 } else { 1 };
102 let end_idx = bytes.len() - 1; let mut i = start_idx;
104 while i < end_idx {
105 if bytes[i] != b'\\' {
106 let is_range = i + 2 < end_idx && bytes[i + 1] == b'-';
107 if !is_range {
108 let b = bytes[i] as i16;
109 result.fsm_mut().add_edge(0, 1, b, b);
110 i += 1;
111 continue;
112 }
113 if bytes[i + 2] != b'\\' {
114 result
115 .fsm_mut()
116 .add_edge(0, 1, bytes[i] as i16, bytes[i + 2] as i16);
117 i += 3;
118 continue;
119 }
120 let escaped = handle_escapes(bytes, i + 2);
121 if escaped.len() != 1 || escaped[0].0 != escaped[0].1 {
122 let b = bytes[i] as i16;
123 result.fsm_mut().add_edge(0, 1, b, b);
124 i += 1;
125 continue;
126 }
127 result
129 .fsm_mut()
130 .add_edge(0, 1, bytes[0] as i16, escaped[0].0 as u8 as i16);
131 i += 4;
132 continue;
133 }
134 let escaped = handle_escapes(bytes, i);
136 i += 1;
137 if escaped.len() != 1 || escaped[0].0 != escaped[0].1 {
138 for (lo, hi) in &escaped {
139 result
140 .fsm_mut()
141 .add_edge(0, 1, *lo as u8 as i16, *hi as u8 as i16);
142 }
143 i += 1;
144 continue;
145 }
146 let is_range = i + 2 < end_idx && bytes[i + 1] == b'-';
147 if !is_range {
148 result
149 .fsm_mut()
150 .add_edge(0, 1, escaped[0].0 as u8 as i16, escaped[0].1 as u8 as i16);
151 i += 1;
152 continue;
153 }
154 if bytes[i + 2] != b'\\' {
155 result
156 .fsm_mut()
157 .add_edge(0, 1, escaped[0].0 as u8 as i16, bytes[i + 2] as i16);
158 i += 3;
159 continue;
160 }
161 let rhs = handle_escapes(bytes, i + 2);
162 if rhs.len() != 1 || rhs[0].0 != rhs[0].1 {
163 result
164 .fsm_mut()
165 .add_edge(0, 1, escaped[0].0 as u8 as i16, escaped[0].1 as u8 as i16);
166 i += 1;
167 continue;
168 }
169 result
170 .fsm_mut()
171 .add_edge(0, 1, escaped[0].0 as u8 as i16, rhs[0].0 as u8 as i16);
172 i += 4;
173 }
174
175 let mut has_edge = [false; 0x100];
178 for edge in result.fsm().edges(0) {
179 for c in edge.min..=edge.max {
180 has_edge[c as usize] = true;
181 }
182 }
183 let mut new_fsm = Fsm::with_states(2);
184 let mut last: i64 = -1;
185 let want = !reverse;
186 for c in 0..0x100usize {
187 if has_edge[c] == want {
188 if last == -1 {
189 last = c as i64;
190 }
191 } else if last != -1 {
192 new_fsm.add_edge(0, 1, last as i16, (c - 1) as i16);
193 last = -1;
194 }
195 }
196 if last != -1 {
197 new_fsm.add_edge(0, 1, last as i16, 0xFF);
198 }
199 let mut ends = vec![false; new_fsm.num_states()];
200 ends[1] = true;
201 *result = FsmWithStartEnd::new(new_fsm, 0, ends, false);
202}