1mod all;
4mod any_of;
5mod attr;
6mod attr_eq;
7mod functions;
8mod seq;
9mod token_has_any;
10mod token_text;
11
12pub use all::{All, All2, All3};
13pub use any_of::{AnyOf, AnyOf2, AnyOf2Matcher, AnyOf3, AnyOf3Matcher};
14pub use attr::Attr;
15pub use attr_eq::AttrEq;
16pub use functions::{all, any_of, attr, attr_eq, seq, token_has_any, token_text, whitespace};
17pub use seq::{Seq, Seq2, Seq3};
18pub use token_has_any::TokenHasAny;
19pub use token_text::TokenText;
20
21use super::{LLLine, LLToken, LToken};
22
23pub trait XMatch<'l> {
25 type Out: Copy;
32
33 fn go<M>(&self, direction: &M, ll_line: &'l LLLine) -> Vec<(Self::Out, ToIdx)>
34 where
35 M: XDirection<'l>;
36}
37
38#[derive(PartialEq, Eq, Clone, Copy)]
39pub struct ToIdx(pub(crate) usize);
40
41pub trait XDirection<'l>
42where
43 Self: Sized,
44{
45 fn attr<T: 'static>(&self, ll_line: &'l LLLine) -> Vec<(&'l T, ToIdx)>;
53 fn attr_eq<T: 'static + PartialEq>(&self, equals: &T, ll_line: &'l LLLine) -> Vec<((), ToIdx)>;
54 fn token_attr_one_of<T: 'static + PartialEq>(
55 &self,
56 set: &[T],
57 ll_line: &'l LLLine,
58 ) -> Vec<(&'l T, ToIdx)>;
59 fn text_token(&self, ll_line: &'l LLLine) -> Option<(&'l str, ToIdx)>;
61 fn after(&self, idx: usize, ll_line: &'l LLLine) -> Option<Self>
62 where
63 Self: Sized;
64}
65
66pub(crate) struct XForwards {
67 pub(super) from_idx: usize,
68}
69
70impl<'l> XDirection<'l> for XForwards {
87 fn attr_eq<T: 'static + PartialEq>(&self, equals: &T, ll_line: &'l LLLine) -> Vec<((), ToIdx)> {
88 ll_line
89 .attrs
90 .starts_at
91 .get(self.from_idx)
92 .expect("Huh... match_forwards was at the end")
93 .get::<T>()
94 .iter()
95 .flat_map(|range| {
96 ll_line
97 .attrs
98 .values
99 .get(&range)
100 .unwrap()
101 .get::<T>()
102 .iter()
103 .filter_map(move |val| {
104 if val == equals {
105 Some(((), ToIdx(range.1)))
106 } else {
107 None
108 }
109 })
110 })
111 .collect()
112 }
113
114 fn attr<T: 'static>(&self, ll_line: &'l LLLine) -> Vec<(&'l T, ToIdx)> {
115 ll_line
116 .attrs
117 .starts_at
118 .get(self.from_idx)
119 .expect("Huh... match_forwards was at the end")
120 .get::<T>()
121 .iter()
122 .flat_map(|range| {
123 ll_line
124 .attrs
125 .values
126 .get(&range)
127 .unwrap()
128 .get::<T>()
129 .iter()
130 .map(move |val| (val, ToIdx(range.1)))
131 })
132 .collect()
133 }
134
135 fn token_attr_one_of<T: 'static + PartialEq>(
136 &self,
137 set: &[T],
138 ll_line: &'l LLLine,
139 ) -> Vec<(&'l T, ToIdx)> {
140 ll_line
143 .attrs
144 .values
145 .get(&(self.from_idx, self.from_idx))
146 .expect("Huh... match_forwards was at the end")
147 .get::<T>()
148 .iter()
149 .filter_map(|value| {
150 if set.contains(value) {
151 Some((value, ToIdx(self.from_idx)))
152 } else {
153 None
154 }
155 })
156 .collect()
157 }
158
159 fn text_token(&self, ll_line: &'l LLLine) -> Option<(&'l str, ToIdx)> {
160 match ll_line
163 .ll_tokens
164 .get(self.from_idx)
165 .expect("Huh... XForwards::text_token was out of LLLine")
166 {
167 LLToken {
168 token: LToken::Text(s, _),
169 ..
170 } => Some((s, ToIdx(self.from_idx))),
171 _ => None,
172 }
173 }
174
175 fn after(&self, idx: usize, ll_line: &'l LLLine) -> Option<Self> {
176 let next_idx = idx + 1;
177 if next_idx < ll_line.ll_tokens.len() {
178 Some(XForwards { from_idx: next_idx })
179 } else {
180 None
181 }
182 }
183}
184
185pub(crate) struct XBackwards {
186 pub(super) from_idx: usize,
187}
188
189impl<'l> XDirection<'l> for XBackwards {
190 fn attr_eq<T: 'static + PartialEq>(&self, equals: &T, ll_line: &'l LLLine) -> Vec<((), ToIdx)> {
191 ll_line
195 .attrs
196 .ends_at
197 .get(self.from_idx)
198 .expect("Huh... match_backwards was out of LLLine")
199 .get::<T>()
200 .iter()
201 .flat_map(|range| {
202 ll_line
203 .attrs
204 .values
205 .get(&range)
206 .unwrap()
207 .get::<T>()
208 .iter()
209 .filter_map(move |val| {
210 if val == equals {
211 Some(((), ToIdx(range.0)))
212 } else {
213 None
214 }
215 })
216 })
217 .collect()
218 }
219
220 fn attr<T: 'static>(&self, ll_line: &'l LLLine) -> Vec<(&'l T, ToIdx)> {
221 ll_line
225 .attrs
226 .ends_at
227 .get(self.from_idx)
228 .expect("Huh... Backwards::next_attr was at the start")
229 .get::<T>()
230 .iter()
231 .flat_map(|range| {
232 ll_line
233 .attrs
234 .values
235 .get(&range)
236 .unwrap()
237 .get::<T>()
238 .iter()
239 .map(move |val| (val, ToIdx(range.0)))
240 })
241 .collect()
242 }
243
244 fn token_attr_one_of<T: 'static + PartialEq>(
245 &self,
246 set: &[T],
247 ll_line: &'l LLLine,
248 ) -> Vec<(&'l T, ToIdx)> {
249 ll_line
253 .attrs
254 .ends_at
255 .get(self.from_idx)
256 .expect("Huh... Backwards::next_attr was at the start")
257 .get::<T>()
258 .iter()
259 .flat_map(|range| {
260 ll_line
261 .attrs
262 .values
263 .get(&range)
264 .unwrap()
265 .get::<T>()
266 .iter()
267 .filter_map(move |val| {
268 if set.contains(&val) {
269 Some((val, ToIdx(range.0)))
270 } else {
271 None
272 }
273 })
274 })
275 .collect()
276 }
277
278 fn text_token(&self, ll_line: &'l LLLine) -> Option<(&'l str, ToIdx)> {
279 ll_line
280 .ll_tokens()
281 .get(self.from_idx)
282 .and_then(|token| match &token.token {
283 LToken::Text(text, _) => Some((text.as_str(), ToIdx(self.from_idx))),
284 LToken::Value => None,
285 })
286 }
287
288 fn after(&self, idx: usize, _: &'l LLLine) -> Option<Self> {
289 if idx > 0 {
290 Some(XBackwards {
291 from_idx: self.from_idx - 1,
292 })
293 } else {
294 None
295 }
296 }
297}