Rename: nlg → elp (Engram Language Protocol)
This commit is contained in:
@@ -0,0 +1,555 @@
|
||||
// morphology-non.el - Old Norse morphology for the NLG engine.
|
||||
//
|
||||
// Implements Old Norse verb conjugation and noun declension for the ca. 700-1100 CE
|
||||
// period. Designed as a companion to morphology.el and called by the engine when
|
||||
// the language profile code is "non".
|
||||
//
|
||||
// Language profile: code=non, name=Old Norse, morph_type=fusional, word_order=V2,
|
||||
// question_strategy=inversion, script=latin, family=germanic.
|
||||
//
|
||||
// Verb conjugation covered:
|
||||
// Tenses: present, past
|
||||
// Persons: first/second/third x singular/plural (slots 0-5)
|
||||
// Classes: weak (-a infinitive: -aði past), and a set of common strong/irregular verbs
|
||||
// Irregulars: vera (be), hafa (have), ganga (go), sjá (see), segja (say),
|
||||
// koma (come)
|
||||
// Canonical map: "be" -> "vera"
|
||||
//
|
||||
// Noun declension covered:
|
||||
// Strong masculine a-stem (like "armr")
|
||||
// Strong feminine ō-stem (like "gör")
|
||||
// Strong neuter a-stem (like "land")
|
||||
// Cases: nominative, accusative, genitive, dative
|
||||
// Numbers: singular, plural
|
||||
// Definite suffix: appended to the declined form (masc -inn/-ins/-inum, neut -it)
|
||||
//
|
||||
// Depends on: morphology.el (str_ends_with, str_len, str_slice, str_eq)
|
||||
|
||||
// ── String helpers ─────────────────────────────────────────────────────────────
|
||||
|
||||
fn non_str_ends(s: String, suf: String) -> Bool {
|
||||
return str_ends_with(s, suf)
|
||||
}
|
||||
|
||||
fn non_drop(s: String, n: Int) -> String {
|
||||
let len: Int = str_len(s)
|
||||
if n >= len { return "" }
|
||||
return str_slice(s, 0, len - n)
|
||||
}
|
||||
|
||||
fn non_last(s: String) -> String {
|
||||
let n: Int = str_len(s)
|
||||
if n == 0 { return "" }
|
||||
return str_slice(s, n - 1, n)
|
||||
}
|
||||
|
||||
// ── Person/number slot ─────────────────────────────────────────────────────────
|
||||
//
|
||||
// Maps person x number to a 0-based paradigm slot.
|
||||
// 0 = 1st singular (ek)
|
||||
// 1 = 2nd singular (þú)
|
||||
// 2 = 3rd singular (hann/hon/þat)
|
||||
// 3 = 1st plural (vér)
|
||||
// 4 = 2nd plural (þér)
|
||||
// 5 = 3rd plural (þeir/þær/þau)
|
||||
|
||||
fn non_slot(person: String, number: String) -> Int {
|
||||
if str_eq(person, "first") {
|
||||
if str_eq(number, "singular") { return 0 }
|
||||
return 3
|
||||
}
|
||||
if str_eq(person, "second") {
|
||||
if str_eq(number, "singular") { return 1 }
|
||||
return 4
|
||||
}
|
||||
// third
|
||||
if str_eq(number, "singular") { return 2 }
|
||||
return 5
|
||||
}
|
||||
|
||||
// ── Irregular verb tables ──────────────────────────────────────────────────────
|
||||
//
|
||||
// Each irregular verb has a present and past paradigm of six forms (slots 0-5).
|
||||
|
||||
fn non_vera_present(slot: Int) -> String {
|
||||
if slot == 0 { return "em" }
|
||||
if slot == 1 { return "ert" }
|
||||
if slot == 2 { return "er" }
|
||||
if slot == 3 { return "erum" }
|
||||
if slot == 4 { return "eruð" }
|
||||
return "eru"
|
||||
}
|
||||
|
||||
fn non_vera_past(slot: Int) -> String {
|
||||
if slot == 0 { return "var" }
|
||||
if slot == 1 { return "vart" }
|
||||
if slot == 2 { return "var" }
|
||||
if slot == 3 { return "vórum" }
|
||||
if slot == 4 { return "vóruð" }
|
||||
return "vóru"
|
||||
}
|
||||
|
||||
fn non_hafa_present(slot: Int) -> String {
|
||||
if slot == 0 { return "hefi" }
|
||||
if slot == 1 { return "hefr" }
|
||||
if slot == 2 { return "hefr" }
|
||||
if slot == 3 { return "höfum" }
|
||||
if slot == 4 { return "hafið" }
|
||||
return "hafa"
|
||||
}
|
||||
|
||||
fn non_hafa_past(slot: Int) -> String {
|
||||
if slot == 0 { return "hafða" }
|
||||
if slot == 1 { return "hafðir" }
|
||||
if slot == 2 { return "hafði" }
|
||||
if slot == 3 { return "höfðum" }
|
||||
if slot == 4 { return "höfðuð" }
|
||||
return "höfðu"
|
||||
}
|
||||
|
||||
fn non_ganga_present(slot: Int) -> String {
|
||||
if slot == 0 { return "geng" }
|
||||
if slot == 1 { return "gengr" }
|
||||
if slot == 2 { return "gengr" }
|
||||
if slot == 3 { return "göngum" }
|
||||
if slot == 4 { return "gangið" }
|
||||
return "ganga"
|
||||
}
|
||||
|
||||
fn non_ganga_past(slot: Int) -> String {
|
||||
if slot == 0 { return "gekk" }
|
||||
if slot == 1 { return "gekkt" }
|
||||
if slot == 2 { return "gekk" }
|
||||
if slot == 3 { return "gengum" }
|
||||
if slot == 4 { return "genguð" }
|
||||
return "gengu"
|
||||
}
|
||||
|
||||
fn non_sja_present(slot: Int) -> String {
|
||||
if slot == 0 { return "sé" }
|
||||
if slot == 1 { return "sér" }
|
||||
if slot == 2 { return "sér" }
|
||||
if slot == 3 { return "séum" }
|
||||
if slot == 4 { return "séið" }
|
||||
return "sjá"
|
||||
}
|
||||
|
||||
fn non_sja_past(slot: Int) -> String {
|
||||
if slot == 0 { return "sá" }
|
||||
if slot == 1 { return "sást" }
|
||||
if slot == 2 { return "sá" }
|
||||
if slot == 3 { return "sám" }
|
||||
if slot == 4 { return "sáð" }
|
||||
return "sáu"
|
||||
}
|
||||
|
||||
fn non_segja_present(slot: Int) -> String {
|
||||
if slot == 0 { return "segi" }
|
||||
if slot == 1 { return "segir" }
|
||||
if slot == 2 { return "segir" }
|
||||
if slot == 3 { return "segjum" }
|
||||
if slot == 4 { return "segið" }
|
||||
return "segja"
|
||||
}
|
||||
|
||||
fn non_segja_past(slot: Int) -> String {
|
||||
if slot == 0 { return "sagði" }
|
||||
if slot == 1 { return "sagðir" }
|
||||
if slot == 2 { return "sagði" }
|
||||
if slot == 3 { return "sögðum" }
|
||||
if slot == 4 { return "sögðuð" }
|
||||
return "sögðu"
|
||||
}
|
||||
|
||||
fn non_koma_present(slot: Int) -> String {
|
||||
if slot == 0 { return "kem" }
|
||||
if slot == 1 { return "kemr" }
|
||||
if slot == 2 { return "kemr" }
|
||||
if slot == 3 { return "komum" }
|
||||
if slot == 4 { return "komið" }
|
||||
return "koma"
|
||||
}
|
||||
|
||||
fn non_koma_past(slot: Int) -> String {
|
||||
if slot == 0 { return "kom" }
|
||||
if slot == 1 { return "komt" }
|
||||
if slot == 2 { return "kom" }
|
||||
if slot == 3 { return "komum" }
|
||||
if slot == 4 { return "komuð" }
|
||||
return "komu"
|
||||
}
|
||||
|
||||
// ── Canonical verb mapping ─────────────────────────────────────────────────────
|
||||
//
|
||||
// Maps English semantic labels to Old Norse infinitives so the semantic layer
|
||||
// can request forms without knowing the target language lexeme.
|
||||
|
||||
fn non_map_canonical(verb: String) -> String {
|
||||
if str_eq(verb, "be") { return "vera" }
|
||||
if str_eq(verb, "have") { return "hafa" }
|
||||
if str_eq(verb, "go") { return "ganga" }
|
||||
if str_eq(verb, "see") { return "sjá" }
|
||||
if str_eq(verb, "say") { return "segja" }
|
||||
if str_eq(verb, "come") { return "koma" }
|
||||
return verb
|
||||
}
|
||||
|
||||
// ── Weak verb conjugation ──────────────────────────────────────────────────────
|
||||
//
|
||||
// Weak verbs (infinitive ending in -a) form the productive conjugation class.
|
||||
//
|
||||
// Present tense (stem = drop final -a from infinitive):
|
||||
// Sg: 1st stem + -a 2nd stem + -ar 3rd stem + -ar
|
||||
// Pl: 1st stem + -um 2nd stem + -ið 3rd stem + -a
|
||||
//
|
||||
// Past tense (suffix -aði- inserted after stem):
|
||||
// Sg: 1st stem + -aði 2nd stem + -aðir 3rd stem + -aði
|
||||
// Pl: 1st stem + -uðum 2nd stem + -uðuð 3rd stem + -uðu
|
||||
|
||||
fn non_weak_present(stem: String, slot: Int) -> String {
|
||||
if slot == 0 { return stem + "a" }
|
||||
if slot == 1 { return stem + "ar" }
|
||||
if slot == 2 { return stem + "ar" }
|
||||
if slot == 3 { return stem + "um" }
|
||||
if slot == 4 { return stem + "ið" }
|
||||
return stem + "a"
|
||||
}
|
||||
|
||||
fn non_weak_past(stem: String, slot: Int) -> String {
|
||||
if slot == 0 { return stem + "aði" }
|
||||
if slot == 1 { return stem + "aðir" }
|
||||
if slot == 2 { return stem + "aði" }
|
||||
if slot == 3 { return stem + "uðum" }
|
||||
if slot == 4 { return stem + "uðuð" }
|
||||
return stem + "uðu"
|
||||
}
|
||||
|
||||
// ── non_conjugate: main conjugation entry point ───────────────────────────────
|
||||
//
|
||||
// verb: Old Norse infinitive (e.g. "kalla", "vera") or English canonical label
|
||||
// tense: "present" | "past"
|
||||
// person: "first" | "second" | "third"
|
||||
// number: "singular" | "plural"
|
||||
//
|
||||
// Returns the inflected form. Unknown tenses fall back to the infinitive rather
|
||||
// than crashing.
|
||||
|
||||
fn non_conjugate(verb: String, tense: String, person: String, number: String) -> String {
|
||||
let v: String = non_map_canonical(verb)
|
||||
let slot: Int = non_slot(person, number)
|
||||
|
||||
// ── Irregulars ────────────────────────────────────────────────────────────
|
||||
|
||||
if str_eq(v, "vera") {
|
||||
if str_eq(tense, "present") { return non_vera_present(slot) }
|
||||
if str_eq(tense, "past") { return non_vera_past(slot) }
|
||||
return v
|
||||
}
|
||||
|
||||
if str_eq(v, "hafa") {
|
||||
if str_eq(tense, "present") { return non_hafa_present(slot) }
|
||||
if str_eq(tense, "past") { return non_hafa_past(slot) }
|
||||
return v
|
||||
}
|
||||
|
||||
if str_eq(v, "ganga") {
|
||||
if str_eq(tense, "present") { return non_ganga_present(slot) }
|
||||
if str_eq(tense, "past") { return non_ganga_past(slot) }
|
||||
return v
|
||||
}
|
||||
|
||||
if str_eq(v, "sjá") {
|
||||
if str_eq(tense, "present") { return non_sja_present(slot) }
|
||||
if str_eq(tense, "past") { return non_sja_past(slot) }
|
||||
return v
|
||||
}
|
||||
|
||||
if str_eq(v, "segja") {
|
||||
if str_eq(tense, "present") { return non_segja_present(slot) }
|
||||
if str_eq(tense, "past") { return non_segja_past(slot) }
|
||||
return v
|
||||
}
|
||||
|
||||
if str_eq(v, "koma") {
|
||||
if str_eq(tense, "present") { return non_koma_present(slot) }
|
||||
if str_eq(tense, "past") { return non_koma_past(slot) }
|
||||
return v
|
||||
}
|
||||
|
||||
// ── Regular weak verb (-a infinitive) ────────────────────────────────────
|
||||
//
|
||||
// If the verb ends in -a, strip it to get the stem and apply weak endings.
|
||||
// Otherwise fall back to returning the base form unchanged.
|
||||
|
||||
if non_str_ends(v, "a") {
|
||||
let stem: String = non_drop(v, 1)
|
||||
if str_eq(tense, "present") { return non_weak_present(stem, slot) }
|
||||
if str_eq(tense, "past") { return non_weak_past(stem, slot) }
|
||||
return v
|
||||
}
|
||||
|
||||
// Unknown verb form: return the infinitive unchanged
|
||||
return v
|
||||
}
|
||||
|
||||
// ── Strong masculine a-stem declension ("armr" — arm) ─────────────────────────
|
||||
//
|
||||
// The paradigm below uses "armr" as the exemplar. The caller passes the full
|
||||
// nominative singular (including the -r ending); the oblique stem is derived
|
||||
// by stripping -r (or -ur) from the nominative.
|
||||
//
|
||||
// Singular: nom armr acc arm gen arms dat armi
|
||||
// Plural: nom armar acc arma gen arma dat örmum
|
||||
//
|
||||
// The dative plural -örmum involves u-umlaut of the root vowel. Because umlaut
|
||||
// depends on the root vowel in complex ways, the module stores the dative plural
|
||||
// stem separately: for "armr" it is "örm". For unknown nouns we approximatehere
|
||||
// by returning the nominative plural (armar) rather than crashing.
|
||||
|
||||
fn non_decline_masc(noun: String, gram_case: String, number: String) -> String {
|
||||
// Derive oblique stem by dropping the nominative -r ending if present.
|
||||
let stem: String = noun
|
||||
if non_str_ends(noun, "r") {
|
||||
let stem = non_drop(noun, 1)
|
||||
}
|
||||
|
||||
// Hard-code the known exemplar "armr" fully, including the umlauted dat pl.
|
||||
if str_eq(noun, "armr") {
|
||||
if str_eq(number, "singular") {
|
||||
if str_eq(gram_case, "nominative") { return "armr" }
|
||||
if str_eq(gram_case, "accusative") { return "arm" }
|
||||
if str_eq(gram_case, "genitive") { return "arms" }
|
||||
if str_eq(gram_case, "dative") { return "armi" }
|
||||
return "armr"
|
||||
}
|
||||
if str_eq(gram_case, "nominative") { return "armar" }
|
||||
if str_eq(gram_case, "accusative") { return "arma" }
|
||||
if str_eq(gram_case, "genitive") { return "arma" }
|
||||
if str_eq(gram_case, "dative") { return "örmum" }
|
||||
return "armar"
|
||||
}
|
||||
|
||||
// Generic strong masculine a-stem: use stripped stem + endings.
|
||||
// Dative plural umlaut is approximated as nominative plural (safe fallback).
|
||||
if str_eq(number, "singular") {
|
||||
if str_eq(gram_case, "nominative") { return stem + "r" }
|
||||
if str_eq(gram_case, "accusative") { return stem }
|
||||
if str_eq(gram_case, "genitive") { return stem + "s" }
|
||||
if str_eq(gram_case, "dative") { return stem + "i" }
|
||||
return stem + "r"
|
||||
}
|
||||
if str_eq(gram_case, "nominative") { return stem + "ar" }
|
||||
if str_eq(gram_case, "accusative") { return stem + "a" }
|
||||
if str_eq(gram_case, "genitive") { return stem + "a" }
|
||||
if str_eq(gram_case, "dative") { return stem + "um" }
|
||||
return stem + "ar"
|
||||
}
|
||||
|
||||
// ── Strong feminine ō-stem declension ("gör" — gear) ─────────────────────────
|
||||
//
|
||||
// ō-stem feminines have a distinct set of endings. The stem is the nominative
|
||||
// singular form itself (no case suffix in nom sg for this class, though some
|
||||
// nouns add -ar in nom/acc pl).
|
||||
//
|
||||
// Singular: nom gör acc görvar gen görvar dat görvi
|
||||
// Plural: nom görvar acc görvar gen görva dat görvum
|
||||
|
||||
fn non_decline_fem(noun: String, gram_case: String, number: String) -> String {
|
||||
// Use "gör" as the fully specified exemplar.
|
||||
if str_eq(noun, "gör") {
|
||||
if str_eq(number, "singular") {
|
||||
if str_eq(gram_case, "nominative") { return "gör" }
|
||||
if str_eq(gram_case, "accusative") { return "görvar" }
|
||||
if str_eq(gram_case, "genitive") { return "görvar" }
|
||||
if str_eq(gram_case, "dative") { return "görvi" }
|
||||
return "gör"
|
||||
}
|
||||
if str_eq(gram_case, "nominative") { return "görvar" }
|
||||
if str_eq(gram_case, "accusative") { return "görvar" }
|
||||
if str_eq(gram_case, "genitive") { return "görva" }
|
||||
if str_eq(gram_case, "dative") { return "görvum" }
|
||||
return "görvar"
|
||||
}
|
||||
|
||||
// Generic ō-stem feminine: noun base + endings (approximate).
|
||||
if str_eq(number, "singular") {
|
||||
if str_eq(gram_case, "nominative") { return noun }
|
||||
if str_eq(gram_case, "accusative") { return noun + "var" }
|
||||
if str_eq(gram_case, "genitive") { return noun + "var" }
|
||||
if str_eq(gram_case, "dative") { return noun + "vi" }
|
||||
return noun
|
||||
}
|
||||
if str_eq(gram_case, "nominative") { return noun + "var" }
|
||||
if str_eq(gram_case, "accusative") { return noun + "var" }
|
||||
if str_eq(gram_case, "genitive") { return noun + "va" }
|
||||
if str_eq(gram_case, "dative") { return noun + "vum" }
|
||||
return noun + "var"
|
||||
}
|
||||
|
||||
// ── Strong neuter a-stem declension ("land" — land) ──────────────────────────
|
||||
//
|
||||
// Neuter a-stems show no ending in nom/acc sg and u-umlaut in the dative plural.
|
||||
//
|
||||
// Singular: nom land acc land gen lands dat landi
|
||||
// Plural: nom lönd acc lönd gen landa dat löndum
|
||||
|
||||
fn non_decline_neut(noun: String, gram_case: String, number: String) -> String {
|
||||
if str_eq(noun, "land") {
|
||||
if str_eq(number, "singular") {
|
||||
if str_eq(gram_case, "nominative") { return "land" }
|
||||
if str_eq(gram_case, "accusative") { return "land" }
|
||||
if str_eq(gram_case, "genitive") { return "lands" }
|
||||
if str_eq(gram_case, "dative") { return "landi" }
|
||||
return "land"
|
||||
}
|
||||
if str_eq(gram_case, "nominative") { return "lönd" }
|
||||
if str_eq(gram_case, "accusative") { return "lönd" }
|
||||
if str_eq(gram_case, "genitive") { return "landa" }
|
||||
if str_eq(gram_case, "dative") { return "löndum" }
|
||||
return "lönd"
|
||||
}
|
||||
|
||||
// Generic strong neuter a-stem (no umlaut approximated — falls back to base).
|
||||
if str_eq(number, "singular") {
|
||||
if str_eq(gram_case, "nominative") { return noun }
|
||||
if str_eq(gram_case, "accusative") { return noun }
|
||||
if str_eq(gram_case, "genitive") { return noun + "s" }
|
||||
if str_eq(gram_case, "dative") { return noun + "i" }
|
||||
return noun
|
||||
}
|
||||
if str_eq(gram_case, "nominative") { return noun }
|
||||
if str_eq(gram_case, "accusative") { return noun }
|
||||
if str_eq(gram_case, "genitive") { return noun + "a" }
|
||||
if str_eq(gram_case, "dative") { return noun + "um" }
|
||||
return noun
|
||||
}
|
||||
|
||||
// ── Gender detection heuristic ─────────────────────────────────────────────────
|
||||
//
|
||||
// Old Norse gender must ideally be supplied by the lexicon. As a heuristic:
|
||||
// ends in -r (after removing) and root looks consonant-final -> masculine
|
||||
// ends in no case suffix (just the root vowel) -> try feminine
|
||||
// monosyllabic root without final r -> neuter
|
||||
//
|
||||
// The module uses a simplified approach: known exemplars are routed to their
|
||||
// specific paradigm; everything else defaults to strong masculine.
|
||||
|
||||
fn non_detect_gender(noun: String) -> String {
|
||||
if str_eq(noun, "land") { return "neuter" }
|
||||
if str_eq(noun, "gör") { return "feminine" }
|
||||
// Default: masculine
|
||||
return "masculine"
|
||||
}
|
||||
|
||||
// ── non_decline: main declension entry point ──────────────────────────────────
|
||||
//
|
||||
// noun: nominative singular Old Norse noun (e.g. "armr", "land", "gör")
|
||||
// gram_case: "nominative" | "accusative" | "genitive" | "dative"
|
||||
// number: "singular" | "plural"
|
||||
//
|
||||
// Returns the inflected form. Falls back to nominative singular on unknown input.
|
||||
|
||||
fn non_decline(noun: String, gram_case: String, number: String) -> String {
|
||||
let gender: String = non_detect_gender(noun)
|
||||
|
||||
if str_eq(gender, "masculine") { return non_decline_masc(noun, gram_case, number) }
|
||||
if str_eq(gender, "feminine") { return non_decline_fem(noun, gram_case, number) }
|
||||
if str_eq(gender, "neuter") { return non_decline_neut(noun, gram_case, number) }
|
||||
|
||||
// Fallback
|
||||
return noun
|
||||
}
|
||||
|
||||
// ── Definite suffix table ──────────────────────────────────────────────────────
|
||||
//
|
||||
// Old Norse expresses definiteness via a suffix enclitic attached to the end of
|
||||
// the inflected noun form (not a separate article). The suffix agrees with gender
|
||||
// and case.
|
||||
//
|
||||
// Masculine singular: nom -inn gen -ins dat -inum acc -inn
|
||||
// Neuter singular: nom -it gen -ins dat -inu acc -it
|
||||
// Feminine singular: nom -in gen -innar dat -inni acc -ina
|
||||
// Plural (all genders): nom/acc -inir (masc), -in (neut), -inar (fem)
|
||||
// — simplified to -in for plural in this module.
|
||||
|
||||
fn non_def_suffix_masc(gram_case: String, number: String) -> String {
|
||||
if str_eq(number, "singular") {
|
||||
if str_eq(gram_case, "nominative") { return "inn" }
|
||||
if str_eq(gram_case, "genitive") { return "ins" }
|
||||
if str_eq(gram_case, "dative") { return "inum" }
|
||||
if str_eq(gram_case, "accusative") { return "inn" }
|
||||
return "inn"
|
||||
}
|
||||
// plural
|
||||
if str_eq(gram_case, "nominative") { return "inir" }
|
||||
if str_eq(gram_case, "accusative") { return "ina" }
|
||||
if str_eq(gram_case, "genitive") { return "anna" }
|
||||
if str_eq(gram_case, "dative") { return "unum" }
|
||||
return "inir"
|
||||
}
|
||||
|
||||
fn non_def_suffix_neut(gram_case: String, number: String) -> String {
|
||||
if str_eq(number, "singular") {
|
||||
if str_eq(gram_case, "nominative") { return "it" }
|
||||
if str_eq(gram_case, "genitive") { return "ins" }
|
||||
if str_eq(gram_case, "dative") { return "inu" }
|
||||
if str_eq(gram_case, "accusative") { return "it" }
|
||||
return "it"
|
||||
}
|
||||
// plural
|
||||
if str_eq(gram_case, "nominative") { return "in" }
|
||||
if str_eq(gram_case, "accusative") { return "in" }
|
||||
if str_eq(gram_case, "genitive") { return "anna" }
|
||||
if str_eq(gram_case, "dative") { return "unum" }
|
||||
return "in"
|
||||
}
|
||||
|
||||
fn non_def_suffix_fem(gram_case: String, number: String) -> String {
|
||||
if str_eq(number, "singular") {
|
||||
if str_eq(gram_case, "nominative") { return "in" }
|
||||
if str_eq(gram_case, "genitive") { return "innar" }
|
||||
if str_eq(gram_case, "dative") { return "inni" }
|
||||
if str_eq(gram_case, "accusative") { return "ina" }
|
||||
return "in"
|
||||
}
|
||||
// plural
|
||||
if str_eq(gram_case, "nominative") { return "inar" }
|
||||
if str_eq(gram_case, "accusative") { return "inar" }
|
||||
if str_eq(gram_case, "genitive") { return "anna" }
|
||||
if str_eq(gram_case, "dative") { return "innar" }
|
||||
return "inar"
|
||||
}
|
||||
|
||||
// ── non_noun_phrase: noun phrase builder ──────────────────────────────────────
|
||||
//
|
||||
// Old Norse definiteness is expressed through a suffix enclitic, not a separate
|
||||
// article. For indefinite nouns the declined form is returned as-is.
|
||||
//
|
||||
// noun: nominative singular Old Norse noun (e.g. "armr", "land")
|
||||
// gram_case: "nominative" | "accusative" | "genitive" | "dative"
|
||||
// number: "singular" | "plural"
|
||||
// definite: "true" | "false" (string comparison)
|
||||
//
|
||||
// Returns the complete noun phrase string.
|
||||
|
||||
fn non_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String {
|
||||
let base: String = non_decline(noun, gram_case, number)
|
||||
|
||||
if !str_eq(definite, "true") { return base }
|
||||
|
||||
// Append the appropriate definite suffix.
|
||||
let gender: String = non_detect_gender(noun)
|
||||
|
||||
if str_eq(gender, "masculine") {
|
||||
return base + non_def_suffix_masc(gram_case, number)
|
||||
}
|
||||
if str_eq(gender, "neuter") {
|
||||
return base + non_def_suffix_neut(gram_case, number)
|
||||
}
|
||||
if str_eq(gender, "feminine") {
|
||||
return base + non_def_suffix_fem(gram_case, number)
|
||||
}
|
||||
|
||||
// Fallback: append generic -inn
|
||||
return base + "inn"
|
||||
}
|
||||
Reference in New Issue
Block a user