1use harper_brill::UPOS;
2use is_macro::Is;
3use itertools::Itertools;
4use paste::paste;
5use serde::{Deserialize, Serialize};
6use smallvec::SmallVec;
7use strum::{EnumCount as _, VariantArray as _};
8use strum_macros::{Display, EnumCount, EnumIter, EnumString, VariantArray};
9
10use std::convert::TryFrom;
11
12use crate::dict_word_metadata_orthography::OrthFlags;
13use crate::spell::WordId;
14use crate::{Document, TokenKind, TokenStringExt};
15
16#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Hash)]
20pub struct DictWordMetadata {
21 pub noun: Option<NounData>,
23 pub pronoun: Option<PronounData>,
24 pub verb: Option<VerbData>,
25 pub adjective: Option<AdjectiveData>,
26 pub adverb: Option<AdverbData>,
27 pub conjunction: Option<ConjunctionData>,
28 pub determiner: Option<DeterminerData>,
29 pub affix: Option<AffixData>,
30 #[serde(default = "default_false")]
33 pub preposition: bool,
34 pub swear: Option<bool>,
36 pub abbreviation: Option<bool>,
38 #[serde(default = "default_default")]
42 pub dialects: DialectFlags,
43 #[serde(default = "OrthFlags::empty")]
45 pub orth_info: OrthFlags,
46 #[serde(default = "default_false")]
48 pub common: bool,
49 #[serde(default = "default_none")]
50 pub derived_from: Option<WordId>,
51 pub np_member: Option<bool>,
56 pub pos_tag: Option<UPOS>,
58}
59
60fn default_false() -> bool {
62 false
63}
64
65fn default_none<T>() -> Option<T> {
67 None
68}
69
70fn default_default<T: Default>() -> T {
72 T::default()
73}
74
75macro_rules! generate_metadata_queries {
76 ($($category:ident has $($sub:ident),*).*) => {
77 paste! {
78 pub fn is_likely_homograph(&self) -> bool {
79 [self.is_determiner(), self.preposition, $(
80 self.[< is_ $category >](),
81 )*].iter().map(|b| *b as u8).sum::<u8>() > 1
82 }
83
84 pub fn difference(&self, other: &Self) -> u32 {
86 [
87 $(
88 Self::[< is_ $category >],
89 $(
90 Self::[< is_ $sub _ $category >],
91 Self::[< is_non_ $sub _ $category >],
92 )*
93 )*
94 ]
95 .iter()
96 .fold(0, |acc, func| acc + (func(self) ^ func(other)) as u32)
97 }
98
99 $(
100 #[doc = concat!("Checks if the word is definitely a ", stringify!($category), ".")]
101 pub fn [< is_ $category >](&self) -> bool {
102 self.$category.is_some()
103 }
104
105 $(
106 #[doc = concat!("Checks if the word is definitely a ", stringify!($category), " and more specifically is labeled as (a) ", stringify!($sub), ".")]
107 pub fn [< is_ $sub _ $category >](&self) -> bool {
108 matches!(
109 self.$category,
110 Some([< $category:camel Data >]{
111 [< is_ $sub >]: Some(true),
112 ..
113 })
114 ) }
115
116 #[doc = concat!("Checks if the word is definitely a ", stringify!($category), " and more specifically is labeled as __not__ (a) ", stringify!($sub), ".")]
117 pub fn [< is_non_ $sub _ $category >](&self) -> bool {
118 matches!(
119 self.$category,
120 Some([< $category:camel Data >]{
121 [< is_ $sub >]: None | Some(false),
122 ..
123 })
124 )
125 }
126 )*
127 )*
128 }
129 };
130}
131
132impl DictWordMetadata {
133 pub fn infer_pos_tag(&self) -> Option<UPOS> {
135 if let Some(pos) = self.pos_tag {
137 return Some(pos);
138 }
139
140 let mut candidates = SmallVec::<[UPOS; 14]>::with_capacity(14);
142
143 if self.is_proper_noun() {
144 candidates.push(UPOS::PROPN);
145 }
146
147 if self.is_pronoun() {
148 candidates.push(UPOS::PRON);
149 }
150 if self.is_noun() {
151 candidates.push(UPOS::NOUN);
152 }
153 if self.is_verb() {
154 if let Some(data) = &self.verb {
156 if data.is_auxiliary == Some(true) {
157 candidates.push(UPOS::AUX);
158 } else {
159 candidates.push(UPOS::VERB);
160 }
161 } else {
162 candidates.push(UPOS::VERB);
163 }
164 }
165 if self.is_adjective() {
166 candidates.push(UPOS::ADJ);
167 }
168 if self.is_adverb() {
169 candidates.push(UPOS::ADV);
170 }
171 if self.is_conjunction() {
172 candidates.push(UPOS::CCONJ);
173 }
174 if self.is_determiner() {
175 candidates.push(UPOS::DET);
176 }
177 if self.preposition {
178 candidates.push(UPOS::ADP);
179 }
180
181 candidates.sort();
183 candidates.dedup();
184
185 candidates.into_iter().exactly_one().ok()
186 }
187
188 pub fn or(&self, other: &Self) -> Self {
190 let mut clone = self.clone();
191 clone.merge(other);
192 clone
193 }
194
195 pub fn enforce_pos_exclusivity(&mut self, pos: &UPOS) {
203 use UPOS::*;
204 match pos {
205 NOUN => {
206 if let Some(noun) = self.noun {
207 self.noun = Some(NounData {
208 is_proper: Some(false),
209 ..noun
210 })
211 } else {
212 self.noun = Some(NounData {
213 is_proper: Some(false),
214 is_singular: None,
215 is_plural: None,
216 is_countable: None,
217 is_mass: None,
218 is_possessive: None,
219 })
220 }
221
222 self.pronoun = None;
223 self.verb = None;
224 self.adjective = None;
225 self.adverb = None;
226 self.conjunction = None;
227 self.determiner = None;
228 self.affix = None;
229 self.preposition = false;
230 }
231 PROPN => {
232 if let Some(noun) = self.noun {
233 self.noun = Some(NounData {
234 is_proper: Some(true),
235 ..noun
236 })
237 } else {
238 self.noun = Some(NounData {
239 is_proper: Some(true),
240 is_singular: None,
241 is_plural: None,
242 is_countable: None,
243 is_mass: None,
244 is_possessive: None,
245 })
246 }
247
248 self.pronoun = None;
249 self.verb = None;
250 self.adjective = None;
251 self.adverb = None;
252 self.conjunction = None;
253 self.determiner = None;
254 self.affix = None;
255 self.preposition = false;
256 }
257 PRON => {
258 if self.pronoun.is_none() {
259 self.pronoun = Some(PronounData::default())
260 }
261
262 self.noun = None;
263 self.verb = None;
264 self.adjective = None;
265 self.adverb = None;
266 self.conjunction = None;
267 self.determiner = None;
268 self.affix = None;
269 self.preposition = false;
270 }
271 VERB => {
272 if let Some(verb) = self.verb {
273 self.verb = Some(VerbData {
274 is_auxiliary: Some(false),
275 ..verb
276 })
277 } else {
278 self.verb = Some(VerbData {
279 is_auxiliary: Some(false),
280 ..Default::default()
281 })
282 }
283
284 self.noun = None;
285 self.pronoun = None;
286 self.adjective = None;
287 self.adverb = None;
288 self.conjunction = None;
289 self.determiner = None;
290 self.affix = None;
291 self.preposition = false;
292 }
293 AUX => {
294 if let Some(verb) = self.verb {
295 self.verb = Some(VerbData {
296 is_auxiliary: Some(true),
297 ..verb
298 })
299 } else {
300 self.verb = Some(VerbData {
301 is_auxiliary: Some(true),
302 ..Default::default()
303 })
304 }
305
306 self.noun = None;
307 self.pronoun = None;
308 self.adjective = None;
309 self.adverb = None;
310 self.conjunction = None;
311 self.determiner = None;
312 self.affix = None;
313 self.preposition = false;
314 }
315 ADJ => {
316 if self.adjective.is_none() {
317 self.adjective = Some(AdjectiveData::default())
318 }
319
320 self.noun = None;
321 self.pronoun = None;
322 self.verb = None;
323 self.adverb = None;
324 self.conjunction = None;
325 self.determiner = None;
326 self.affix = None;
327 self.preposition = false;
328 }
329 ADV => {
330 if self.adverb.is_none() {
331 self.adverb = Some(AdverbData::default())
332 }
333
334 self.noun = None;
335 self.pronoun = None;
336 self.verb = None;
337 self.adjective = None;
338 self.conjunction = None;
339 self.determiner = None;
340 self.affix = None;
341 self.preposition = false;
342 }
343 ADP => {
344 self.noun = None;
345 self.pronoun = None;
346 self.verb = None;
347 self.adjective = None;
348 self.adverb = None;
349 self.conjunction = None;
350 self.determiner = None;
351 self.affix = None;
352 self.preposition = true;
353 }
354 DET => {
355 self.noun = None;
356 self.pronoun = None;
357 self.verb = None;
358 self.adjective = None;
359 self.adverb = None;
360 self.conjunction = None;
361 self.affix = None;
362 self.preposition = false;
363 self.determiner = Some(DeterminerData::default());
364 }
365 CCONJ | SCONJ => {
366 if self.conjunction.is_none() {
367 self.conjunction = Some(ConjunctionData::default())
368 }
369
370 self.noun = None;
371 self.pronoun = None;
372 self.verb = None;
373 self.adjective = None;
374 self.adverb = None;
375 self.determiner = None;
376 self.affix = None;
377 self.preposition = false;
378 }
379 _ => {}
380 }
381 }
382
383 generate_metadata_queries!(
387 noun has proper, plural, mass, possessive.
389 pronoun has personal, singular, plural, possessive, reflexive, subject, object.
390 determiner has demonstrative, possessive, quantifier.
391 verb has linking, auxiliary.
392 conjunction has.
393 adjective has.
394 adverb has manner, frequency, degree
395 );
396
397 pub fn get_person(&self) -> Option<Person> {
403 self.pronoun.as_ref().and_then(|p| p.person)
404 }
405
406 pub fn is_first_person_plural_pronoun(&self) -> bool {
408 matches!(
409 self.pronoun,
410 Some(PronounData {
411 person: Some(Person::First),
412 is_plural: Some(true),
413 ..
414 })
415 )
416 }
417
418 pub fn is_first_person_singular_pronoun(&self) -> bool {
420 matches!(
421 self.pronoun,
422 Some(PronounData {
423 person: Some(Person::First),
424 is_singular: Some(true),
425 ..
426 })
427 )
428 }
429
430 pub fn is_third_person_plural_pronoun(&self) -> bool {
432 matches!(
433 self.pronoun,
434 Some(PronounData {
435 person: Some(Person::Third),
436 is_plural: Some(true),
437 ..
438 })
439 )
440 }
441
442 pub fn is_third_person_singular_pronoun(&self) -> bool {
444 matches!(
445 self.pronoun,
446 Some(PronounData {
447 person: Some(Person::Third),
448 is_singular: Some(true),
449 ..
450 })
451 )
452 }
453
454 pub fn is_third_person_pronoun(&self) -> bool {
456 matches!(
457 self.pronoun,
458 Some(PronounData {
459 person: Some(Person::Third),
460 ..
461 })
462 )
463 }
464
465 pub fn is_second_person_pronoun(&self) -> bool {
467 matches!(
468 self.pronoun,
469 Some(PronounData {
470 person: Some(Person::Second),
471 ..
472 })
473 )
474 }
475
476 pub fn is_verb_lemma(&self) -> bool {
478 if let Some(verb) = self.verb {
479 if let Some(forms) = verb.verb_forms {
480 return forms.is_empty() || forms.contains(VerbFormFlags::LEMMA);
481 } else {
482 return true;
483 }
484 }
485 false
486 }
487
488 pub fn is_verb_past_form(&self) -> bool {
493 self.verb.is_some_and(|v| {
494 v.verb_forms
495 .is_some_and(|vf| vf.contains(VerbFormFlags::PAST))
496 })
497 }
498
499 pub fn is_verb_preterite_and_participle_form(&self) -> bool {
504 self.verb.is_some_and(|v| {
505 v.verb_forms.is_some_and(|vf| {
506 vf.contains(VerbFormFlags::PRETERITE) && vf.contains(VerbFormFlags::PAST_PARTICIPLE)
507 })
508 })
509 }
510
511 pub fn is_verb_simple_past_form(&self) -> bool {
515 self.verb.is_some_and(|v| {
516 v.verb_forms
517 .is_some_and(|vf| vf.contains(VerbFormFlags::PRETERITE))
518 })
519 }
520
521 pub fn is_verb_past_participle_form(&self) -> bool {
525 self.verb.is_some_and(|v| {
526 v.verb_forms
527 .is_some_and(|vf| vf.contains(VerbFormFlags::PAST_PARTICIPLE))
528 })
529 }
530
531 pub fn is_verb_simple_past_only(&self) -> bool {
534 self.verb.is_some_and(|v| {
535 v.verb_forms.is_some_and(|vf| {
536 vf.contains(VerbFormFlags::PRETERITE)
537 && !vf.intersects(VerbFormFlags::PAST | VerbFormFlags::PAST_PARTICIPLE)
538 })
539 })
540 }
541
542 pub fn is_verb_past_participle_only(&self) -> bool {
545 self.verb.is_some_and(|v| {
546 v.verb_forms.is_some_and(|vf| {
547 vf.contains(VerbFormFlags::PAST_PARTICIPLE)
548 && !vf.intersects(VerbFormFlags::PAST | VerbFormFlags::PRETERITE)
549 })
550 })
551 }
552
553 pub fn is_verb_progressive_form(&self) -> bool {
555 self.verb.is_some_and(|v| {
556 v.verb_forms
557 .is_some_and(|vf| vf.contains(VerbFormFlags::PROGRESSIVE))
558 })
559 }
560
561 pub fn is_verb_third_person_singular_present_form(&self) -> bool {
563 self.verb.is_some_and(|v| {
564 v.verb_forms
565 .is_some_and(|vf| vf.contains(VerbFormFlags::THIRD_PERSON_SINGULAR))
566 })
567 }
568
569 pub fn is_singular_noun(&self) -> bool {
575 if let Some(noun) = self.noun {
576 matches!(
577 (noun.is_singular, noun.is_plural),
578 (Some(true), _) | (None | Some(false), None | Some(false))
579 )
580 } else {
581 false
582 }
583 }
584
585 pub fn is_non_singular_noun(&self) -> bool {
589 if let Some(noun) = self.noun {
590 !matches!(
591 (noun.is_singular, noun.is_plural),
592 (Some(true), _) | (None | Some(false), None | Some(false))
593 )
594 } else {
595 false
596 }
597 }
598
599 pub fn is_countable_noun(&self) -> bool {
603 if let Some(noun) = self.noun {
604 matches!(
605 (noun.is_countable, noun.is_mass),
606 (Some(true), _) | (None | Some(false), None | Some(false))
607 )
608 } else {
609 false
610 }
611 }
612
613 pub fn is_non_countable_noun(&self) -> bool {
617 if let Some(noun) = self.noun {
618 !matches!(
619 (noun.is_countable, noun.is_mass),
620 (Some(true), _) | (None | Some(false), None | Some(false))
621 )
622 } else {
623 false
624 }
625 }
626
627 pub fn is_singular_noun_only(&self) -> bool {
632 if let Some(noun) = self.noun {
633 matches!(
634 (noun.is_singular, noun.is_plural),
635 (Some(true), None | Some(false))
636 )
637 } else {
638 false
639 }
640 }
641
642 pub fn is_plural_noun_only(&self) -> bool {
647 if let Some(noun) = self.noun {
648 matches!(
649 (noun.is_singular, noun.is_plural),
650 (None | Some(false), Some(true))
651 )
652 } else {
653 false
654 }
655 }
656
657 pub fn is_mass_noun_only(&self) -> bool {
660 if let Some(noun) = self.noun {
661 matches!(
662 (noun.is_countable, noun.is_mass),
663 (None | Some(false), Some(true))
664 )
665 } else {
666 false
667 }
668 }
669
670 pub fn is_nominal(&self) -> bool {
674 self.is_noun() || self.is_pronoun()
675 }
676
677 pub fn is_singular_nominal(&self) -> bool {
679 self.is_singular_noun() || self.is_singular_pronoun()
680 }
681
682 pub fn is_plural_nominal(&self) -> bool {
684 self.is_plural_noun() || self.is_plural_pronoun()
685 }
686
687 pub fn is_possessive_nominal(&self) -> bool {
692 self.is_possessive_noun() || self.is_possessive_determiner()
693 }
694
695 pub fn is_non_singular_nominal(&self) -> bool {
697 self.is_non_singular_noun() || self.is_non_singular_pronoun()
698 }
699
700 pub fn is_non_plural_nominal(&self) -> bool {
702 self.is_non_plural_noun() || self.is_non_plural_pronoun()
703 }
704
705 pub fn get_degree(&self) -> Option<Degree> {
708 self.adjective.as_ref().and_then(|a| a.degree)
709 }
710
711 pub fn is_comparative_adjective(&self) -> bool {
712 matches!(
713 self.adjective,
714 Some(AdjectiveData {
715 degree: Some(Degree::Comparative)
716 })
717 )
718 }
719
720 pub fn is_superlative_adjective(&self) -> bool {
721 matches!(
722 self.adjective,
723 Some(AdjectiveData {
724 degree: Some(Degree::Superlative)
725 })
726 )
727 }
728
729 pub fn is_positive_adjective(&self) -> bool {
731 match self.adjective {
732 Some(AdjectiveData {
733 degree: Some(Degree::Positive),
734 }) => true,
735 Some(AdjectiveData { degree: None }) => true,
736 Some(AdjectiveData {
737 degree: Some(degree),
738 }) => !matches!(degree, Degree::Comparative | Degree::Superlative),
739 _ => false,
740 }
741 }
742
743 pub fn is_quantifier(&self) -> bool {
747 self.is_quantifier_determiner()
748 }
749
750 pub fn is_swear(&self) -> bool {
754 matches!(self.swear, Some(true))
755 }
756
757 pub fn is_abbreviation(&self) -> bool {
759 matches!(self.abbreviation, Some(true))
760 }
761
762 pub fn is_lowercase(&self) -> bool {
770 self.orth_info.contains(OrthFlags::LOWERCASE)
771 }
772 pub fn is_titlecase(&self) -> bool {
784 self.orth_info.contains(OrthFlags::TITLECASE)
785 }
786 pub fn is_allcaps(&self) -> bool {
794 self.orth_info.contains(OrthFlags::ALLCAPS)
795 }
796 pub fn is_lower_camel(&self) -> bool {
808 self.orth_info.contains(OrthFlags::LOWER_CAMEL)
809 }
810 pub fn is_upper_camel(&self) -> bool {
827 self.orth_info.contains(OrthFlags::UPPER_CAMEL)
828 }
829
830 pub fn is_apostrophized(&self) -> bool {
832 self.orth_info.contains(OrthFlags::APOSTROPHE)
833 }
834
835 pub fn is_roman_numerals(&self) -> bool {
836 self.orth_info.contains(OrthFlags::ROMAN_NUMERALS)
837 }
838
839 pub fn merge(&mut self, other: &Self) -> &mut Self {
841 macro_rules! merge {
842 ($a:expr, $b:expr) => {
843 match ($a, $b) {
844 (Some(a), Some(b)) => Some(a.or(&b)),
845 (Some(a), None) => Some(a),
846 (None, Some(b)) => Some(b),
847 (None, None) => None,
848 }
849 };
850 }
851
852 self.noun = merge!(self.noun, other.noun);
853 self.pronoun = merge!(self.pronoun, other.pronoun);
854 self.verb = merge!(self.verb, other.verb);
855 self.adjective = merge!(self.adjective, other.adjective);
856 self.adverb = merge!(self.adverb, other.adverb);
857 self.conjunction = merge!(self.conjunction, other.conjunction);
858 self.determiner = merge!(self.determiner, other.determiner);
859 self.affix = merge!(self.affix, other.affix);
860 self.preposition |= other.preposition;
861 self.dialects |= other.dialects;
862 self.orth_info |= other.orth_info;
863 self.swear = self.swear.or(other.swear);
864 self.abbreviation = self.abbreviation.or(other.abbreviation);
865 self.common |= other.common;
866 self.derived_from = self.derived_from.or(other.derived_from);
867 self.pos_tag = self.pos_tag.or(other.pos_tag);
868 self.np_member = self.np_member.or(other.np_member);
869
870 self
871 }
872}
873
874#[repr(u32)]
890pub enum VerbForm {
891 LemmaForm = 1 << 0,
893 PastForm = 1 << 1,
895 SimplePastForm = 1 << 2,
897 PastParticipleForm = 1 << 3,
899 ProgressiveForm = 1 << 4,
901 ThirdPersonSingularPresentForm = 1 << 5,
903}
904
905pub type VerbFormFlagsUnderlyingType = u32;
907
908bitflags::bitflags! {
909 #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
913 #[serde(transparent)]
914 pub struct VerbFormFlags: VerbFormFlagsUnderlyingType {
915 const LEMMA = VerbForm::LemmaForm as VerbFormFlagsUnderlyingType;
916 const PAST = VerbForm::PastForm as VerbFormFlagsUnderlyingType;
917 const PRETERITE = VerbForm::SimplePastForm as VerbFormFlagsUnderlyingType;
918 const PAST_PARTICIPLE = VerbForm::PastParticipleForm as VerbFormFlagsUnderlyingType;
919 const PROGRESSIVE = VerbForm::ProgressiveForm as VerbFormFlagsUnderlyingType;
920 const THIRD_PERSON_SINGULAR = VerbForm::ThirdPersonSingularPresentForm as VerbFormFlagsUnderlyingType;
921 }
922}
923
924#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
925pub struct VerbData {
926 pub is_linking: Option<bool>,
927 pub is_auxiliary: Option<bool>,
928 #[serde(rename = "verb_form", default)]
929 pub verb_forms: Option<VerbFormFlags>,
930}
931
932impl VerbData {
933 pub fn or(&self, other: &Self) -> Self {
935 let verb_forms = match (self.verb_forms, other.verb_forms) {
936 (Some(self_verb_forms), Some(other_verb_forms)) => {
937 Some(self_verb_forms | other_verb_forms)
938 }
939 (Some(self_verb_forms), None) => Some(self_verb_forms),
940 (None, Some(other_verb_forms)) => Some(other_verb_forms),
941 (None, None) => None,
942 };
943
944 Self {
945 is_linking: self.is_linking.or(other.is_linking),
946 is_auxiliary: self.is_auxiliary.or(other.is_auxiliary),
947 verb_forms,
948 }
949 }
950}
951
952#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
955pub struct NounData {
956 pub is_proper: Option<bool>,
957 pub is_singular: Option<bool>,
958 pub is_plural: Option<bool>,
959 pub is_countable: Option<bool>,
960 pub is_mass: Option<bool>,
961 pub is_possessive: Option<bool>,
962}
963
964impl NounData {
965 pub fn or(&self, other: &Self) -> Self {
967 Self {
968 is_proper: self.is_proper.or(other.is_proper),
969 is_singular: self.is_singular.or(other.is_singular),
970 is_plural: self.is_plural.or(other.is_plural),
971 is_countable: self.is_countable.or(other.is_countable),
972 is_mass: self.is_mass.or(other.is_mass),
973 is_possessive: self.is_possessive.or(other.is_possessive),
974 }
975 }
976}
977
978#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Is, Hash)]
980pub enum Person {
981 First,
982 Second,
983 Third,
984}
985
986#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
988pub struct PronounData {
989 pub is_personal: Option<bool>,
990 pub is_singular: Option<bool>,
991 pub is_plural: Option<bool>,
992 pub is_possessive: Option<bool>,
993 pub is_reflexive: Option<bool>,
994 pub person: Option<Person>,
995 pub is_subject: Option<bool>,
996 pub is_object: Option<bool>,
997}
998
999impl PronounData {
1000 pub fn or(&self, other: &Self) -> Self {
1002 Self {
1003 is_personal: self.is_personal.or(other.is_personal),
1004 is_singular: self.is_singular.or(other.is_singular),
1005 is_plural: self.is_plural.or(other.is_plural),
1006 is_possessive: self.is_possessive.or(other.is_possessive),
1007 is_reflexive: self.is_reflexive.or(other.is_reflexive),
1008 person: self.person.or(other.person),
1009 is_subject: self.is_subject.or(other.is_subject),
1010 is_object: self.is_object.or(other.is_object),
1011 }
1012 }
1013}
1014
1015#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
1017pub struct DeterminerData {
1018 pub is_demonstrative: Option<bool>,
1019 pub is_possessive: Option<bool>,
1020 pub is_quantifier: Option<bool>,
1021}
1022
1023impl DeterminerData {
1024 pub fn or(&self, other: &Self) -> Self {
1026 Self {
1027 is_demonstrative: self.is_demonstrative.or(other.is_demonstrative),
1028 is_possessive: self.is_possessive.or(other.is_possessive),
1029 is_quantifier: self.is_quantifier.or(other.is_quantifier),
1030 }
1031 }
1032}
1033
1034#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Is, Hash)]
1038pub enum Degree {
1039 Positive,
1040 Comparative,
1041 Superlative,
1042}
1043
1044#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
1048pub struct AdjectiveData {
1049 pub degree: Option<Degree>,
1050}
1051
1052impl AdjectiveData {
1053 pub fn or(&self, other: &Self) -> Self {
1055 Self {
1056 degree: self.degree.or(other.degree),
1057 }
1058 }
1059}
1060
1061#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
1065pub struct AdverbData {
1066 pub is_manner: Option<bool>,
1067 pub is_frequency: Option<bool>,
1068 pub is_degree: Option<bool>,
1069}
1070
1071impl AdverbData {
1072 pub fn or(&self, _other: &Self) -> Self {
1074 Self {
1075 is_manner: self.is_manner.or(_other.is_manner),
1076 is_frequency: self.is_frequency.or(_other.is_frequency),
1077 is_degree: self.is_degree.or(_other.is_degree),
1078 }
1079 }
1080}
1081
1082#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
1083pub struct ConjunctionData {}
1084
1085impl ConjunctionData {
1086 pub fn or(&self, _other: &Self) -> Self {
1088 Self {}
1089 }
1090}
1091
1092#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
1093pub struct AffixData {
1094 pub is_prefix: Option<bool>,
1095 pub is_suffix: Option<bool>,
1096}
1097
1098impl AffixData {
1099 pub fn or(&self, _other: &Self) -> Self {
1101 Self {
1102 is_prefix: self.is_prefix.or(_other.is_prefix),
1103 is_suffix: self.is_suffix.or(_other.is_suffix),
1104 }
1105 }
1106}
1107
1108#[derive(
1114 Debug,
1115 Clone,
1116 Copy,
1117 Serialize,
1118 Deserialize,
1119 PartialEq,
1120 PartialOrd,
1121 Eq,
1122 Hash,
1123 EnumCount,
1124 EnumString,
1125 EnumIter,
1126 Display,
1127 VariantArray,
1128)]
1129pub enum Dialect {
1130 American = 1 << 0,
1131 Canadian = 1 << 1,
1132 Australian = 1 << 2,
1133 British = 1 << 3,
1134 Indian = 1 << 4,
1135}
1136impl Dialect {
1137 #[must_use]
1140 pub fn try_guess_from_document(document: &Document) -> Option<Self> {
1141 Self::try_from(DialectFlags::get_most_used_dialects_from_document(document)).ok()
1142 }
1143
1144 #[must_use]
1162 pub fn try_from_abbr(abbr: &str) -> Option<Self> {
1163 match abbr {
1164 "US" => Some(Self::American),
1165 "CA" => Some(Self::Canadian),
1166 "AU" => Some(Self::Australian),
1167 "GB" => Some(Self::British),
1168 "IN" => Some(Self::Indian),
1169 _ => None,
1170 }
1171 }
1172 pub fn try_from_bcp47(bcp47: &str) -> Option<Self> {
1174 bcp47.strip_prefix("en-").and_then(Self::try_from_abbr)
1175 }
1176}
1177impl TryFrom<DialectFlags> for Dialect {
1178 type Error = ();
1179
1180 fn try_from(dialect_flags: DialectFlags) -> Result<Self, Self::Error> {
1187 if dialect_flags.bits().count_ones() == 1 {
1189 match dialect_flags {
1190 df if df.is_dialect_enabled_strict(Dialect::American) => Ok(Dialect::American),
1191 df if df.is_dialect_enabled_strict(Dialect::Canadian) => Ok(Dialect::Canadian),
1192 df if df.is_dialect_enabled_strict(Dialect::Australian) => Ok(Dialect::Australian),
1193 df if df.is_dialect_enabled_strict(Dialect::British) => Ok(Dialect::British),
1194 df if df.is_dialect_enabled_strict(Dialect::Indian) => Ok(Dialect::Indian),
1195 _ => Err(()),
1196 }
1197 } else {
1198 Err(())
1200 }
1201 }
1202}
1203
1204type DialectFlagsUnderlyingType = u8;
1208
1209bitflags::bitflags! {
1210 #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash)]
1214 #[serde(transparent)]
1215 pub struct DialectFlags: DialectFlagsUnderlyingType {
1216 const AMERICAN = Dialect::American as DialectFlagsUnderlyingType;
1217 const CANADIAN = Dialect::Canadian as DialectFlagsUnderlyingType;
1218 const AUSTRALIAN = Dialect::Australian as DialectFlagsUnderlyingType;
1219 const BRITISH = Dialect::British as DialectFlagsUnderlyingType;
1220 const INDIAN = Dialect::Indian as DialectFlagsUnderlyingType;
1221 }
1222}
1223impl DialectFlags {
1224 #[must_use]
1227 pub fn is_dialect_enabled(self, dialect: Dialect) -> bool {
1228 self.is_empty() || self.intersects(Self::from_dialect(dialect))
1229 }
1230
1231 #[must_use]
1236 pub fn is_dialect_enabled_strict(self, dialect: Dialect) -> bool {
1237 self.intersects(Self::from_dialect(dialect))
1238 }
1239
1240 #[must_use]
1248 pub fn from_dialect(dialect: Dialect) -> Self {
1249 let Some(out) = Self::from_bits(dialect as DialectFlagsUnderlyingType) else {
1250 panic!("The '{dialect}' dialect isn't defined in DialectFlags!");
1251 };
1252 out
1253 }
1254
1255 #[must_use]
1261 pub fn get_most_used_dialects_from_document(document: &Document) -> Self {
1262 let mut dialect_counters: [(Dialect, usize); Dialect::COUNT] = Dialect::VARIANTS
1264 .iter()
1265 .map(|d| (*d, 0))
1266 .collect_array()
1267 .unwrap();
1268
1269 document.iter_words().for_each(|w| {
1271 if let TokenKind::Word(Some(lexeme_metadata)) = &w.kind {
1272 dialect_counters.iter_mut().for_each(|(dialect, count)| {
1275 if lexeme_metadata.dialects.is_dialect_enabled(*dialect) {
1276 *count += 1;
1277 }
1278 });
1279 }
1280 });
1281
1282 let max_counter = dialect_counters
1284 .iter()
1285 .map(|(_, count)| count)
1286 .max()
1287 .unwrap();
1288 dialect_counters
1290 .into_iter()
1291 .filter(|(_, count)| count == max_counter)
1292 .fold(DialectFlags::empty(), |acc, dialect| {
1293 acc | Self::from_dialect(dialect.0)
1295 })
1296 }
1297}
1298impl Default for DialectFlags {
1299 fn default() -> Self {
1302 Self::empty()
1303 }
1304}
1305
1306#[cfg(test)]
1307pub mod tests {
1308 use crate::DictWordMetadata;
1309 use crate::spell::{Dictionary, FstDictionary};
1310
1311 pub fn md(word: &str) -> DictWordMetadata {
1313 FstDictionary::curated()
1314 .get_word_metadata_str(word)
1315 .unwrap_or_else(|| panic!("Word '{word}' not found in dictionary"))
1316 .into_owned()
1317 }
1318
1319 mod dialect {
1320 use super::super::{Dialect, DialectFlags};
1321 use crate::Document;
1322
1323 #[test]
1324 fn guess_british_dialect() {
1325 let document = Document::new_plain_english_curated("Aluminium was used.");
1326 let df = DialectFlags::get_most_used_dialects_from_document(&document);
1327 assert!(
1328 df.is_dialect_enabled_strict(Dialect::British)
1329 && !df.is_dialect_enabled_strict(Dialect::American)
1330 );
1331 }
1332
1333 #[test]
1334 fn guess_american_dialect() {
1335 let document = Document::new_plain_english_curated("Aluminum was used.");
1336 let df = DialectFlags::get_most_used_dialects_from_document(&document);
1337 assert!(
1338 df.is_dialect_enabled_strict(Dialect::American)
1339 && !df.is_dialect_enabled_strict(Dialect::British)
1340 );
1341 }
1342 }
1343
1344 mod noun {
1345 use crate::dict_word_metadata::tests::md;
1346
1347 #[test]
1348 fn puppy_is_noun() {
1349 assert!(md("puppy").is_noun());
1350 }
1351
1352 #[test]
1353 fn prepare_is_not_noun() {
1354 assert!(!md("prepare").is_noun());
1355 }
1356
1357 #[test]
1358 fn paris_is_proper_noun() {
1359 assert!(md("Paris").is_proper_noun());
1360 }
1361
1362 #[test]
1363 fn permit_is_non_proper_noun() {
1364 assert!(md("lapdog").is_non_proper_noun());
1365 }
1366
1367 #[test]
1368 fn hound_is_singular_noun() {
1369 assert!(md("hound").is_singular_noun());
1370 }
1371
1372 #[test]
1373 fn pooches_is_non_singular_noun() {
1374 assert!(md("pooches").is_non_singular_noun());
1375 }
1376
1377 #[test]
1381 fn loyal_doesnt_pass_is_non_singular_noun() {
1382 assert!(!md("loyal").is_non_singular_noun());
1383 }
1384
1385 #[test]
1386 fn hounds_is_plural_noun() {
1387 assert!(md("hounds").is_plural_noun());
1388 }
1389
1390 #[test]
1391 fn pooch_is_non_plural_noun() {
1392 assert!(md("pooch").is_non_plural_noun());
1393 }
1394
1395 #[test]
1396 fn fish_is_singular_noun() {
1397 assert!(md("fish").is_singular_noun());
1398 }
1399
1400 #[test]
1401 fn fish_is_plural_noun() {
1402 assert!(md("fish").is_plural_noun());
1403 }
1404
1405 #[test]
1406 fn fishes_is_plural_noun() {
1407 assert!(md("fishes").is_plural_noun());
1408 }
1409
1410 #[test]
1411 fn sheep_is_singular_noun() {
1412 assert!(md("sheep").is_singular_noun());
1413 }
1414
1415 #[test]
1416 fn sheep_is_plural_noun() {
1417 assert!(md("sheep").is_plural_noun());
1418 }
1419
1420 #[test]
1421 #[should_panic]
1422 fn sheeps_is_not_word() {
1423 md("sheeps");
1424 }
1425
1426 #[test]
1427 fn bicep_is_singular_noun() {
1428 assert!(md("bicep").is_singular_noun());
1429 }
1430
1431 #[test]
1432 fn biceps_is_singular_noun() {
1433 assert!(md("biceps").is_singular_noun());
1434 }
1435
1436 #[test]
1437 fn biceps_is_plural_noun() {
1438 assert!(md("biceps").is_plural_noun());
1439 }
1440
1441 #[test]
1442 fn aircraft_is_singular_noun() {
1443 assert!(md("aircraft").is_singular_noun());
1444 }
1445
1446 #[test]
1447 fn aircraft_is_plural_noun() {
1448 assert!(md("aircraft").is_plural_noun());
1449 }
1450
1451 #[test]
1452 #[should_panic]
1453 fn aircrafts_is_not_word() {
1454 md("aircrafts");
1455 }
1456
1457 #[test]
1458 fn dog_apostrophe_s_is_possessive_noun() {
1459 assert!(md("dog's").is_possessive_noun());
1460 }
1461
1462 #[test]
1463 fn dogs_is_non_possessive_noun() {
1464 assert!(md("dogs").is_non_possessive_noun());
1465 }
1466
1467 #[test]
1470 fn dog_is_countable() {
1471 assert!(md("dog").is_countable_noun());
1472 }
1473 #[test]
1474 fn dog_is_non_mass_noun() {
1475 assert!(md("dog").is_non_mass_noun());
1476 }
1477
1478 #[test]
1479 fn furniture_is_mass_noun() {
1480 assert!(md("furniture").is_mass_noun());
1481 }
1482 #[test]
1483 fn furniture_is_non_countable_noun() {
1484 assert!(md("furniture").is_non_countable_noun());
1485 }
1486
1487 #[test]
1488 fn equipment_is_mass_noun() {
1489 assert!(md("equipment").is_mass_noun());
1490 }
1491 #[test]
1492 fn equipment_is_non_countable_noun() {
1493 assert!(md("equipment").is_non_countable_noun());
1494 }
1495
1496 #[test]
1497 fn beer_is_countable_noun() {
1498 assert!(md("beer").is_countable_noun());
1499 }
1500 #[test]
1501 fn beer_is_mass_noun() {
1502 assert!(md("beer").is_mass_noun());
1503 }
1504 }
1505
1506 mod pronoun {
1507 use crate::dict_word_metadata::tests::md;
1508
1509 mod i_me_myself {
1510 use crate::dict_word_metadata::tests::md;
1511
1512 #[test]
1513 fn i_is_pronoun() {
1514 assert!(md("I").is_pronoun());
1515 }
1516 #[test]
1517 fn i_is_personal_pronoun() {
1518 assert!(md("I").is_personal_pronoun());
1519 }
1520 #[test]
1521 fn i_is_singular_pronoun() {
1522 assert!(md("I").is_singular_pronoun());
1523 }
1524 #[test]
1525 fn i_is_subject_pronoun() {
1526 assert!(md("I").is_subject_pronoun());
1527 }
1528
1529 #[test]
1530 fn me_is_pronoun() {
1531 assert!(md("me").is_pronoun());
1532 }
1533 #[test]
1534 fn me_is_personal_pronoun() {
1535 assert!(md("me").is_personal_pronoun());
1536 }
1537 #[test]
1538 fn me_is_singular_pronoun() {
1539 assert!(md("me").is_singular_pronoun());
1540 }
1541 #[test]
1542 fn me_is_object_pronoun() {
1543 assert!(md("me").is_object_pronoun());
1544 }
1545
1546 #[test]
1547 fn myself_is_pronoun() {
1548 assert!(md("myself").is_pronoun());
1549 }
1550 #[test]
1551 fn myself_is_personal_pronoun() {
1552 assert!(md("myself").is_personal_pronoun());
1553 }
1554 #[test]
1555 fn myself_is_singular_pronoun() {
1556 assert!(md("myself").is_singular_pronoun());
1557 }
1558 #[test]
1559 fn myself_is_reflexive_pronoun() {
1560 assert!(md("myself").is_reflexive_pronoun());
1561 }
1562 }
1563
1564 mod we_us_ourselves {
1565 use crate::dict_word_metadata::tests::md;
1566
1567 #[test]
1568 fn we_is_pronoun() {
1569 assert!(md("we").is_pronoun());
1570 }
1571 #[test]
1572 fn we_is_personal_pronoun() {
1573 assert!(md("we").is_personal_pronoun());
1574 }
1575 #[test]
1576 fn we_is_plural_pronoun() {
1577 assert!(md("we").is_plural_pronoun());
1578 }
1579 #[test]
1580 fn we_is_subject_pronoun() {
1581 assert!(md("we").is_subject_pronoun());
1582 }
1583
1584 #[test]
1585 fn us_is_pronoun() {
1586 assert!(md("us").is_pronoun());
1587 }
1588 #[test]
1589 fn us_is_personal_pronoun() {
1590 assert!(md("us").is_personal_pronoun());
1591 }
1592 #[test]
1593 fn us_is_plural_pronoun() {
1594 assert!(md("us").is_plural_pronoun());
1595 }
1596 #[test]
1597 fn us_is_object_pronoun() {
1598 assert!(md("us").is_object_pronoun());
1599 }
1600
1601 #[test]
1602 fn ourselves_is_pronoun() {
1603 assert!(md("ourselves").is_pronoun());
1604 }
1605 #[test]
1606 fn ourselves_is_personal_pronoun() {
1607 assert!(md("ourselves").is_personal_pronoun());
1608 }
1609 #[test]
1610 fn ourselves_is_plural_pronoun() {
1611 assert!(md("ourselves").is_plural_pronoun());
1612 }
1613 #[test]
1614 fn ourselves_is_reflexive_pronoun() {
1615 assert!(md("ourselves").is_reflexive_pronoun());
1616 }
1617 }
1618
1619 mod you_yourself {
1620 use crate::dict_word_metadata::tests::md;
1621
1622 #[test]
1623 fn you_is_pronoun() {
1624 assert!(md("you").is_pronoun());
1625 }
1626 #[test]
1627 fn you_is_personal_pronoun() {
1628 assert!(md("you").is_personal_pronoun());
1629 }
1630 #[test]
1631 fn you_is_singular_pronoun() {
1632 assert!(md("you").is_singular_pronoun());
1633 }
1634 #[test]
1635 fn you_is_plural_pronoun() {
1636 assert!(md("you").is_plural_pronoun());
1637 }
1638 #[test]
1639 fn you_is_subject_pronoun() {
1640 assert!(md("you").is_subject_pronoun());
1641 }
1642 #[test]
1643 fn you_is_object_pronoun() {
1644 assert!(md("you").is_object_pronoun());
1645 }
1646 #[test]
1647 fn yourself_is_pronoun() {
1648 assert!(md("yourself").is_pronoun());
1649 }
1650 #[test]
1651 fn yourself_is_personal_pronoun() {
1652 assert!(md("yourself").is_personal_pronoun());
1653 }
1654 #[test]
1655 fn yourself_is_singular_pronoun() {
1656 assert!(md("yourself").is_singular_pronoun());
1657 }
1658 #[test]
1659 fn yourself_is_reflexive_pronoun() {
1660 assert!(md("yourself").is_reflexive_pronoun());
1661 }
1662 }
1663
1664 mod he_him_himself {
1665 use crate::dict_word_metadata::tests::md;
1666
1667 #[test]
1668 fn he_is_pronoun() {
1669 assert!(md("he").is_pronoun());
1670 }
1671 #[test]
1672 fn he_is_personal_pronoun() {
1673 assert!(md("he").is_personal_pronoun());
1674 }
1675 #[test]
1676 fn he_is_singular_pronoun() {
1677 assert!(md("he").is_singular_pronoun());
1678 }
1679 #[test]
1680 fn he_is_subject_pronoun() {
1681 assert!(md("he").is_subject_pronoun());
1682 }
1683
1684 #[test]
1685 fn him_is_pronoun() {
1686 assert!(md("him").is_pronoun());
1687 }
1688 #[test]
1689 fn him_is_personal_pronoun() {
1690 assert!(md("him").is_personal_pronoun());
1691 }
1692 #[test]
1693 fn him_is_singular_pronoun() {
1694 assert!(md("him").is_singular_pronoun());
1695 }
1696 #[test]
1697 fn him_is_object_pronoun() {
1698 assert!(md("him").is_object_pronoun());
1699 }
1700
1701 #[test]
1702 fn himself_is_pronoun() {
1703 assert!(md("himself").is_pronoun());
1704 }
1705 #[test]
1706 fn himself_is_personal_pronoun() {
1707 assert!(md("himself").is_personal_pronoun());
1708 }
1709 #[test]
1710 fn himself_is_singular_pronoun() {
1711 assert!(md("himself").is_singular_pronoun());
1712 }
1713 #[test]
1714 fn himself_is_reflexive_pronoun() {
1715 assert!(md("himself").is_reflexive_pronoun());
1716 }
1717 }
1718
1719 mod she_her_herself {
1720 use crate::dict_word_metadata::tests::md;
1721
1722 #[test]
1723 fn she_is_pronoun() {
1724 assert!(md("she").is_pronoun());
1725 }
1726 #[test]
1727 fn she_is_personal_pronoun() {
1728 assert!(md("she").is_personal_pronoun());
1729 }
1730 #[test]
1731 fn she_is_singular_pronoun() {
1732 assert!(md("she").is_singular_pronoun());
1733 }
1734 #[test]
1735 fn she_is_subject_pronoun() {
1736 assert!(md("she").is_subject_pronoun());
1737 }
1738
1739 #[test]
1740 fn her_is_pronoun() {
1741 assert!(md("her").is_pronoun());
1742 }
1743 #[test]
1744 fn her_is_personal_pronoun() {
1745 assert!(md("her").is_personal_pronoun());
1746 }
1747 #[test]
1748 fn her_is_singular_pronoun() {
1749 assert!(md("her").is_singular_pronoun());
1750 }
1751 #[test]
1752 fn her_is_object_pronoun() {
1753 assert!(md("her").is_object_pronoun());
1754 }
1755
1756 #[test]
1757 fn herself_is_pronoun() {
1758 assert!(md("herself").is_pronoun());
1759 }
1760 #[test]
1761 fn herself_is_personal_pronoun() {
1762 assert!(md("herself").is_personal_pronoun());
1763 }
1764 #[test]
1765 fn herself_is_singular_pronoun() {
1766 assert!(md("herself").is_singular_pronoun());
1767 }
1768 #[test]
1769 fn herself_is_reflexive_pronoun() {
1770 assert!(md("herself").is_reflexive_pronoun());
1771 }
1772 }
1773
1774 mod it_itself {
1775 use crate::dict_word_metadata::tests::md;
1776
1777 #[test]
1778 fn it_is_pronoun() {
1779 assert!(md("it").is_pronoun());
1780 }
1781 #[test]
1782 fn it_is_personal_pronoun() {
1783 assert!(md("it").is_personal_pronoun());
1784 }
1785 #[test]
1786 fn it_is_singular_pronoun() {
1787 assert!(md("it").is_singular_pronoun());
1788 }
1789 #[test]
1790 fn it_is_subject_pronoun() {
1791 assert!(md("it").is_subject_pronoun());
1792 }
1793 #[test]
1794 fn it_is_object_pronoun() {
1795 assert!(md("it").is_object_pronoun());
1796 }
1797
1798 #[test]
1799 fn itself_is_pronoun() {
1800 assert!(md("itself").is_pronoun());
1801 }
1802 #[test]
1803 fn itself_is_personal_pronoun() {
1804 assert!(md("itself").is_personal_pronoun());
1805 }
1806 #[test]
1807 fn itself_is_singular_pronoun() {
1808 assert!(md("itself").is_singular_pronoun());
1809 }
1810 #[test]
1811 fn itself_is_reflexive_pronoun() {
1812 assert!(md("itself").is_reflexive_pronoun());
1813 }
1814 }
1815
1816 mod they_them_themselves {
1817 use crate::dict_word_metadata::tests::md;
1818
1819 #[test]
1820 fn they_is_pronoun() {
1821 assert!(md("they").is_pronoun());
1822 }
1823 #[test]
1824 fn they_is_personal_pronoun() {
1825 assert!(md("they").is_personal_pronoun());
1826 }
1827 #[test]
1828 fn they_is_plural_pronoun() {
1829 assert!(md("they").is_plural_pronoun());
1830 }
1831 #[test]
1832 fn they_is_subject_pronoun() {
1833 assert!(md("they").is_subject_pronoun());
1834 }
1835
1836 #[test]
1837 fn them_is_pronoun() {
1838 assert!(md("them").is_pronoun());
1839 }
1840 #[test]
1841 fn them_is_personal_pronoun() {
1842 assert!(md("them").is_personal_pronoun());
1843 }
1844 #[test]
1845 fn them_is_plural_pronoun() {
1846 assert!(md("them").is_plural_pronoun());
1847 }
1848 #[test]
1849 fn them_is_object_pronoun() {
1850 assert!(md("them").is_object_pronoun());
1851 }
1852
1853 #[test]
1854 fn themselves_is_pronoun() {
1855 assert!(md("themselves").is_pronoun());
1856 }
1857 #[test]
1858 fn themselves_is_personal_pronoun() {
1859 assert!(md("themselves").is_personal_pronoun());
1860 }
1861 #[test]
1862 fn themselves_is_plural_pronoun() {
1863 assert!(md("themselves").is_plural_pronoun());
1864 }
1865 #[test]
1866 fn themselves_is_reflexive_pronoun() {
1867 assert!(md("themselves").is_reflexive_pronoun());
1868 }
1869 }
1870
1871 #[test]
1873 fn mine_is_pronoun() {
1874 assert!(md("mine").is_pronoun());
1875 }
1876 #[test]
1877 fn ours_is_pronoun() {
1878 assert!(md("ours").is_pronoun());
1879 }
1880 #[test]
1881 fn yours_is_pronoun() {
1882 assert!(md("yours").is_pronoun());
1883 }
1884 #[test]
1885 fn his_is_pronoun() {
1886 assert!(md("his").is_pronoun());
1887 }
1888 #[test]
1889 fn hers_is_pronoun() {
1890 assert!(md("hers").is_pronoun());
1891 }
1892 #[test]
1893 fn its_is_pronoun() {
1894 assert!(md("its").is_pronoun());
1895 }
1896 #[test]
1897 fn theirs_is_pronoun() {
1898 assert!(md("theirs").is_pronoun());
1899 }
1900
1901 #[test]
1903 fn archaic_pronouns() {
1904 assert!(md("thou").is_pronoun());
1905 assert!(md("thee").is_pronoun());
1906 assert!(md("thyself").is_pronoun());
1907 assert!(md("thine").is_pronoun());
1908 }
1909
1910 #[test]
1912 fn generic_pronouns() {
1913 assert!(md("one").is_pronoun());
1914 assert!(md("oneself").is_pronoun());
1915 }
1916
1917 #[test]
1919 fn relative_and_interrogative_pronouns() {
1920 assert!(md("who").is_pronoun());
1921 assert!(md("whom").is_pronoun());
1922 assert!(md("whose").is_pronoun());
1923 assert!(md("which").is_pronoun());
1924 assert!(md("what").is_pronoun());
1925 }
1926
1927 #[test]
1929 #[ignore = "not in dictionary"]
1930 fn nonstandard_pronouns() {
1931 assert!(md("themself").pronoun.is_some());
1932 assert!(md("y'all'").pronoun.is_some());
1933 }
1934 }
1935
1936 mod nominal {
1937 use crate::dict_word_metadata::tests::md;
1938
1939 #[test]
1940 fn my_is_possessive_nominal() {
1941 assert!(md("my").is_possessive_nominal());
1942 }
1943
1944 #[test]
1945 fn mine_is_not_possessive_nominal() {
1946 assert!(!md("mine").is_possessive_nominal());
1947 }
1948
1949 #[test]
1950 fn freds_is_possessive_nominal() {
1951 assert!(md("Fred's").is_possessive_nominal());
1952 }
1953
1954 #[test]
1955 fn fred_is_not_possessive_nominal() {
1956 assert!(!md("Fred").is_possessive_nominal());
1957 }
1958
1959 #[test]
1960 fn dogs_is_possessive_nominal() {
1961 assert!(md("dog's").is_possessive_nominal());
1962 }
1963
1964 #[test]
1965 fn microsofts_is_possessive_nominal() {
1966 assert!(md("Microsoft's").is_possessive_nominal());
1967 }
1968 }
1969
1970 mod adjective {
1971 use crate::{Degree, dict_word_metadata::tests::md};
1972
1973 #[test]
1976 #[ignore = "not marked yet because it might not be reliable"]
1977 fn big_is_positive() {
1978 assert_eq!(md("big").get_degree(), Some(Degree::Positive));
1979 }
1980
1981 #[test]
1982 fn bigger_is_comparative() {
1983 assert_eq!(md("bigger").get_degree(), Some(Degree::Comparative));
1984 }
1985
1986 #[test]
1987 fn biggest_is_superlative() {
1988 assert_eq!(md("biggest").get_degree(), Some(Degree::Superlative));
1989 }
1990
1991 #[test]
1992 #[should_panic(expected = "Word 'bigly' not found in dictionary")]
1993 fn bigly_is_not_an_adjective_form_we_track() {
1994 assert_eq!(md("bigly").get_degree(), None);
1995 }
1996
1997 #[test]
2002 fn bigger_is_comparative_adjective() {
2003 assert!(md("bigger").is_comparative_adjective());
2004 }
2005
2006 #[test]
2007 fn biggest_is_superlative_adjective() {
2008 assert!(md("biggest").is_superlative_adjective());
2009 }
2010 }
2011
2012 #[test]
2013 fn the_is_determiner() {
2014 assert!(md("the").is_determiner());
2015 }
2016 #[test]
2017 fn this_is_demonstrative_determiner() {
2018 assert!(md("this").is_demonstrative_determiner());
2019 }
2020 #[test]
2021 fn your_is_possessive_determiner() {
2022 assert!(md("your").is_possessive_determiner());
2023 }
2024
2025 #[test]
2026 fn every_is_quantifier() {
2027 assert!(md("every").is_quantifier());
2028 }
2029
2030 #[test]
2031 fn the_isnt_quantifier() {
2032 assert!(!md("the").is_quantifier());
2033 }
2034
2035 #[test]
2036 fn equipment_is_mass_noun() {
2037 assert!(md("equipment").is_mass_noun());
2038 }
2039
2040 #[test]
2041 fn equipment_is_non_countable_noun() {
2042 assert!(md("equipment").is_non_countable_noun());
2043 }
2044
2045 #[test]
2046 fn equipment_isnt_countable_noun() {
2047 assert!(!md("equipment").is_countable_noun());
2048 }
2049
2050 #[test]
2051 fn infrastructure_is_mass_noun_only() {
2052 assert!(md("infrastructure").is_mass_noun_only());
2053 }
2054
2055 #[test]
2056 fn beer_is_not_mass_noun_only() {
2057 assert!(!md("beer").is_mass_noun_only());
2058 }
2059
2060 #[test]
2061 fn sheep_is_not_singular_only() {
2062 assert!(!md("sheep").is_singular_noun_only());
2063 }
2064
2065 #[test]
2066 fn sheep_is_not_plural_only() {
2067 assert!(!md("sheep").is_plural_noun_only());
2068 }
2069
2070 #[test]
2071 fn ox_is_singular_only() {
2072 assert!(md("ox").is_singular_noun_only());
2073 }
2074
2075 #[test]
2076 fn oxen_is_plural_only() {
2077 assert!(md("oxen").is_plural_noun_only());
2078 }
2079
2080 mod verb {
2081 use crate::dict_word_metadata::tests::md;
2082
2083 #[test]
2084 fn lemma_walk() {
2085 let md = md("walk");
2086 assert!(md.is_verb_lemma())
2087 }
2088
2089 #[test]
2090 fn lemma_fix() {
2091 let md = md("fix");
2092 assert!(md.is_verb_lemma())
2093 }
2094
2095 #[test]
2096 fn progressive_walking() {
2097 let md = md("walking");
2098 assert!(md.is_verb_progressive_form())
2099 }
2100
2101 #[test]
2102 fn past_walked() {
2103 let md = md("walked");
2104 assert!(md.is_verb_past_form())
2105 }
2106
2107 #[test]
2108 fn regular_past_thought() {
2109 let md = md("thought");
2110 assert!(md.is_verb_preterite_and_participle_form())
2111 }
2112
2113 #[test]
2114 fn simple_past_ate() {
2115 let md = md("ate");
2116 assert!(md.is_verb_simple_past_form())
2117 }
2118
2119 #[test]
2120 fn past_participle_eaten() {
2121 let md = md("eaten");
2122 assert!(md.is_verb_past_participle_form())
2123 }
2124
2125 #[test]
2126 fn ate_is_simple_past_only() {
2127 let md = md("ate");
2128 assert!(md.is_verb_simple_past_only());
2129 assert!(!md.is_verb_past_participle_only());
2130 }
2131
2132 #[test]
2133 fn eaten_is_past_participle_only() {
2134 let md = md("eaten");
2135 assert!(md.is_verb_past_participle_only());
2136 assert!(!md.is_verb_simple_past_only());
2137 }
2138
2139 #[test]
2140 fn thought_is_neither_past_form_only() {
2141 let md = md("thought");
2142 assert!(!md.is_verb_simple_past_only());
2143 assert!(!md.is_verb_past_participle_only());
2144 }
2145
2146 #[test]
2147 fn shared_past_forms_are_neither_past_form_only() {
2148 let md = md("thought");
2149 assert!(!md.is_verb_simple_past_only());
2150 assert!(!md.is_verb_past_participle_only());
2151 assert!(md.is_verb_preterite_and_participle_form());
2152 }
2153
2154 #[test]
2155 fn distinct_past_forms_are_not_regular_past() {
2156 assert!(!md("ate").is_verb_preterite_and_participle_form());
2157 assert!(!md("eaten").is_verb_preterite_and_participle_form());
2158 assert!(!md("walked").is_verb_preterite_and_participle_form());
2159 }
2160
2161 #[test]
2162 fn third_pers_sing_walks() {
2163 let md = md("walks");
2164 assert!(md.is_verb_third_person_singular_present_form())
2165 }
2166 }
2167}