harper_core/expr/
reflexive_pronoun.rs1use crate::{
2 Span, Token,
3 expr::{Expr, FirstMatchOf},
4 patterns::WordSet,
5};
6
7const BAD_REFLEXIVE_PRONOUNS: &[&str] = &["hisself", "oneselves", "theirself", "theirselves"];
10
11pub struct ReflexivePronoun {
16 include_common_errors: bool,
17}
18
19impl Default for ReflexivePronoun {
20 fn default() -> Self {
21 Self::standard()
22 }
23}
24
25impl ReflexivePronoun {
26 pub fn standard() -> Self {
31 Self {
32 include_common_errors: false,
33 }
34 }
35
36 pub fn with_common_errors() -> Self {
41 Self {
42 include_common_errors: true,
43 }
44 }
45}
46
47impl Expr for ReflexivePronoun {
48 fn run(&self, cursor: usize, tokens: &[Token], source: &[char]) -> Option<Span<Token>> {
49 let good_pronouns = |token: &Token, _: &[char]| token.kind.is_reflexive_pronoun();
50 let mut expr = FirstMatchOf::new(vec![Box::new(good_pronouns)]);
51 if self.include_common_errors {
52 expr.add(WordSet::new(BAD_REFLEXIVE_PRONOUNS));
53 }
54 expr.run(cursor, tokens, source)
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use crate::{
61 Document, TokenKind,
62 expr::{ExprExt, ReflexivePronoun, reflexive_pronoun::BAD_REFLEXIVE_PRONOUNS},
63 };
64
65 const GOOD_REFLEXIVE_PRONOUNS: &[&str] = &[
68 "herself",
69 "himself",
70 "itself",
71 "myself",
72 "oneself",
73 "ourself",
74 "ourselves",
75 "themselves",
76 "thyself",
77 "yourself",
78 "yourselves",
79 ];
80
81 fn test_pronoun(word: &str) {
82 let doc = Document::new_plain_english_curated(word);
83 let token = doc.tokens().next().expect("No tokens in document");
84
85 let is_good_pron = GOOD_REFLEXIVE_PRONOUNS.contains(&word);
86 let is_bad_pron = BAD_REFLEXIVE_PRONOUNS.contains(&word);
87
88 match (is_good_pron, is_bad_pron, &token.kind) {
89 (true, false, TokenKind::Word(Some(md))) => {
90 assert!(md.is_pronoun());
91 assert!(md.is_reflexive_pronoun());
92 }
93 (true, false, TokenKind::Word(None)) => {
94 panic!("Widely accepted pronoun '{word}' has gone missing from the dictionary!")
95 }
96 (false, true, TokenKind::Word(Some(_))) => panic!(
97 "Unaccepted pronoun '{word}' that's used in bad English is now in the dictionary!"
98 ),
99 (false, true, TokenKind::Word(None)) => {}
100 (false, false, TokenKind::Word(Some(_))) => panic!(
101 "non-pronoun '{word}' is made up just for testing but is now in the dictionary!"
102 ),
103 (false, false, TokenKind::Word(None)) => {}
104 (true, true, _) => panic!("'{word}' is in both good and bad lists"),
105 _ => panic!("'{word}' doesn't match any expected case"),
106 }
107 }
108
109 #[test]
110 fn test_good_reflexive_pronouns() {
111 for word in GOOD_REFLEXIVE_PRONOUNS {
112 test_pronoun(word);
113 }
114 }
115
116 #[test]
117 fn test_bad_reflexive_pronouns() {
118 for word in BAD_REFLEXIVE_PRONOUNS {
119 test_pronoun(word);
120 }
121 }
122
123 #[test]
125 fn test_non_pronouns() {
126 test_pronoun("myselves");
127 test_pronoun("weselves");
128 test_pronoun("usself");
129 test_pronoun("usselves");
130 }
131
132 #[test]
133 fn ensure_standard_ctor_includes_myself() {
134 let doc =
135 Document::new_plain_english_curated("If you want something done, do it yourself.");
136 let rp = ReflexivePronoun::standard();
137 let matches = rp.iter_matches_in_doc(&doc);
138 assert_eq!(matches.count(), 1);
139 }
140
141 #[test]
142 fn ensure_default_ctor_includes_myself() {
143 let doc = Document::new_plain_english_curated(
144 "I wanted a reflexive pronoun module, so I wrote one myself.",
145 );
146 let rp = ReflexivePronoun::default();
147 let matches = rp.iter_matches_in_doc(&doc);
148 assert_eq!(matches.count(), 1);
149 }
150
151 #[test]
152 fn ensure_with_common_errors_includes_hisself() {
153 let doc = Document::new_plain_english_curated("He teached hisself English.");
154 let rp = ReflexivePronoun::with_common_errors();
155 let matches = rp.iter_matches_in_doc(&doc);
156 assert_eq!(matches.count(), 1);
157 }
158
159 #[test]
160 fn ensure_standard_ctor_excludes_hisself() {
161 let doc = Document::new_plain_english_curated("Was he pleased with hisself?");
162 let rp = ReflexivePronoun::standard();
163 let matches = rp.iter_matches_in_doc(&doc);
164 assert_eq!(matches.count(), 0);
165 }
166
167 #[test]
168 fn ensure_default_ctor_excludes_theirself() {
169 let doc = Document::new_plain_english_curated("They look at theirself in the mirror.");
170 let rp = ReflexivePronoun::default();
171 let matches = rp.iter_matches_in_doc(&doc);
172 assert_eq!(matches.count(), 0);
173 }
174}