1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use super::{AppositiveReferentialAffix, RegularAffix};
use crate::{
category::{VowelFormDegree, VowelFormSequence},
gloss::{Gloss, GlossFlags},
romanize::{
stream::ParseError,
token::{OwnedConsonantForm, VowelForm},
},
};
/// A list of affixes in a formative slot.
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum AffixList {
/// A list of normal affixes.
Normal(Vec<RegularAffix>),
/// A single appositive referential affix.
AppositiveReferential(AppositiveReferentialAffix),
}
impl AffixList {
/// Creates an [`AffixList`] from a slice of VxCs pairs. If the slice contains a single affix
/// and the affix is a type-3 affix, it will be interpreted as an appositive referential.
/// Otherwise, the affix list will be interpreted normally.
pub fn from_vxcs_slice(forms: &[(VowelForm, OwnedConsonantForm)]) -> Result<Self, ParseError> {
'a: {
if forms.len() == 1 {
let first = &forms[0];
if first.0.sequence == VowelFormSequence::S3
&& !matches!(
&**first.1,
"lw" | "ly"
| "sw"
| "zw"
| "čw"
| "šw"
| "žw"
| "jw"
| "sy"
| "zy"
| "čy"
| "šy"
| "žy"
| "jy"
)
{
return Ok(AffixList::AppositiveReferential(
AppositiveReferentialAffix {
case: match first.0.degree {
VowelFormDegree::D0 => break 'a,
VowelFormDegree::D1 => crate::category::AppositiveCase::POS,
VowelFormDegree::D2 => crate::category::AppositiveCase::PRP,
VowelFormDegree::D3 => crate::category::AppositiveCase::GEN,
VowelFormDegree::D4 => crate::category::AppositiveCase::ATT,
VowelFormDegree::D5 => crate::category::AppositiveCase::PDC,
VowelFormDegree::D6 => crate::category::AppositiveCase::ITP,
VowelFormDegree::D7 => crate::category::AppositiveCase::OGN,
VowelFormDegree::D8 => crate::category::AppositiveCase::IDP,
VowelFormDegree::D9 => crate::category::AppositiveCase::PAR,
},
referents: first.1.parse()?,
},
));
}
}
}
let mut items = Vec::new();
for (vx, cs) in forms {
items.push(RegularAffix::from_vxcs(*vx, &**cs)?);
}
Ok(Self::Normal(items))
}
/// Gets the number of affixes in this list.
pub fn len(&self) -> usize {
match self {
Self::Normal(items) => items.len(),
Self::AppositiveReferential(_) => 1,
}
}
}
impl Default for AffixList {
fn default() -> Self {
AffixList::Normal(Vec::new())
}
}
impl Gloss for AffixList {
fn gloss(&self, flags: GlossFlags) -> String {
match self {
Self::AppositiveReferential(value) => value.gloss(flags),
Self::Normal(value) => {
let mut output = String::new();
let mut is_first = true;
for affix in value {
if !is_first {
output += "-";
}
is_first = false;
output += &affix.gloss(flags);
}
output
}
}
}
}