1use smallvec::SmallVec;
2
3use crate::{
4 analyzer::{dictionary::LemmaDict, Tag},
5 errors::DictionaryErr,
6 morph::vanga::{LemmaVanga, VangaVariant},
7 opencorpora::dictionary::GramWord,
8};
9
10use self::grammemes::{Grammem, Other, ParteSpeech};
11
12pub mod grammemes;
15pub(crate) mod vanga;
18
19pub(crate) const UNPRODUCTIVE: [Grammem; 8] = [
23 Grammem::ParteSpeech(ParteSpeech::Number),
24 Grammem::ParteSpeech(ParteSpeech::NounPronoun),
25 Grammem::ParteSpeech(ParteSpeech::Predicative),
26 Grammem::ParteSpeech(ParteSpeech::Preposition),
27 Grammem::ParteSpeech(ParteSpeech::Conjunction),
28 Grammem::ParteSpeech(ParteSpeech::Particle),
29 Grammem::ParteSpeech(ParteSpeech::Interjection),
30 Grammem::Other(Other::Pronominal),
31];
32
33#[macro_export]
34macro_rules! gram {
35 ( $x:expr ) => {{
36 $crate::morph::grammemes::ToGrammem::to_grammem($x)
37 }};
38}
39
40#[macro_export]
41macro_rules! grams {
42 ( $($x:expr),* $(,)? ) => {
43 {
44 vec![$(
45 $crate::gram![$x],
46 )*]
47 }
48 };
49}
50
51#[test]
52fn test_gram() {
53 let grammemes = vec![
54 Grammem::ParteSpeech(ParteSpeech::Number),
55 Grammem::Other(Other::Pronominal),
56 ];
57
58 let grams = grams![ParteSpeech::Number, Other::Pronominal];
59
60 assert_eq!(gram!(ParteSpeech::Number), *grammemes.first().unwrap());
61 assert_eq!(grammemes, grams);
62}
63
64impl LemmaDict {
65 pub(crate) fn first_tags(&self) -> Result<Tag, DictionaryErr> {
68 let LemmaDict { normal_form, .. } = self;
69
70 match &normal_form.gram {
71 None => Err(DictionaryErr::LostFirstGrammemes(
72 normal_form.text.to_owned(),
73 )),
74 Some(gram) => Ok(SmallVec::from_iter(gram.iter().map(|g| g.v))),
75 }
76 }
77
78 pub(crate) fn forms(forms: Vec<GramWord>) -> impl Iterator<Item = (String, Tag)> {
82 forms.into_iter().map(|gram| match gram.gram {
83 None => (gram.text, SmallVec::from(vec![])),
84 Some(grams) => {
85 let tags = SmallVec::from_iter(grams.iter().map(|gram| gram.v));
86 (gram.text, tags)
87 }
88 })
89 }
90}
91
92impl LemmaVanga {
93 pub(crate) fn first_tags(&self) -> Result<Tag, DictionaryErr> {
96 let LemmaVanga { variants } = self;
97
98 match variants.first() {
99 None => Err(DictionaryErr::EmptyVanga),
100 Some(VangaVariant { tag, .. }) => Ok(tag.to_owned()),
101 }
102 }
103
104 pub(crate) fn forms(forms: Vec<GramWord>) -> impl Iterator<Item = (String, Tag)> {
108 forms.into_iter().map(|gram| match gram.gram {
109 None => (gram.text, SmallVec::from(vec![])),
110 Some(grams) => {
111 let tags = SmallVec::from_iter(grams.iter().map(|gram| gram.v));
112 (gram.text, tags)
113 }
114 })
115 }
116}