litcheck_filecheck/pattern/matcher/matchers/
any.rs1use crate::common::*;
2
3use super::{MatchAll, RegexSetMatcher, SubstringSetMatcher};
4
5#[derive(Debug)]
6pub enum MatchAny<'a> {
7 Literal(SubstringSetMatcher<'a>),
9 Regex(RegexSetMatcher<'a>),
11 AnyPrefix {
18 prefixes: Vec<Pattern<'a>>,
20 suffixes: Vec<Vec<Pattern<'a>>>,
22 },
23 RegexPrefix {
26 prefixes: RegexSetMatcher<'a>,
27 suffixes: Vec<Vec<Pattern<'a>>>,
28 },
29 SubstringPrefix {
32 prefixes: SubstringSetMatcher<'a>,
33 suffixes: Vec<Vec<Pattern<'a>>>,
34 },
35}
36impl<'a> From<MatchAll<'a>> for MatchAny<'a> {
37 fn from(match_all: MatchAll<'a>) -> Self {
38 match match_all {
39 MatchAll::Literal(lit) => Self::Literal(lit),
40 MatchAll::Regex(re) => Self::Regex(re),
41 MatchAll::AnyPrefix { prefixes, suffixes } => Self::AnyPrefix { prefixes, suffixes },
42 MatchAll::SubstringPrefix { prefixes, suffixes } => {
43 Self::SubstringPrefix { prefixes, suffixes }
44 }
45 MatchAll::RegexPrefix { prefixes, suffixes } => {
46 Self::RegexPrefix { prefixes, suffixes }
47 }
48 }
49 }
50}
51impl<'a> MatchAny<'a> {
52 pub fn pattern_len(&self) -> usize {
53 match self {
54 Self::Literal(ref matcher) => matcher.pattern_len(),
55 Self::Regex(ref matcher) => matcher.patterns_len(),
56 Self::AnyPrefix { suffixes, .. }
57 | Self::RegexPrefix { suffixes, .. }
58 | Self::SubstringPrefix { suffixes, .. } => suffixes.iter().map(|ps| ps.len()).sum(),
59 }
60 }
61
62 pub fn first_pattern(&self) -> Span<usize> {
63 match self {
64 Self::Literal(matcher) => matcher.first_pattern(),
65 Self::Regex(matcher) => matcher.first_pattern(),
66 Self::AnyPrefix {
67 ref prefixes,
68 ref suffixes,
69 } => {
70 let (prefix_id, start) = prefixes
71 .iter()
72 .enumerate()
73 .map(|(i, p)| (i, p.span().start()))
74 .min_by_key(|&(_, s)| s)
75 .unwrap();
76 let (offset, end) = suffixes[prefix_id]
77 .iter()
78 .enumerate()
79 .map(|(offset, p)| (offset, p.span().end()))
80 .min_by_key(|&(_, e)| e)
81 .unwrap();
82 Span::new(SourceSpan::from(start..end), prefix_id + offset)
83 }
84 Self::RegexPrefix {
85 ref prefixes,
86 ref suffixes,
87 } => {
88 let (first_prefix_span, first_prefix) = prefixes.first_pattern().into_parts();
89 let start = first_prefix_span.start();
90 let (offset, end) = suffixes[first_prefix]
91 .iter()
92 .enumerate()
93 .map(|(offset, p)| (offset, p.span().end()))
94 .min_by_key(|&(_, end)| end)
95 .unwrap();
96 Span::new(SourceSpan::from(start..end), first_prefix + offset)
97 }
98 Self::SubstringPrefix {
99 ref prefixes,
100 ref suffixes,
101 } => {
102 let (first_prefix_span, first_prefix) = prefixes.first_pattern().into_parts();
103 let start = first_prefix_span.start();
104 let (offset, end) = suffixes[first_prefix]
105 .iter()
106 .enumerate()
107 .map(|(offset, p)| (offset, p.span().end()))
108 .min_by_key(|&(_, end)| end)
109 .unwrap();
110 Span::new(SourceSpan::from(start..end), first_prefix + offset)
111 }
112 }
113 }
114
115 pub fn first_pattern_span(&self) -> SourceSpan {
116 self.first_pattern().span()
117 }
118}
119impl<'a> Spanned for MatchAny<'a> {
120 fn span(&self) -> SourceSpan {
121 match self {
122 Self::Literal(ref matcher) => matcher.span(),
123 Self::Regex(ref matcher) => matcher.span(),
124 Self::AnyPrefix {
125 ref prefixes,
126 ref suffixes,
127 } => {
128 let start = prefixes
129 .iter()
130 .map(|prefix| prefix.span().start())
131 .min()
132 .unwrap();
133 let end = prefixes
134 .iter()
135 .zip(suffixes.iter())
136 .map(|(prefix, suffixes)| {
137 suffixes
138 .iter()
139 .map(|p| p.span().end())
140 .max()
141 .unwrap_or(prefix.span().end())
142 })
143 .max()
144 .unwrap();
145 SourceSpan::from(start..end)
146 }
147 Self::RegexPrefix {
148 ref prefixes,
149 ref suffixes,
150 } => {
151 let prefix_span = prefixes.span();
152 let start = prefix_span.start();
153 let prefix_end = prefix_span.end();
154 let end = core::cmp::max(
155 prefix_end,
156 suffixes
157 .iter()
158 .map(|suffixes| {
159 suffixes
160 .iter()
161 .map(|p| p.span().end())
162 .max()
163 .unwrap_or(prefix_end)
164 })
165 .max()
166 .unwrap(),
167 );
168 SourceSpan::from(start..end)
169 }
170 Self::SubstringPrefix {
171 ref prefixes,
172 ref suffixes,
173 } => {
174 let prefix_span = prefixes.span();
175 let start = prefix_span.start();
176 let prefix_end = prefix_span.end();
177 let end = core::cmp::max(
178 prefix_end,
179 suffixes
180 .iter()
181 .map(|suffixes| {
182 suffixes
183 .iter()
184 .map(|p| p.span().end())
185 .max()
186 .unwrap_or(prefix_end)
187 })
188 .max()
189 .unwrap(),
190 );
191 SourceSpan::from(start..end)
192 }
193 }
194 }
195}
196impl<'a> MatcherMut for MatchAny<'a> {
197 fn try_match_mut<'input, 'context, C>(
198 &self,
199 input: Input<'input>,
200 context: &mut C,
201 ) -> DiagResult<MatchResult<'input>>
202 where
203 C: Context<'input, 'context> + ?Sized,
204 {
205 use crate::pattern::search::PatternSetSearcher;
206
207 match self {
208 Self::Literal(ref matcher) => matcher.try_match_mut(input, context),
209 Self::Regex(ref matcher) => matcher.try_match_mut(input, context),
210 Self::AnyPrefix {
211 ref prefixes,
212 ref suffixes,
213 } => {
214 let searcher = PatternSetSearcher::new(input, prefixes)?;
215 try_match_searcher(searcher, suffixes, input, context)
216 }
217 Self::RegexPrefix {
218 ref prefixes,
219 ref suffixes,
220 } => try_match_searcher(prefixes.search(input), suffixes, input, context),
221 Self::SubstringPrefix {
222 ref prefixes,
223 ref suffixes,
224 } => try_match_searcher(prefixes.search(input)?, suffixes, input, context),
225 }
226 }
227}
228
229fn try_match_searcher<'input, 'context, 'a, S, C>(
230 mut searcher: S,
231 suffixes: &[Vec<Pattern<'a>>],
232 input: Input<'input>,
233 context: &mut C,
234) -> DiagResult<MatchResult<'input>>
235where
236 S: PatternSearcher<'input>,
237 C: Context<'input, 'context> + ?Sized,
238{
239 loop {
240 match searcher.try_match_next(context)? {
241 MatchResult {
242 info: Some(ref mut info),
243 ty: MatchType::MatchFoundAndExpected,
244 } => {
245 let mut suffix_input = input;
246 suffix_input.set_start(searcher.last_match_end().unwrap());
247 suffix_input.set_anchored(true);
248 let suffixes = &suffixes[info.pattern_id];
249 if let Some(found) =
250 try_match_suffix(info, suffixes, info.pattern_id, suffix_input, context)?
251 {
252 break Ok(found);
253 }
254 }
255 result @ MatchResult { info: None, .. } => break Ok(result),
256 _ => continue,
257 }
258 }
259}
260
261fn try_match_suffix<'input, 'context, 'a, C>(
262 prefix_info: &mut MatchInfo<'input>,
263 suffixes: &[Pattern<'a>],
264 mut pattern_id: usize,
265 input: Input<'input>,
266 context: &mut C,
267) -> DiagResult<Option<MatchResult<'input>>>
268where
269 C: Context<'input, 'context> + ?Sized,
270{
271 for suffix in suffixes.iter() {
272 match suffix.try_match_mut(input, context)? {
273 MatchResult {
274 info: Some(mut suffix_info),
275 ty: MatchType::MatchFoundAndExpected,
276 } => {
277 let mut captures = core::mem::take(&mut prefix_info.captures);
279 captures.append(&mut suffix_info.captures);
280 return Ok(Some(MatchResult::ok(MatchInfo {
281 pattern_id,
282 span: SourceSpan::from(prefix_info.span.start()..suffix_info.span.end()),
283 captures,
284 ..suffix_info
285 })));
286 }
287 MatchResult {
288 info: Some(mut info),
289 ty,
290 } => {
291 info.pattern_id = pattern_id;
293 return Ok(Some(MatchResult {
294 info: Some(info),
295 ty,
296 }));
297 }
298 _ => {
299 pattern_id += 1;
301 }
302 }
303 }
304
305 Ok(None)
306}