use std::str::FromStr;
use crate::{
category::{AffixDegree, PerspectivelessReferentList},
gloss::{Gloss, GlossFlags, GlossStatic},
prelude::token::NumeralForm,
romanize::{stream::ParseError, token::OwnedConsonantForm},
specificity::{AsGeneral, TryAsSpecific},
};
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct NormalFormativeRoot {
pub cr: OwnedConsonantForm,
}
impl NormalFormativeRoot {
pub fn new(cr: impl Into<String>) -> Self {
Self {
cr: OwnedConsonantForm(cr.into()),
}
}
}
impl Gloss for NormalFormativeRoot {
fn gloss(&self, flags: GlossFlags) -> String {
if flags.matches(GlossFlags::FORMAT_MARKDOWN) {
let mut output = "**".to_owned();
output += &self.cr; output += "**";
output
} else {
self.cr.0.to_owned()
}
}
}
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct NumericFormativeRoot {
pub form: NumeralForm,
}
impl Gloss for NumericFormativeRoot {
fn gloss(&self, _flags: GlossFlags) -> String {
let mut output = "“".to_owned();
output += &self.form.integer_part.to_string();
output += "”";
output
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ReferentialFormativeRoot {
pub referents: PerspectivelessReferentList,
}
impl FromStr for ReferentialFormativeRoot {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(ReferentialFormativeRoot {
referents: s.parse()?,
})
}
}
impl Gloss for ReferentialFormativeRoot {
fn gloss(&self, flags: GlossFlags) -> String {
let referents = &self.referents.referents;
if referents.len() == 1 {
referents.first().gloss(flags)
} else {
let mut output = "[".to_owned();
output += &referents.first().gloss(flags);
for el in &referents[1..] {
output += "+";
output += &el.gloss(flags);
}
output += "]";
output
}
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct AffixualFormativeRoot {
pub cs: String,
pub degree: AffixDegree,
}
impl AffixualFormativeRoot {
pub fn new(cs: impl Into<String>, degree: AffixDegree) -> Self {
Self {
cs: cs.try_into().unwrap(),
degree,
}
}
}
impl Gloss for AffixualFormativeRoot {
fn gloss(&self, flags: GlossFlags) -> String {
if flags.matches(GlossFlags::FORMAT_MARKDOWN) {
let mut output = "**".to_owned();
output += &self.cs; output += "**/";
output += self.degree.gloss_static(GlossFlags::NONE);
output += "-D";
output += self.degree.gloss_static(GlossFlags::NONE);
output
} else {
let mut output = self.cs.clone();
output += "/";
output += self.degree.gloss_static(GlossFlags::NONE);
output += "-D";
output += self.degree.gloss_static(GlossFlags::NONE);
return output;
}
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum ShortcutCheckedFormativeRoot {
Normal(NormalFormativeRoot),
Numeric(NumericFormativeRoot),
Referential(ReferentialFormativeRoot),
Affixual(AffixualFormativeRoot),
}
impl ShortcutCheckedFormativeRoot {
pub fn new_normal(source: impl Into<String>) -> ShortcutCheckedFormativeRoot {
ShortcutCheckedFormativeRoot::Normal(NormalFormativeRoot {
cr: OwnedConsonantForm(source.into()),
})
}
}
impl Default for ShortcutCheckedFormativeRoot {
fn default() -> Self {
Self::Normal(NormalFormativeRoot {
cr: OwnedConsonantForm("t".to_owned()),
})
}
}
impl Gloss for ShortcutCheckedFormativeRoot {
fn gloss(&self, flags: GlossFlags) -> String {
match self {
Self::Normal(value) => value.gloss(flags),
Self::Numeric(value) => value.gloss(flags),
Self::Referential(value) => value.gloss(flags),
Self::Affixual(value) => value.gloss(flags),
}
}
}
macro_rules! as_general_impl {
($specific:ident, $variant:ident) => {
impl AsGeneral<ShortcutCheckedFormativeRoot> for $specific {
fn as_general(self) -> ShortcutCheckedFormativeRoot {
ShortcutCheckedFormativeRoot::$variant(self)
}
}
impl From<$specific> for ShortcutCheckedFormativeRoot {
fn from(value: $specific) -> Self {
value.as_general()
}
}
impl TryAsSpecific<$specific> for ShortcutCheckedFormativeRoot {
fn try_as_specific(self) -> Option<$specific> {
match self {
Self::$variant(value) => Some(value),
_ => None,
}
}
}
};
}
as_general_impl!(NormalFormativeRoot, Normal);
as_general_impl!(NumericFormativeRoot, Numeric);
as_general_impl!(ReferentialFormativeRoot, Referential);
as_general_impl!(AffixualFormativeRoot, Affixual);