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!(
384 noun has proper, plural, mass, possessive.
386 pronoun has personal, singular, plural, possessive, reflexive, subject, object.
387 determiner has demonstrative, possessive, quantifier.
388 verb has linking, auxiliary.
389 conjunction has.
390 adjective has.
391 adverb has manner, frequency, degree
392 );
393
394 pub fn get_person(&self) -> Option<Person> {
399 self.pronoun.as_ref().and_then(|p| p.person)
400 }
401
402 pub fn is_first_person_plural_pronoun(&self) -> bool {
403 matches!(
404 self.pronoun,
405 Some(PronounData {
406 person: Some(Person::First),
407 is_plural: Some(true),
408 ..
409 })
410 )
411 }
412
413 pub fn is_first_person_singular_pronoun(&self) -> bool {
414 matches!(
415 self.pronoun,
416 Some(PronounData {
417 person: Some(Person::First),
418 is_singular: Some(true),
419 ..
420 })
421 )
422 }
423
424 pub fn is_third_person_plural_pronoun(&self) -> bool {
425 matches!(
426 self.pronoun,
427 Some(PronounData {
428 person: Some(Person::Third),
429 is_plural: Some(true),
430 ..
431 })
432 )
433 }
434
435 pub fn is_third_person_singular_pronoun(&self) -> bool {
436 matches!(
437 self.pronoun,
438 Some(PronounData {
439 person: Some(Person::Third),
440 is_singular: Some(true),
441 ..
442 })
443 )
444 }
445
446 pub fn is_third_person_pronoun(&self) -> bool {
447 matches!(
448 self.pronoun,
449 Some(PronounData {
450 person: Some(Person::Third),
451 ..
452 })
453 )
454 }
455
456 pub fn is_second_person_pronoun(&self) -> bool {
457 matches!(
458 self.pronoun,
459 Some(PronounData {
460 person: Some(Person::Second),
461 ..
462 })
463 )
464 }
465
466 pub fn is_verb_lemma(&self) -> bool {
468 if let Some(verb) = self.verb {
469 if let Some(forms) = verb.verb_forms {
470 return forms.is_empty() || forms.contains(VerbFormFlags::LEMMA);
471 } else {
472 return true;
473 }
474 }
475 false
476 }
477
478 pub fn is_verb_past_form(&self) -> bool {
479 self.verb.is_some_and(|v| {
480 v.verb_forms
481 .is_some_and(|vf| vf.contains(VerbFormFlags::PAST))
482 })
483 }
484
485 pub fn is_verb_regular_past_form(&self) -> bool {
486 self.verb.is_some_and(|v| {
487 v.verb_forms.is_some_and(|vf| {
488 vf.contains(VerbFormFlags::PRETERITE) && vf.contains(VerbFormFlags::PAST_PARTICIPLE)
489 })
490 })
491 }
492
493 pub fn is_verb_simple_past_form(&self) -> bool {
494 self.verb.is_some_and(|v| {
495 v.verb_forms
496 .is_some_and(|vf| vf.contains(VerbFormFlags::PRETERITE))
497 })
498 }
499
500 pub fn is_verb_past_participle_form(&self) -> bool {
501 self.verb.is_some_and(|v| {
502 v.verb_forms
503 .is_some_and(|vf| vf.contains(VerbFormFlags::PAST_PARTICIPLE))
504 })
505 }
506
507 pub fn is_verb_simple_past_only(&self) -> bool {
508 self.verb.is_some_and(|v| {
509 v.verb_forms.is_some_and(|vf| {
510 vf.contains(VerbFormFlags::PRETERITE)
511 && !vf.intersects(VerbFormFlags::PAST | VerbFormFlags::PAST_PARTICIPLE)
512 })
513 })
514 }
515
516 pub fn is_verb_past_participle_only(&self) -> bool {
517 self.verb.is_some_and(|v| {
518 v.verb_forms.is_some_and(|vf| {
519 vf.contains(VerbFormFlags::PAST_PARTICIPLE)
520 && !vf.intersects(VerbFormFlags::PAST | VerbFormFlags::PRETERITE)
521 })
522 })
523 }
524
525 pub fn is_verb_progressive_form(&self) -> bool {
526 self.verb.is_some_and(|v| {
527 v.verb_forms
528 .is_some_and(|vf| vf.contains(VerbFormFlags::PROGRESSIVE))
529 })
530 }
531
532 pub fn is_verb_third_person_singular_present_form(&self) -> bool {
533 self.verb.is_some_and(|v| {
534 v.verb_forms
535 .is_some_and(|vf| vf.contains(VerbFormFlags::THIRD_PERSON_SINGULAR))
536 })
537 }
538
539 pub fn is_singular_noun(&self) -> bool {
543 if let Some(noun) = self.noun {
544 matches!(
545 (noun.is_singular, noun.is_plural),
546 (Some(true), _) | (None | Some(false), None | Some(false))
547 )
548 } else {
549 false
550 }
551 }
552 pub fn is_non_singular_noun(&self) -> bool {
553 if let Some(noun) = self.noun {
554 !matches!(
555 (noun.is_singular, noun.is_plural),
556 (Some(true), _) | (None | Some(false), None | Some(false))
557 )
558 } else {
559 false
560 }
561 }
562
563 pub fn is_countable_noun(&self) -> bool {
565 if let Some(noun) = self.noun {
566 matches!(
567 (noun.is_countable, noun.is_mass),
568 (Some(true), _) | (None | Some(false), None | Some(false))
569 )
570 } else {
571 false
572 }
573 }
574 pub fn is_non_countable_noun(&self) -> bool {
575 if let Some(noun) = self.noun {
576 !matches!(
577 (noun.is_countable, noun.is_mass),
578 (Some(true), _) | (None | Some(false), None | Some(false))
579 )
580 } else {
581 false
582 }
583 }
584
585 pub fn is_singular_noun_only(&self) -> bool {
586 if let Some(noun) = self.noun {
587 matches!(
588 (noun.is_singular, noun.is_plural),
589 (Some(true), None | Some(false))
590 )
591 } else {
592 false
593 }
594 }
595
596 pub fn is_plural_noun_only(&self) -> bool {
597 if let Some(noun) = self.noun {
598 matches!(
599 (noun.is_singular, noun.is_plural),
600 (None | Some(false), Some(true))
601 )
602 } else {
603 false
604 }
605 }
606
607 pub fn is_mass_noun_only(&self) -> bool {
609 if let Some(noun) = self.noun {
610 matches!(
611 (noun.is_countable, noun.is_mass),
612 (None | Some(false), Some(true))
613 )
614 } else {
615 false
616 }
617 }
618
619 pub fn is_nominal(&self) -> bool {
623 self.is_noun() || self.is_pronoun()
624 }
625
626 pub fn is_singular_nominal(&self) -> bool {
628 self.is_singular_noun() || self.is_singular_pronoun()
629 }
630
631 pub fn is_plural_nominal(&self) -> bool {
633 self.is_plural_noun() || self.is_plural_pronoun()
634 }
635
636 pub fn is_possessive_nominal(&self) -> bool {
641 self.is_possessive_noun() || self.is_possessive_determiner()
642 }
643
644 pub fn is_non_singular_nominal(&self) -> bool {
646 self.is_non_singular_noun() || self.is_non_singular_pronoun()
647 }
648
649 pub fn is_non_plural_nominal(&self) -> bool {
651 self.is_non_plural_noun() || self.is_non_plural_pronoun()
652 }
653
654 pub fn get_degree(&self) -> Option<Degree> {
657 self.adjective.as_ref().and_then(|a| a.degree)
658 }
659
660 pub fn is_comparative_adjective(&self) -> bool {
661 matches!(
662 self.adjective,
663 Some(AdjectiveData {
664 degree: Some(Degree::Comparative)
665 })
666 )
667 }
668
669 pub fn is_superlative_adjective(&self) -> bool {
670 matches!(
671 self.adjective,
672 Some(AdjectiveData {
673 degree: Some(Degree::Superlative)
674 })
675 )
676 }
677
678 pub fn is_positive_adjective(&self) -> bool {
680 match self.adjective {
681 Some(AdjectiveData {
682 degree: Some(Degree::Positive),
683 }) => true,
684 Some(AdjectiveData { degree: None }) => true,
685 Some(AdjectiveData {
686 degree: Some(degree),
687 }) => !matches!(degree, Degree::Comparative | Degree::Superlative),
688 _ => false,
689 }
690 }
691
692 pub fn is_quantifier(&self) -> bool {
696 self.is_quantifier_determiner()
697 }
698
699 pub fn is_swear(&self) -> bool {
703 matches!(self.swear, Some(true))
704 }
705
706 pub fn is_abbreviation(&self) -> bool {
708 matches!(self.abbreviation, Some(true))
709 }
710
711 pub fn is_lowercase(&self) -> bool {
719 self.orth_info.contains(OrthFlags::LOWERCASE)
720 }
721 pub fn is_titlecase(&self) -> bool {
733 self.orth_info.contains(OrthFlags::TITLECASE)
734 }
735 pub fn is_allcaps(&self) -> bool {
743 self.orth_info.contains(OrthFlags::ALLCAPS)
744 }
745 pub fn is_lower_camel(&self) -> bool {
757 self.orth_info.contains(OrthFlags::LOWER_CAMEL)
758 }
759 pub fn is_upper_camel(&self) -> bool {
776 self.orth_info.contains(OrthFlags::UPPER_CAMEL)
777 }
778
779 pub fn is_apostrophized(&self) -> bool {
781 self.orth_info.contains(OrthFlags::APOSTROPHE)
782 }
783
784 pub fn is_roman_numerals(&self) -> bool {
785 self.orth_info.contains(OrthFlags::ROMAN_NUMERALS)
786 }
787
788 pub fn merge(&mut self, other: &Self) -> &mut Self {
790 macro_rules! merge {
791 ($a:expr, $b:expr) => {
792 match ($a, $b) {
793 (Some(a), Some(b)) => Some(a.or(&b)),
794 (Some(a), None) => Some(a),
795 (None, Some(b)) => Some(b),
796 (None, None) => None,
797 }
798 };
799 }
800
801 self.noun = merge!(self.noun, other.noun);
802 self.pronoun = merge!(self.pronoun, other.pronoun);
803 self.verb = merge!(self.verb, other.verb);
804 self.adjective = merge!(self.adjective, other.adjective);
805 self.adverb = merge!(self.adverb, other.adverb);
806 self.conjunction = merge!(self.conjunction, other.conjunction);
807 self.determiner = merge!(self.determiner, other.determiner);
808 self.affix = merge!(self.affix, other.affix);
809 self.preposition |= other.preposition;
810 self.dialects |= other.dialects;
811 self.orth_info |= other.orth_info;
812 self.swear = self.swear.or(other.swear);
813 self.abbreviation = self.abbreviation.or(other.abbreviation);
814 self.common |= other.common;
815 self.derived_from = self.derived_from.or(other.derived_from);
816 self.pos_tag = self.pos_tag.or(other.pos_tag);
817 self.np_member = self.np_member.or(other.np_member);
818
819 self
820 }
821}
822
823#[repr(u32)]
839pub enum VerbForm {
840 LemmaForm = 1 << 0,
842 PastForm = 1 << 1,
844 SimplePastForm = 1 << 2,
846 PastParticipleForm = 1 << 3,
848 ProgressiveForm = 1 << 4,
850 ThirdPersonSingularPresentForm = 1 << 5,
852}
853
854pub type VerbFormFlagsUnderlyingType = u32;
856
857bitflags::bitflags! {
858 #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
862 #[serde(transparent)]
863 pub struct VerbFormFlags: VerbFormFlagsUnderlyingType {
864 const LEMMA = VerbForm::LemmaForm as VerbFormFlagsUnderlyingType;
865 const PAST = VerbForm::PastForm as VerbFormFlagsUnderlyingType;
866 const PRETERITE = VerbForm::SimplePastForm as VerbFormFlagsUnderlyingType;
867 const PAST_PARTICIPLE = VerbForm::PastParticipleForm as VerbFormFlagsUnderlyingType;
868 const PROGRESSIVE = VerbForm::ProgressiveForm as VerbFormFlagsUnderlyingType;
869 const THIRD_PERSON_SINGULAR = VerbForm::ThirdPersonSingularPresentForm as VerbFormFlagsUnderlyingType;
870 }
871}
872
873#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
874pub struct VerbData {
875 pub is_linking: Option<bool>,
876 pub is_auxiliary: Option<bool>,
877 #[serde(rename = "verb_form", default)]
878 pub verb_forms: Option<VerbFormFlags>,
879}
880
881impl VerbData {
882 pub fn or(&self, other: &Self) -> Self {
884 let verb_forms = match (self.verb_forms, other.verb_forms) {
885 (Some(self_verb_forms), Some(other_verb_forms)) => {
886 Some(self_verb_forms | other_verb_forms)
887 }
888 (Some(self_verb_forms), None) => Some(self_verb_forms),
889 (None, Some(other_verb_forms)) => Some(other_verb_forms),
890 (None, None) => None,
891 };
892
893 Self {
894 is_linking: self.is_linking.or(other.is_linking),
895 is_auxiliary: self.is_auxiliary.or(other.is_auxiliary),
896 verb_forms,
897 }
898 }
899}
900
901#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
904pub struct NounData {
905 pub is_proper: Option<bool>,
906 pub is_singular: Option<bool>,
907 pub is_plural: Option<bool>,
908 pub is_countable: Option<bool>,
909 pub is_mass: Option<bool>,
910 pub is_possessive: Option<bool>,
911}
912
913impl NounData {
914 pub fn or(&self, other: &Self) -> Self {
916 Self {
917 is_proper: self.is_proper.or(other.is_proper),
918 is_singular: self.is_singular.or(other.is_singular),
919 is_plural: self.is_plural.or(other.is_plural),
920 is_countable: self.is_countable.or(other.is_countable),
921 is_mass: self.is_mass.or(other.is_mass),
922 is_possessive: self.is_possessive.or(other.is_possessive),
923 }
924 }
925}
926
927#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Is, Hash)]
929pub enum Person {
930 First,
931 Second,
932 Third,
933}
934
935#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
937pub struct PronounData {
938 pub is_personal: Option<bool>,
939 pub is_singular: Option<bool>,
940 pub is_plural: Option<bool>,
941 pub is_possessive: Option<bool>,
942 pub is_reflexive: Option<bool>,
943 pub person: Option<Person>,
944 pub is_subject: Option<bool>,
945 pub is_object: Option<bool>,
946}
947
948impl PronounData {
949 pub fn or(&self, other: &Self) -> Self {
951 Self {
952 is_personal: self.is_personal.or(other.is_personal),
953 is_singular: self.is_singular.or(other.is_singular),
954 is_plural: self.is_plural.or(other.is_plural),
955 is_possessive: self.is_possessive.or(other.is_possessive),
956 is_reflexive: self.is_reflexive.or(other.is_reflexive),
957 person: self.person.or(other.person),
958 is_subject: self.is_subject.or(other.is_subject),
959 is_object: self.is_object.or(other.is_object),
960 }
961 }
962}
963
964#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
966pub struct DeterminerData {
967 pub is_demonstrative: Option<bool>,
968 pub is_possessive: Option<bool>,
969 pub is_quantifier: Option<bool>,
970}
971
972impl DeterminerData {
973 pub fn or(&self, other: &Self) -> Self {
975 Self {
976 is_demonstrative: self.is_demonstrative.or(other.is_demonstrative),
977 is_possessive: self.is_possessive.or(other.is_possessive),
978 is_quantifier: self.is_quantifier.or(other.is_quantifier),
979 }
980 }
981}
982
983#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Is, Hash)]
987pub enum Degree {
988 Positive,
989 Comparative,
990 Superlative,
991}
992
993#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
997pub struct AdjectiveData {
998 pub degree: Option<Degree>,
999}
1000
1001impl AdjectiveData {
1002 pub fn or(&self, other: &Self) -> Self {
1004 Self {
1005 degree: self.degree.or(other.degree),
1006 }
1007 }
1008}
1009
1010#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
1014pub struct AdverbData {
1015 pub is_manner: Option<bool>,
1016 pub is_frequency: Option<bool>,
1017 pub is_degree: Option<bool>,
1018}
1019
1020impl AdverbData {
1021 pub fn or(&self, _other: &Self) -> Self {
1023 Self {
1024 is_manner: self.is_manner.or(_other.is_manner),
1025 is_frequency: self.is_frequency.or(_other.is_frequency),
1026 is_degree: self.is_degree.or(_other.is_degree),
1027 }
1028 }
1029}
1030
1031#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
1032pub struct ConjunctionData {}
1033
1034impl ConjunctionData {
1035 pub fn or(&self, _other: &Self) -> Self {
1037 Self {}
1038 }
1039}
1040
1041#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Default)]
1042pub struct AffixData {
1043 pub is_prefix: Option<bool>,
1044 pub is_suffix: Option<bool>,
1045}
1046
1047impl AffixData {
1048 pub fn or(&self, _other: &Self) -> Self {
1050 Self {
1051 is_prefix: self.is_prefix.or(_other.is_prefix),
1052 is_suffix: self.is_suffix.or(_other.is_suffix),
1053 }
1054 }
1055}
1056
1057#[derive(
1063 Debug,
1064 Clone,
1065 Copy,
1066 Serialize,
1067 Deserialize,
1068 PartialEq,
1069 PartialOrd,
1070 Eq,
1071 Hash,
1072 EnumCount,
1073 EnumString,
1074 EnumIter,
1075 Display,
1076 VariantArray,
1077)]
1078pub enum Dialect {
1079 American = 1 << 0,
1080 Canadian = 1 << 1,
1081 Australian = 1 << 2,
1082 British = 1 << 3,
1083 Indian = 1 << 4,
1084}
1085impl Dialect {
1086 #[must_use]
1089 pub fn try_guess_from_document(document: &Document) -> Option<Self> {
1090 Self::try_from(DialectFlags::get_most_used_dialects_from_document(document)).ok()
1091 }
1092
1093 #[must_use]
1111 pub fn try_from_abbr(abbr: &str) -> Option<Self> {
1112 match abbr {
1113 "US" => Some(Self::American),
1114 "CA" => Some(Self::Canadian),
1115 "AU" => Some(Self::Australian),
1116 "GB" => Some(Self::British),
1117 "IN" => Some(Self::Indian),
1118 _ => None,
1119 }
1120 }
1121 pub fn try_from_bcp47(bcp47: &str) -> Option<Self> {
1123 bcp47.strip_prefix("en-").and_then(Self::try_from_abbr)
1124 }
1125}
1126impl TryFrom<DialectFlags> for Dialect {
1127 type Error = ();
1128
1129 fn try_from(dialect_flags: DialectFlags) -> Result<Self, Self::Error> {
1136 if dialect_flags.bits().count_ones() == 1 {
1138 match dialect_flags {
1139 df if df.is_dialect_enabled_strict(Dialect::American) => Ok(Dialect::American),
1140 df if df.is_dialect_enabled_strict(Dialect::Canadian) => Ok(Dialect::Canadian),
1141 df if df.is_dialect_enabled_strict(Dialect::Australian) => Ok(Dialect::Australian),
1142 df if df.is_dialect_enabled_strict(Dialect::British) => Ok(Dialect::British),
1143 df if df.is_dialect_enabled_strict(Dialect::Indian) => Ok(Dialect::Indian),
1144 _ => Err(()),
1145 }
1146 } else {
1147 Err(())
1149 }
1150 }
1151}
1152
1153type DialectFlagsUnderlyingType = u8;
1157
1158bitflags::bitflags! {
1159 #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash)]
1163 #[serde(transparent)]
1164 pub struct DialectFlags: DialectFlagsUnderlyingType {
1165 const AMERICAN = Dialect::American as DialectFlagsUnderlyingType;
1166 const CANADIAN = Dialect::Canadian as DialectFlagsUnderlyingType;
1167 const AUSTRALIAN = Dialect::Australian as DialectFlagsUnderlyingType;
1168 const BRITISH = Dialect::British as DialectFlagsUnderlyingType;
1169 const INDIAN = Dialect::Indian as DialectFlagsUnderlyingType;
1170 }
1171}
1172impl DialectFlags {
1173 #[must_use]
1176 pub fn is_dialect_enabled(self, dialect: Dialect) -> bool {
1177 self.is_empty() || self.intersects(Self::from_dialect(dialect))
1178 }
1179
1180 #[must_use]
1185 pub fn is_dialect_enabled_strict(self, dialect: Dialect) -> bool {
1186 self.intersects(Self::from_dialect(dialect))
1187 }
1188
1189 #[must_use]
1197 pub fn from_dialect(dialect: Dialect) -> Self {
1198 let Some(out) = Self::from_bits(dialect as DialectFlagsUnderlyingType) else {
1199 panic!("The '{dialect}' dialect isn't defined in DialectFlags!");
1200 };
1201 out
1202 }
1203
1204 #[must_use]
1210 pub fn get_most_used_dialects_from_document(document: &Document) -> Self {
1211 let mut dialect_counters: [(Dialect, usize); Dialect::COUNT] = Dialect::VARIANTS
1213 .iter()
1214 .map(|d| (*d, 0))
1215 .collect_array()
1216 .unwrap();
1217
1218 document.iter_words().for_each(|w| {
1220 if let TokenKind::Word(Some(lexeme_metadata)) = &w.kind {
1221 dialect_counters.iter_mut().for_each(|(dialect, count)| {
1224 if lexeme_metadata.dialects.is_dialect_enabled(*dialect) {
1225 *count += 1;
1226 }
1227 });
1228 }
1229 });
1230
1231 let max_counter = dialect_counters
1233 .iter()
1234 .map(|(_, count)| count)
1235 .max()
1236 .unwrap();
1237 dialect_counters
1239 .into_iter()
1240 .filter(|(_, count)| count == max_counter)
1241 .fold(DialectFlags::empty(), |acc, dialect| {
1242 acc | Self::from_dialect(dialect.0)
1244 })
1245 }
1246}
1247impl Default for DialectFlags {
1248 fn default() -> Self {
1251 Self::empty()
1252 }
1253}
1254
1255#[cfg(test)]
1256pub mod tests {
1257 use crate::DictWordMetadata;
1258 use crate::spell::{Dictionary, FstDictionary};
1259
1260 pub fn md(word: &str) -> DictWordMetadata {
1262 FstDictionary::curated()
1263 .get_word_metadata_str(word)
1264 .unwrap_or_else(|| panic!("Word '{word}' not found in dictionary"))
1265 .into_owned()
1266 }
1267
1268 mod dialect {
1269 use super::super::{Dialect, DialectFlags};
1270 use crate::Document;
1271
1272 #[test]
1273 fn guess_british_dialect() {
1274 let document = Document::new_plain_english_curated("Aluminium was used.");
1275 let df = DialectFlags::get_most_used_dialects_from_document(&document);
1276 assert!(
1277 df.is_dialect_enabled_strict(Dialect::British)
1278 && !df.is_dialect_enabled_strict(Dialect::American)
1279 );
1280 }
1281
1282 #[test]
1283 fn guess_american_dialect() {
1284 let document = Document::new_plain_english_curated("Aluminum was used.");
1285 let df = DialectFlags::get_most_used_dialects_from_document(&document);
1286 assert!(
1287 df.is_dialect_enabled_strict(Dialect::American)
1288 && !df.is_dialect_enabled_strict(Dialect::British)
1289 );
1290 }
1291 }
1292
1293 mod noun {
1294 use crate::dict_word_metadata::tests::md;
1295
1296 #[test]
1297 fn puppy_is_noun() {
1298 assert!(md("puppy").is_noun());
1299 }
1300
1301 #[test]
1302 fn prepare_is_not_noun() {
1303 assert!(!md("prepare").is_noun());
1304 }
1305
1306 #[test]
1307 fn paris_is_proper_noun() {
1308 assert!(md("Paris").is_proper_noun());
1309 }
1310
1311 #[test]
1312 fn permit_is_non_proper_noun() {
1313 assert!(md("lapdog").is_non_proper_noun());
1314 }
1315
1316 #[test]
1317 fn hound_is_singular_noun() {
1318 assert!(md("hound").is_singular_noun());
1319 }
1320
1321 #[test]
1322 fn pooches_is_non_singular_noun() {
1323 assert!(md("pooches").is_non_singular_noun());
1324 }
1325
1326 #[test]
1330 fn loyal_doesnt_pass_is_non_singular_noun() {
1331 assert!(!md("loyal").is_non_singular_noun());
1332 }
1333
1334 #[test]
1335 fn hounds_is_plural_noun() {
1336 assert!(md("hounds").is_plural_noun());
1337 }
1338
1339 #[test]
1340 fn pooch_is_non_plural_noun() {
1341 assert!(md("pooch").is_non_plural_noun());
1342 }
1343
1344 #[test]
1345 fn fish_is_singular_noun() {
1346 assert!(md("fish").is_singular_noun());
1347 }
1348
1349 #[test]
1350 fn fish_is_plural_noun() {
1351 assert!(md("fish").is_plural_noun());
1352 }
1353
1354 #[test]
1355 fn fishes_is_plural_noun() {
1356 assert!(md("fishes").is_plural_noun());
1357 }
1358
1359 #[test]
1360 fn sheep_is_singular_noun() {
1361 assert!(md("sheep").is_singular_noun());
1362 }
1363
1364 #[test]
1365 fn sheep_is_plural_noun() {
1366 assert!(md("sheep").is_plural_noun());
1367 }
1368
1369 #[test]
1370 #[should_panic]
1371 fn sheeps_is_not_word() {
1372 md("sheeps");
1373 }
1374
1375 #[test]
1376 fn bicep_is_singular_noun() {
1377 assert!(md("bicep").is_singular_noun());
1378 }
1379
1380 #[test]
1381 fn biceps_is_singular_noun() {
1382 assert!(md("biceps").is_singular_noun());
1383 }
1384
1385 #[test]
1386 fn biceps_is_plural_noun() {
1387 assert!(md("biceps").is_plural_noun());
1388 }
1389
1390 #[test]
1391 fn aircraft_is_singular_noun() {
1392 assert!(md("aircraft").is_singular_noun());
1393 }
1394
1395 #[test]
1396 fn aircraft_is_plural_noun() {
1397 assert!(md("aircraft").is_plural_noun());
1398 }
1399
1400 #[test]
1401 #[should_panic]
1402 fn aircrafts_is_not_word() {
1403 md("aircrafts");
1404 }
1405
1406 #[test]
1407 fn dog_apostrophe_s_is_possessive_noun() {
1408 assert!(md("dog's").is_possessive_noun());
1409 }
1410
1411 #[test]
1412 fn dogs_is_non_possessive_noun() {
1413 assert!(md("dogs").is_non_possessive_noun());
1414 }
1415
1416 #[test]
1419 fn dog_is_countable() {
1420 assert!(md("dog").is_countable_noun());
1421 }
1422 #[test]
1423 fn dog_is_non_mass_noun() {
1424 assert!(md("dog").is_non_mass_noun());
1425 }
1426
1427 #[test]
1428 fn furniture_is_mass_noun() {
1429 assert!(md("furniture").is_mass_noun());
1430 }
1431 #[test]
1432 fn furniture_is_non_countable_noun() {
1433 assert!(md("furniture").is_non_countable_noun());
1434 }
1435
1436 #[test]
1437 fn equipment_is_mass_noun() {
1438 assert!(md("equipment").is_mass_noun());
1439 }
1440 #[test]
1441 fn equipment_is_non_countable_noun() {
1442 assert!(md("equipment").is_non_countable_noun());
1443 }
1444
1445 #[test]
1446 fn beer_is_countable_noun() {
1447 assert!(md("beer").is_countable_noun());
1448 }
1449 #[test]
1450 fn beer_is_mass_noun() {
1451 assert!(md("beer").is_mass_noun());
1452 }
1453 }
1454
1455 mod pronoun {
1456 use crate::dict_word_metadata::tests::md;
1457
1458 mod i_me_myself {
1459 use crate::dict_word_metadata::tests::md;
1460
1461 #[test]
1462 fn i_is_pronoun() {
1463 assert!(md("I").is_pronoun());
1464 }
1465 #[test]
1466 fn i_is_personal_pronoun() {
1467 assert!(md("I").is_personal_pronoun());
1468 }
1469 #[test]
1470 fn i_is_singular_pronoun() {
1471 assert!(md("I").is_singular_pronoun());
1472 }
1473 #[test]
1474 fn i_is_subject_pronoun() {
1475 assert!(md("I").is_subject_pronoun());
1476 }
1477
1478 #[test]
1479 fn me_is_pronoun() {
1480 assert!(md("me").is_pronoun());
1481 }
1482 #[test]
1483 fn me_is_personal_pronoun() {
1484 assert!(md("me").is_personal_pronoun());
1485 }
1486 #[test]
1487 fn me_is_singular_pronoun() {
1488 assert!(md("me").is_singular_pronoun());
1489 }
1490 #[test]
1491 fn me_is_object_pronoun() {
1492 assert!(md("me").is_object_pronoun());
1493 }
1494
1495 #[test]
1496 fn myself_is_pronoun() {
1497 assert!(md("myself").is_pronoun());
1498 }
1499 #[test]
1500 fn myself_is_personal_pronoun() {
1501 assert!(md("myself").is_personal_pronoun());
1502 }
1503 #[test]
1504 fn myself_is_singular_pronoun() {
1505 assert!(md("myself").is_singular_pronoun());
1506 }
1507 #[test]
1508 fn myself_is_reflexive_pronoun() {
1509 assert!(md("myself").is_reflexive_pronoun());
1510 }
1511 }
1512
1513 mod we_us_ourselves {
1514 use crate::dict_word_metadata::tests::md;
1515
1516 #[test]
1517 fn we_is_pronoun() {
1518 assert!(md("we").is_pronoun());
1519 }
1520 #[test]
1521 fn we_is_personal_pronoun() {
1522 assert!(md("we").is_personal_pronoun());
1523 }
1524 #[test]
1525 fn we_is_plural_pronoun() {
1526 assert!(md("we").is_plural_pronoun());
1527 }
1528 #[test]
1529 fn we_is_subject_pronoun() {
1530 assert!(md("we").is_subject_pronoun());
1531 }
1532
1533 #[test]
1534 fn us_is_pronoun() {
1535 assert!(md("us").is_pronoun());
1536 }
1537 #[test]
1538 fn us_is_personal_pronoun() {
1539 assert!(md("us").is_personal_pronoun());
1540 }
1541 #[test]
1542 fn us_is_plural_pronoun() {
1543 assert!(md("us").is_plural_pronoun());
1544 }
1545 #[test]
1546 fn us_is_object_pronoun() {
1547 assert!(md("us").is_object_pronoun());
1548 }
1549
1550 #[test]
1551 fn ourselves_is_pronoun() {
1552 assert!(md("ourselves").is_pronoun());
1553 }
1554 #[test]
1555 fn ourselves_is_personal_pronoun() {
1556 assert!(md("ourselves").is_personal_pronoun());
1557 }
1558 #[test]
1559 fn ourselves_is_plural_pronoun() {
1560 assert!(md("ourselves").is_plural_pronoun());
1561 }
1562 #[test]
1563 fn ourselves_is_reflexive_pronoun() {
1564 assert!(md("ourselves").is_reflexive_pronoun());
1565 }
1566 }
1567
1568 mod you_yourself {
1569 use crate::dict_word_metadata::tests::md;
1570
1571 #[test]
1572 fn you_is_pronoun() {
1573 assert!(md("you").is_pronoun());
1574 }
1575 #[test]
1576 fn you_is_personal_pronoun() {
1577 assert!(md("you").is_personal_pronoun());
1578 }
1579 #[test]
1580 fn you_is_singular_pronoun() {
1581 assert!(md("you").is_singular_pronoun());
1582 }
1583 #[test]
1584 fn you_is_plural_pronoun() {
1585 assert!(md("you").is_plural_pronoun());
1586 }
1587 #[test]
1588 fn you_is_subject_pronoun() {
1589 assert!(md("you").is_subject_pronoun());
1590 }
1591 #[test]
1592 fn you_is_object_pronoun() {
1593 assert!(md("you").is_object_pronoun());
1594 }
1595 #[test]
1596 fn yourself_is_pronoun() {
1597 assert!(md("yourself").is_pronoun());
1598 }
1599 #[test]
1600 fn yourself_is_personal_pronoun() {
1601 assert!(md("yourself").is_personal_pronoun());
1602 }
1603 #[test]
1604 fn yourself_is_singular_pronoun() {
1605 assert!(md("yourself").is_singular_pronoun());
1606 }
1607 #[test]
1608 fn yourself_is_reflexive_pronoun() {
1609 assert!(md("yourself").is_reflexive_pronoun());
1610 }
1611 }
1612
1613 mod he_him_himself {
1614 use crate::dict_word_metadata::tests::md;
1615
1616 #[test]
1617 fn he_is_pronoun() {
1618 assert!(md("he").is_pronoun());
1619 }
1620 #[test]
1621 fn he_is_personal_pronoun() {
1622 assert!(md("he").is_personal_pronoun());
1623 }
1624 #[test]
1625 fn he_is_singular_pronoun() {
1626 assert!(md("he").is_singular_pronoun());
1627 }
1628 #[test]
1629 fn he_is_subject_pronoun() {
1630 assert!(md("he").is_subject_pronoun());
1631 }
1632
1633 #[test]
1634 fn him_is_pronoun() {
1635 assert!(md("him").is_pronoun());
1636 }
1637 #[test]
1638 fn him_is_personal_pronoun() {
1639 assert!(md("him").is_personal_pronoun());
1640 }
1641 #[test]
1642 fn him_is_singular_pronoun() {
1643 assert!(md("him").is_singular_pronoun());
1644 }
1645 #[test]
1646 fn him_is_object_pronoun() {
1647 assert!(md("him").is_object_pronoun());
1648 }
1649
1650 #[test]
1651 fn himself_is_pronoun() {
1652 assert!(md("himself").is_pronoun());
1653 }
1654 #[test]
1655 fn himself_is_personal_pronoun() {
1656 assert!(md("himself").is_personal_pronoun());
1657 }
1658 #[test]
1659 fn himself_is_singular_pronoun() {
1660 assert!(md("himself").is_singular_pronoun());
1661 }
1662 #[test]
1663 fn himself_is_reflexive_pronoun() {
1664 assert!(md("himself").is_reflexive_pronoun());
1665 }
1666 }
1667
1668 mod she_her_herself {
1669 use crate::dict_word_metadata::tests::md;
1670
1671 #[test]
1672 fn she_is_pronoun() {
1673 assert!(md("she").is_pronoun());
1674 }
1675 #[test]
1676 fn she_is_personal_pronoun() {
1677 assert!(md("she").is_personal_pronoun());
1678 }
1679 #[test]
1680 fn she_is_singular_pronoun() {
1681 assert!(md("she").is_singular_pronoun());
1682 }
1683 #[test]
1684 fn she_is_subject_pronoun() {
1685 assert!(md("she").is_subject_pronoun());
1686 }
1687
1688 #[test]
1689 fn her_is_pronoun() {
1690 assert!(md("her").is_pronoun());
1691 }
1692 #[test]
1693 fn her_is_personal_pronoun() {
1694 assert!(md("her").is_personal_pronoun());
1695 }
1696 #[test]
1697 fn her_is_singular_pronoun() {
1698 assert!(md("her").is_singular_pronoun());
1699 }
1700 #[test]
1701 fn her_is_object_pronoun() {
1702 assert!(md("her").is_object_pronoun());
1703 }
1704
1705 #[test]
1706 fn herself_is_pronoun() {
1707 assert!(md("herself").is_pronoun());
1708 }
1709 #[test]
1710 fn herself_is_personal_pronoun() {
1711 assert!(md("herself").is_personal_pronoun());
1712 }
1713 #[test]
1714 fn herself_is_singular_pronoun() {
1715 assert!(md("herself").is_singular_pronoun());
1716 }
1717 #[test]
1718 fn herself_is_reflexive_pronoun() {
1719 assert!(md("herself").is_reflexive_pronoun());
1720 }
1721 }
1722
1723 mod it_itself {
1724 use crate::dict_word_metadata::tests::md;
1725
1726 #[test]
1727 fn it_is_pronoun() {
1728 assert!(md("it").is_pronoun());
1729 }
1730 #[test]
1731 fn it_is_personal_pronoun() {
1732 assert!(md("it").is_personal_pronoun());
1733 }
1734 #[test]
1735 fn it_is_singular_pronoun() {
1736 assert!(md("it").is_singular_pronoun());
1737 }
1738 #[test]
1739 fn it_is_subject_pronoun() {
1740 assert!(md("it").is_subject_pronoun());
1741 }
1742 #[test]
1743 fn it_is_object_pronoun() {
1744 assert!(md("it").is_object_pronoun());
1745 }
1746
1747 #[test]
1748 fn itself_is_pronoun() {
1749 assert!(md("itself").is_pronoun());
1750 }
1751 #[test]
1752 fn itself_is_personal_pronoun() {
1753 assert!(md("itself").is_personal_pronoun());
1754 }
1755 #[test]
1756 fn itself_is_singular_pronoun() {
1757 assert!(md("itself").is_singular_pronoun());
1758 }
1759 #[test]
1760 fn itself_is_reflexive_pronoun() {
1761 assert!(md("itself").is_reflexive_pronoun());
1762 }
1763 }
1764
1765 mod they_them_themselves {
1766 use crate::dict_word_metadata::tests::md;
1767
1768 #[test]
1769 fn they_is_pronoun() {
1770 assert!(md("they").is_pronoun());
1771 }
1772 #[test]
1773 fn they_is_personal_pronoun() {
1774 assert!(md("they").is_personal_pronoun());
1775 }
1776 #[test]
1777 fn they_is_plural_pronoun() {
1778 assert!(md("they").is_plural_pronoun());
1779 }
1780 #[test]
1781 fn they_is_subject_pronoun() {
1782 assert!(md("they").is_subject_pronoun());
1783 }
1784
1785 #[test]
1786 fn them_is_pronoun() {
1787 assert!(md("them").is_pronoun());
1788 }
1789 #[test]
1790 fn them_is_personal_pronoun() {
1791 assert!(md("them").is_personal_pronoun());
1792 }
1793 #[test]
1794 fn them_is_plural_pronoun() {
1795 assert!(md("them").is_plural_pronoun());
1796 }
1797 #[test]
1798 fn them_is_object_pronoun() {
1799 assert!(md("them").is_object_pronoun());
1800 }
1801
1802 #[test]
1803 fn themselves_is_pronoun() {
1804 assert!(md("themselves").is_pronoun());
1805 }
1806 #[test]
1807 fn themselves_is_personal_pronoun() {
1808 assert!(md("themselves").is_personal_pronoun());
1809 }
1810 #[test]
1811 fn themselves_is_plural_pronoun() {
1812 assert!(md("themselves").is_plural_pronoun());
1813 }
1814 #[test]
1815 fn themselves_is_reflexive_pronoun() {
1816 assert!(md("themselves").is_reflexive_pronoun());
1817 }
1818 }
1819
1820 #[test]
1822 fn mine_is_pronoun() {
1823 assert!(md("mine").is_pronoun());
1824 }
1825 #[test]
1826 fn ours_is_pronoun() {
1827 assert!(md("ours").is_pronoun());
1828 }
1829 #[test]
1830 fn yours_is_pronoun() {
1831 assert!(md("yours").is_pronoun());
1832 }
1833 #[test]
1834 fn his_is_pronoun() {
1835 assert!(md("his").is_pronoun());
1836 }
1837 #[test]
1838 fn hers_is_pronoun() {
1839 assert!(md("hers").is_pronoun());
1840 }
1841 #[test]
1842 fn its_is_pronoun() {
1843 assert!(md("its").is_pronoun());
1844 }
1845 #[test]
1846 fn theirs_is_pronoun() {
1847 assert!(md("theirs").is_pronoun());
1848 }
1849
1850 #[test]
1852 fn archaic_pronouns() {
1853 assert!(md("thou").is_pronoun());
1854 assert!(md("thee").is_pronoun());
1855 assert!(md("thyself").is_pronoun());
1856 assert!(md("thine").is_pronoun());
1857 }
1858
1859 #[test]
1861 fn generic_pronouns() {
1862 assert!(md("one").is_pronoun());
1863 assert!(md("oneself").is_pronoun());
1864 }
1865
1866 #[test]
1868 fn relative_and_interrogative_pronouns() {
1869 assert!(md("who").is_pronoun());
1870 assert!(md("whom").is_pronoun());
1871 assert!(md("whose").is_pronoun());
1872 assert!(md("which").is_pronoun());
1873 assert!(md("what").is_pronoun());
1874 }
1875
1876 #[test]
1878 #[ignore = "not in dictionary"]
1879 fn nonstandard_pronouns() {
1880 assert!(md("themself").pronoun.is_some());
1881 assert!(md("y'all'").pronoun.is_some());
1882 }
1883 }
1884
1885 mod nominal {
1886 use crate::dict_word_metadata::tests::md;
1887
1888 #[test]
1889 fn my_is_possessive_nominal() {
1890 assert!(md("my").is_possessive_nominal());
1891 }
1892
1893 #[test]
1894 fn mine_is_not_possessive_nominal() {
1895 assert!(!md("mine").is_possessive_nominal());
1896 }
1897
1898 #[test]
1899 fn freds_is_possessive_nominal() {
1900 assert!(md("Fred's").is_possessive_nominal());
1901 }
1902
1903 #[test]
1904 fn fred_is_not_possessive_nominal() {
1905 assert!(!md("Fred").is_possessive_nominal());
1906 }
1907
1908 #[test]
1909 fn dogs_is_possessive_nominal() {
1910 assert!(md("dog's").is_possessive_nominal());
1911 }
1912
1913 #[test]
1914 fn microsofts_is_possessive_nominal() {
1915 assert!(md("Microsoft's").is_possessive_nominal());
1916 }
1917 }
1918
1919 mod adjective {
1920 use crate::{Degree, dict_word_metadata::tests::md};
1921
1922 #[test]
1925 #[ignore = "not marked yet because it might not be reliable"]
1926 fn big_is_positive() {
1927 assert_eq!(md("big").get_degree(), Some(Degree::Positive));
1928 }
1929
1930 #[test]
1931 fn bigger_is_comparative() {
1932 assert_eq!(md("bigger").get_degree(), Some(Degree::Comparative));
1933 }
1934
1935 #[test]
1936 fn biggest_is_superlative() {
1937 assert_eq!(md("biggest").get_degree(), Some(Degree::Superlative));
1938 }
1939
1940 #[test]
1941 #[should_panic(expected = "Word 'bigly' not found in dictionary")]
1942 fn bigly_is_not_an_adjective_form_we_track() {
1943 assert_eq!(md("bigly").get_degree(), None);
1944 }
1945
1946 #[test]
1951 fn bigger_is_comparative_adjective() {
1952 assert!(md("bigger").is_comparative_adjective());
1953 }
1954
1955 #[test]
1956 fn biggest_is_superlative_adjective() {
1957 assert!(md("biggest").is_superlative_adjective());
1958 }
1959 }
1960
1961 #[test]
1962 fn the_is_determiner() {
1963 assert!(md("the").is_determiner());
1964 }
1965 #[test]
1966 fn this_is_demonstrative_determiner() {
1967 assert!(md("this").is_demonstrative_determiner());
1968 }
1969 #[test]
1970 fn your_is_possessive_determiner() {
1971 assert!(md("your").is_possessive_determiner());
1972 }
1973
1974 #[test]
1975 fn every_is_quantifier() {
1976 assert!(md("every").is_quantifier());
1977 }
1978
1979 #[test]
1980 fn the_isnt_quantifier() {
1981 assert!(!md("the").is_quantifier());
1982 }
1983
1984 #[test]
1985 fn equipment_is_mass_noun() {
1986 assert!(md("equipment").is_mass_noun());
1987 }
1988
1989 #[test]
1990 fn equipment_is_non_countable_noun() {
1991 assert!(md("equipment").is_non_countable_noun());
1992 }
1993
1994 #[test]
1995 fn equipment_isnt_countable_noun() {
1996 assert!(!md("equipment").is_countable_noun());
1997 }
1998
1999 #[test]
2000 fn infrastructure_is_mass_noun_only() {
2001 assert!(md("infrastructure").is_mass_noun_only());
2002 }
2003
2004 #[test]
2005 fn beer_is_not_mass_noun_only() {
2006 assert!(!md("beer").is_mass_noun_only());
2007 }
2008
2009 #[test]
2010 fn sheep_is_not_singular_only() {
2011 assert!(!md("sheep").is_singular_noun_only());
2012 }
2013
2014 #[test]
2015 fn sheep_is_not_plural_only() {
2016 assert!(!md("sheep").is_plural_noun_only());
2017 }
2018
2019 #[test]
2020 fn ox_is_singular_only() {
2021 assert!(md("ox").is_singular_noun_only());
2022 }
2023
2024 #[test]
2025 fn oxen_is_plural_only() {
2026 assert!(md("oxen").is_plural_noun_only());
2027 }
2028
2029 mod verb {
2030 use crate::dict_word_metadata::tests::md;
2031
2032 #[test]
2033 fn lemma_walk() {
2034 let md = md("walk");
2035 assert!(md.is_verb_lemma())
2036 }
2037
2038 #[test]
2039 fn lemma_fix() {
2040 let md = md("fix");
2041 assert!(md.is_verb_lemma())
2042 }
2043
2044 #[test]
2045 fn progressive_walking() {
2046 let md = md("walking");
2047 assert!(md.is_verb_progressive_form())
2048 }
2049
2050 #[test]
2051 fn past_walked() {
2052 let md = md("walked");
2053 assert!(md.is_verb_past_form())
2054 }
2055
2056 #[test]
2057 fn regular_past_thought() {
2058 let md = md("thought");
2059 assert!(md.is_verb_regular_past_form())
2060 }
2061
2062 #[test]
2063 fn simple_past_ate() {
2064 let md = md("ate");
2065 assert!(md.is_verb_simple_past_form())
2066 }
2067
2068 #[test]
2069 fn past_participle_eaten() {
2070 let md = md("eaten");
2071 assert!(md.is_verb_past_participle_form())
2072 }
2073
2074 #[test]
2075 fn ate_is_simple_past_only() {
2076 let md = md("ate");
2077 assert!(md.is_verb_simple_past_only());
2078 assert!(!md.is_verb_past_participle_only());
2079 }
2080
2081 #[test]
2082 fn eaten_is_past_participle_only() {
2083 let md = md("eaten");
2084 assert!(md.is_verb_past_participle_only());
2085 assert!(!md.is_verb_simple_past_only());
2086 }
2087
2088 #[test]
2089 fn thought_is_neither_past_form_only() {
2090 let md = md("thought");
2091 assert!(!md.is_verb_simple_past_only());
2092 assert!(!md.is_verb_past_participle_only());
2093 }
2094
2095 #[test]
2096 fn shared_past_forms_are_neither_past_form_only() {
2097 let md = md("thought");
2098 assert!(!md.is_verb_simple_past_only());
2099 assert!(!md.is_verb_past_participle_only());
2100 assert!(md.is_verb_regular_past_form());
2101 }
2102
2103 #[test]
2104 fn distinct_past_forms_are_not_regular_past() {
2105 assert!(!md("ate").is_verb_regular_past_form());
2106 assert!(!md("eaten").is_verb_regular_past_form());
2107 assert!(!md("walked").is_verb_regular_past_form());
2108 }
2109
2110 #[test]
2111 fn third_pers_sing_walks() {
2112 let md = md("walks");
2113 assert!(md.is_verb_third_person_singular_present_form())
2114 }
2115 }
2116}