harper_core/patterns/
repeating_pattern.rs1use super::Pattern;
2use crate::Token;
3
4pub struct RepeatingPattern {
8 inner: Box<dyn Pattern>,
9 required_repetitions: usize,
10}
11
12impl RepeatingPattern {
13 pub fn new(pattern: Box<dyn Pattern>, required_repetitions: usize) -> Self {
14 Self {
15 inner: pattern,
16 required_repetitions,
17 }
18 }
19}
20
21impl Pattern for RepeatingPattern {
22 fn matches(&self, tokens: &[Token], source: &[char]) -> usize {
23 let mut tok_cursor = 0;
24 let mut repetition = 0;
25
26 loop {
27 let match_len = self.inner.matches(&tokens[tok_cursor..], source);
28
29 if match_len == 0 {
30 if repetition >= self.required_repetitions {
31 return tok_cursor;
32 } else {
33 return 0;
34 }
35 } else {
36 tok_cursor += match_len;
37 repetition += 1;
38 }
39 }
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::RepeatingPattern;
46 use crate::Document;
47 use crate::patterns::{AnyPattern, Pattern};
48
49 #[test]
50 fn matches_anything() {
51 let doc = Document::new_plain_english_curated(
52 "This matcher will match the entirety of any document!",
53 );
54 let pat = RepeatingPattern::new(Box::new(AnyPattern), 0);
55
56 assert_eq!(
57 pat.matches(doc.get_tokens(), doc.get_source()),
58 doc.get_tokens().len()
59 )
60 }
61
62 #[test]
63 fn does_not_match_short() {
64 let doc = Document::new_plain_english_curated("No match");
65 let pat = RepeatingPattern::new(Box::new(AnyPattern), 4);
66
67 assert_eq!(pat.matches(doc.get_tokens(), doc.get_source()), 0)
68 }
69}