ct_regex_internal/matcher/interface.rs
1use std::fmt::Debug;
2
3use crate::expr::IndexedCaptures;
4use crate::haystack::{HaystackItem, HaystackOf};
5use crate::sealed::Sealed;
6
7pub trait Matcher<I: HaystackItem>: Sealed + Debug + Default + Clone + Copy {
8 type AllMatches<'a, H: HaystackOf<'a, I>>: Iterator<Item = usize>;
9 type AllCaptures<'a, H: HaystackOf<'a, I>>: Iterator<Item = (usize, IndexedCaptures)>;
10
11 /// Checks if the start of the haystack contains a match for this [`Matcher`]. If this method
12 /// successfully matches the start of the haystack, `hay` is progressed so that `hay.item()`
13 /// hasn't been matched yet. On a fail, the state of hay is undefined.
14 fn matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> bool;
15
16 /// Produces a Vec of all valid haystack states produced as the result of a valid match at the
17 /// start of `hay`, used to implement backtracking. The Vec is produced in reverse priority
18 /// order, so the last match has the highest priority. After calling all_matches, the state of
19 /// `hay` itself is undefined.
20 ///
21 /// # Required
22 /// This method needs to be implemented by all [`Matcher`]s that can match more than one string
23 /// of characters from a haystack.
24 fn all_matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> Self::AllMatches<'a, H>;
25
26 /// Checks if the start of the haystack contains a match for this Matcher, writing any groups
27 /// to `caps`. Similar to [`matches`], this method progresses `hay` and `caps` on a success. On
28 /// a fail, they have undefined states.
29 ///
30 /// # Required
31 /// This method needs to be implemented for capturing groups or any type that holds other
32 /// [`Matcher`]s, so that it can redirect to the relevant `capture` methods.
33 fn captures<'a, H: HaystackOf<'a, I>>(hay: &mut H, caps: &mut IndexedCaptures) -> bool {
34 let _ = caps;
35 Self::matches(hay)
36 }
37
38 /// Produces a Vec of all valid captures (and accompanying haystack states) present at the start
39 /// of `hay`. Used to implement backtracking for capturing methods. As with
40 /// [`all_matches`](Matcher::all_matches), the resulting Vec is produced in reverse priority
41 /// order. After calling all_captures, the state of `hay` and `caps` are undefined.
42 ///
43 /// # Required
44 /// This method needs to be implemented for any type that also implements
45 /// [`captures`](Matcher::captures) and [`all_matches`](Matcher::all_matches).
46 fn all_captures<'a, H: HaystackOf<'a, I>>(
47 hay: &mut H,
48 caps: &mut IndexedCaptures,
49 ) -> Self::AllCaptures<'a, H>;
50}
51
52// I'm just going to write this down cause I seem to keep forgetting. For alternations, either
53// branch may match a longer sequence in the haystack, but the first branch should be the priority.
54// This would complicate lazy semantics beyond just reversing the order of return values if it
55// wasn't for the simple fact that *alternations can't be lazy*. Laziness only applies to
56// quantifiers, even if that quantifiers is a 0-1 ("??" in the expression). Because there is always
57// a type between Lazy and Or in the type expression, it doesn't matter.
58// - Or<Lazy<..>, Lazy<..>> is valid and has clear semantics. No need for any special logic.
59// - Lazy<QuantifierNOrMore<Or<..>, N>> is also valid and matches Or eagerly during every
60// repetition, rolling back if necessary.
61// - Lazy<Or<..>> is where things would get complicated, but there is no way to express it in an
62// expression.
63
64pub trait LazyMatcher<I: HaystackItem>: Matcher<I> {
65 type LazyAllMatches<'a, H: HaystackOf<'a, I>>: Iterator<Item = usize>;
66 type LazyAllCaptures<'a, H: HaystackOf<'a, I>>: Iterator<Item = (usize, IndexedCaptures)>;
67
68 /// Functions exactly the same as [`Matcher::matches`], except that the haystack's index is left
69 /// at the first location where the match is considered successful.
70 fn lazy_matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> bool;
71
72 /// Functions exactly the same as [`Matcher::all_matches`], except that the indices are produced
73 /// in the opposite order. The first value returned by the iterator is the one first encountered
74 /// in the haystack, not the one that produces the longest match.
75 fn lazy_all_matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> Self::LazyAllMatches<'a, H>;
76
77 /// Functions exactly the same as [`Matcher::captures`], except that the haystack's index and
78 /// captures represent the first location where the match is considered successful.
79 fn lazy_captures<'a, H: HaystackOf<'a, I>>(hay: &mut H, caps: &mut IndexedCaptures) -> bool;
80
81 /// Functions exactly the same as [`Matcher::all_captures`], except that the indices and
82 /// captures are produced in the opposite order. The first value returned by the iterator is the
83 /// one first encountered in the haystack, not the one that produces the longest match.
84 fn lazy_all_captures<'a, H: HaystackOf<'a, I>>(
85 hay: &mut H,
86 caps: &mut IndexedCaptures,
87 ) -> Self::LazyAllCaptures<'a, H>;
88}