harper_core/patterns/
implies_quantity.rs

1use crate::{Token, TokenKind};
2
3use super::SingleTokenPattern;
4
5/// This struct does two things.
6///
7/// First, it acts as a pattern that looks for phrases that describe a quantity of a noun
8/// that may or may not succeed it.
9///
10/// Second, it determines the implied plurality of that quantity.implies
11pub struct ImpliesQuantity;
12
13impl ImpliesQuantity {
14    pub fn implies_plurality(token: &Token, source: &[char]) -> Option<bool> {
15        match &token.kind {
16            TokenKind::Word(Some(lexeme_metadata)) => {
17                if lexeme_metadata.is_determiner() {
18                    return Some(false);
19                }
20
21                let source = token.span.get_content(source);
22
23                match source {
24                    ['a'] => Some(false),
25                    ['a', 'n'] => Some(false),
26                    ['m', 'a', 'n', 'y'] => Some(true),
27                    _ => None,
28                }
29            }
30            TokenKind::Number(number) => Some((number.value.abs() - 1.).abs() > f64::EPSILON),
31            _ => None,
32        }
33    }
34}
35
36impl SingleTokenPattern for ImpliesQuantity {
37    fn matches_token(&self, token: &Token, source: &[char]) -> bool {
38        Self::implies_plurality(token, source).is_some()
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use crate::{
45        Document, Span,
46        patterns::{DocPattern, ImpliesQuantity},
47    };
48
49    #[test]
50    fn number_implies() {
51        let doc = Document::new_plain_english_curated("There are 60 minutes in an hour.");
52
53        assert_eq!(
54            ImpliesQuantity.find_all_matches_in_doc(&doc),
55            vec![Span::new(4, 5), Span::new(10, 11)]
56        )
57    }
58}