harper_core/patterns/
nominal_phrase.rs1use crate::Token;
2
3use super::Pattern;
4
5#[derive(Default)]
6pub struct NominalPhrase;
7
8impl Pattern for NominalPhrase {
9 fn matches(&self, tokens: &[Token], _source: &[char]) -> Option<usize> {
10 let mut cursor = 0;
11
12 loop {
13 let tok = tokens.get(cursor)?;
14
15 if tok.kind.is_adjective() || tok.kind.is_determiner() {
16 let next = tokens.get(cursor + 1)?;
17
18 if !next.kind.is_whitespace() {
19 return None;
20 }
21
22 cursor += 2;
23 continue;
24 }
25
26 if tok.kind.is_nominal() {
27 return Some(cursor + 1);
28 }
29
30 return None;
31 }
32 }
33}
34
35#[cfg(test)]
36mod tests {
37 use super::super::DocPattern;
38 use super::NominalPhrase;
39 use crate::{Document, Span, patterns::Pattern};
40
41 #[test]
42 fn simple_apple() {
43 let doc = Document::new_markdown_default_curated("A red apple");
44 let matches = NominalPhrase.find_all_matches_in_doc(&doc);
45
46 assert_eq!(matches, vec![Span::new(0, 5)])
47 }
48
49 #[test]
50 fn complex_apple() {
51 let doc = Document::new_markdown_default_curated("A red apple with a long stem");
52 let matches = NominalPhrase.find_all_matches_in_doc(&doc);
53
54 assert_eq!(matches, vec![Span::new(0, 5), Span::new(8, 13)])
55 }
56
57 #[test]
58 fn list_fruit() {
59 let doc = Document::new_markdown_default_curated("An apple, a banana and a pear");
60 let matches = NominalPhrase.find_all_matches_in_doc(&doc);
61
62 assert_eq!(
63 matches,
64 vec![Span::new(0, 3), Span::new(5, 8), Span::new(11, 14)]
65 )
66 }
67
68 #[test]
69 fn simplest_banana() {
70 let doc = Document::new_markdown_default_curated("a banana");
71 assert!(
72 NominalPhrase
73 .matches(doc.get_tokens(), doc.get_source())
74 .is_some()
75 );
76 }
77
78 #[test]
79 fn food() {
80 let doc = Document::new_markdown_default_curated(
81 "My favorite foods are pizza, sushi, tacos and burgers.",
82 );
83 let matches = NominalPhrase.find_all_matches_in_doc(&doc);
84
85 dbg!(&matches);
86
87 assert_eq!(
88 matches,
89 vec![
90 Span::new(0, 5),
91 Span::new(8, 9),
92 Span::new(11, 12),
93 Span::new(14, 15),
94 Span::new(18, 19)
95 ]
96 )
97 }
98}