pub struct GrammarFeature {
pub id: &'static str,
pub question: &'static str,
pub options: &'static [(&'static str, &'static str)],
}
impl GrammarFeature {
pub fn is_valid(&self, value: &str) -> bool {
self.options.iter().any(|(v, _)| v.eq_ignore_ascii_case(value))
}
pub fn values(&self) -> String {
self.options.iter().map(|(v, _)| *v).collect::<Vec<_>>().join(" | ")
}
}
pub fn catalog() -> &'static [GrammarFeature] {
CATALOG
}
pub fn feature(id: &str) -> Option<&'static GrammarFeature> {
CATALOG.iter().find(|f| f.id.eq_ignore_ascii_case(id))
}
const CATALOG: &[GrammarFeature] = &[
GrammarFeature {
id: "word_order",
question: "Basic order of subject, verb, object?",
options: &[
("svo", "subject–verb–object (English, Mandarin)"),
("sov", "subject–object–verb (Japanese, Turkish, Latin)"),
("vso", "verb–subject–object (Welsh, Classical Arabic)"),
("vos", "verb–object–subject (Malagasy)"),
("osv", "object–subject–verb (rare)"),
("ovs", "object–verb–subject (rare)"),
("free", "free order with case marking (Russian, Sanskrit)"),
],
},
GrammarFeature {
id: "adjective_order",
question: "Where do adjectives sit relative to the noun?",
options: &[("prenominal", "before the noun (English)"), ("postnominal", "after the noun (French, Spanish)")],
},
GrammarFeature {
id: "genitive_order",
question: "Where does the possessor sit relative to the possessed?",
options: &[("possessor_first", "possessor–possessed (John's book)"), ("possessed_first", "possessed–possessor (book of John)")],
},
GrammarFeature {
id: "adposition",
question: "Prepositions or postpositions?",
options: &[("preposition", "before the noun (to the house)"), ("postposition", "after the noun (the house to)"), ("none", "case marking instead")],
},
GrammarFeature {
id: "alignment",
question: "Morphosyntactic alignment?",
options: &[
("nominative_accusative", "subject vs object (most European languages)"),
("ergative_absolutive", "agent vs patient/intransitive subject (Basque, Dyirbal)"),
("tripartite", "S, A, and P all distinct"),
("active_stative", "marking by volitionality"),
],
},
GrammarFeature {
id: "case",
question: "Morphological case system?",
options: &[("none", "no case marking"), ("few", "a small set (2–4 cases)"), ("many", "a rich case system (5+)")],
},
GrammarFeature {
id: "gender",
question: "Grammatical gender / noun class?",
options: &[("none", "no gender"), ("two", "two genders (masc/fem or common/neuter)"), ("three", "three genders"), ("many", "a noun-class system (Bantu)")],
},
GrammarFeature {
id: "number",
question: "Number marking?",
options: &[("none", "no obligatory number"), ("singular_plural", "singular vs plural"), ("singular_dual_plural", "adds a dual"), ("rich", "trial / paucal / etc.")],
},
GrammarFeature {
id: "definiteness",
question: "How is definiteness marked?",
options: &[("none", "no articles"), ("articles", "definite/indefinite words (a, the)"), ("affix", "a definite affix (Scandinavian, Arabic)")],
},
GrammarFeature {
id: "tense",
question: "Tense inflection?",
options: &[("none", "no grammatical tense"), ("past_nonpast", "past vs non-past"), ("past_present_future", "three-way"), ("remoteness", "graded remoteness (today/yesterday/distant)")],
},
GrammarFeature {
id: "aspect",
question: "Aspect inflection?",
options: &[("none", "no grammatical aspect"), ("perfective_imperfective", "perfective vs imperfective"), ("rich", "progressive/habitual/perfect/…")],
},
GrammarFeature {
id: "mood",
question: "Mood inflection?",
options: &[("none", "mood only periphrastically"), ("indicative_subjunctive", "a realis/irrealis split"), ("rich", "many moods (optative, jussive, …)")],
},
GrammarFeature {
id: "evidentiality",
question: "Is the source of information grammaticalized?",
options: &[("none", "no evidentials"), ("present", "marks witnessed / reported / inferred (Quechua, Tariana)")],
},
GrammarFeature {
id: "negation",
question: "How is clausal negation expressed?",
options: &[("particle", "a negative word (not)"), ("affix", "a negative affix on the verb"), ("auxiliary", "a negative auxiliary verb (Finnish)")],
},
GrammarFeature {
id: "question",
question: "How are polar (yes/no) questions formed?",
options: &[("intonation", "intonation only"), ("particle", "a question particle (Japanese -ka)"), ("word_order", "inversion (English)"), ("morphology", "verbal morphology")],
},
GrammarFeature {
id: "relative_clause",
question: "Relative-clause strategy?",
options: &[("postnominal", "after the head noun (English)"), ("prenominal", "before the head noun (Japanese, Chinese)"), ("internally_headed", "head inside the clause"), ("correlative", "correlative (Hindi)")],
},
GrammarFeature {
id: "numeral_order",
question: "Where do cardinal numerals sit relative to the noun?",
options: &[("numeral_first", "numeral–noun (three books; English)"), ("noun_first", "noun–numeral (books three; Khmer)")],
},
GrammarFeature {
id: "demonstrative_order",
question: "Where do demonstratives sit relative to the noun?",
options: &[("demonstrative_first", "this book (English)"), ("noun_first", "book this (Indonesian)")],
},
GrammarFeature {
id: "morphological_type",
question: "Dominant morphological type?",
options: &[
("isolating", "little/no inflection (Mandarin, Vietnamese)"),
("agglutinative", "clear morpheme boundaries (Turkish, Finnish)"),
("fusional", "portmanteau affixes (Latin, Russian)"),
("polysynthetic", "many morphemes per word (Inuktitut)"),
],
},
GrammarFeature {
id: "head_marking",
question: "Is agreement marked on the head or the dependent?",
options: &[("head_marking", "on the head (Mayan)"), ("dependent_marking", "on the dependent / by case (Latin)"), ("double", "both"), ("none", "neither")],
},
GrammarFeature {
id: "voice",
question: "Valence-changing voice operations?",
options: &[("none", "no voice morphology"), ("passive", "a passive"), ("passive_antipassive", "passive + antipassive"), ("rich", "applicatives / causatives / …")],
},
GrammarFeature {
id: "comparative",
question: "How is the standard of comparison marked?",
options: &[("particle", "a comparative word (bigger than)"), ("locational", "a case/adposition ('big from Y')"), ("exceed", "a verb 'to exceed' (serial; many African/Asian langs)"), ("conjoined", "conjoined ('X is big, Y is small')")],
},
];
pub struct UgParameter {
pub id: &'static str,
#[allow(dead_code)]
pub question: &'static str,
pub values: &'static [&'static str],
}
impl UgParameter {
pub fn is_valid(&self, value: &str) -> bool {
self.values.iter().any(|v| v.eq_ignore_ascii_case(value))
}
}
pub const UG_PARAMETERS: &[UgParameter] = &[
UgParameter {
id: "head_final",
question: "Are heads final (the dependent precedes the head)?",
values: &["true", "false"],
},
UgParameter {
id: "pro_drop",
question: "May subject pronouns be omitted (pro-drop)?",
values: &["true", "false"],
},
UgParameter {
id: "wh_movement",
question: "Do question words move to the clause front?",
values: &["true", "false"],
},
UgParameter {
id: "configurational",
question: "Is phrase structure fixed (vs free word order)?",
values: &["true", "false"],
},
UgParameter {
id: "polysynthesis",
question: "Does the verb incorporate its arguments (polysynthesis)?",
values: &["true", "false"],
},
];
pub fn ug_parameter(id: &str) -> Option<&'static UgParameter> {
UG_PARAMETERS.iter().find(|p| p.id.eq_ignore_ascii_case(id))
}
pub const VERB_VALENCES: &[&str] = &["intransitive", "transitive", "ditransitive", "impersonal"];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn catalog_lookup_and_validation() {
assert_eq!(catalog().len(), 22); let wo = feature("word_order").unwrap();
assert!(wo.is_valid("SOV")); assert!(!wo.is_valid("backwards"));
assert!(feature("nonexistent").is_none());
assert!(wo.values().contains("svo"));
assert!(feature("morphological_type").unwrap().is_valid("agglutinative"));
assert!(feature("numeral_order").unwrap().is_valid("noun_first"));
}
}