harper_core/patterns/
word_pattern_group.rs

1use hashbrown::HashMap;
2
3use super::naive_pattern_group::NaivePatternGroup;
4use super::{Pattern, SequencePattern};
5use crate::CharString;
6
7/// A pattern collection to look for patterns that start with a specific
8/// word.
9#[derive(Default)]
10pub struct WordPatternGroup<P>
11where
12    P: Pattern,
13{
14    patterns: HashMap<CharString, P>,
15}
16
17impl WordPatternGroup<NaivePatternGroup> {
18    pub fn add(&mut self, word: &str, pat: Box<dyn Pattern>) {
19        let chars = word.chars().collect();
20
21        if let Some(group) = self.patterns.get_mut(&chars) {
22            group.push(pat);
23        } else {
24            let mut group = NaivePatternGroup::default();
25            group.push(pat);
26            self.patterns.insert(chars, group);
27        }
28    }
29
30    /// Add a pattern that matches just a word on its own, without anything else required to match.
31    pub fn add_word(&mut self, word: &'static str) {
32        self.add(
33            word,
34            Box::new(SequencePattern::default().then_exact_word(word)),
35        );
36    }
37}
38
39impl<P> Pattern for WordPatternGroup<P>
40where
41    P: Pattern,
42{
43    fn matches(&self, tokens: &[crate::Token], source: &[char]) -> Option<usize> {
44        let first = tokens.first()?;
45        if !first.kind.is_word() {
46            return None;
47        }
48
49        let word_chars = first.span.get_content(source);
50        let inner_pattern = self.patterns.get(word_chars)?;
51
52        inner_pattern.matches(tokens, source)
53    }
54}