// morphology-grc.el - Ancient Greek morphology for the NLG engine. // // Implements polytonic Ancient Greek verb conjugation, noun declension, and // the definite article. Designed as a companion to morphology.el and called // by the engine when the language profile code is "grc". // // Language profile: code=grc, name=Ancient Greek, morph_type=fusional, // word_order=SOV, question_strategy=particle, script=greek, family=hellenic. // // Typology note: Ancient Greek is a heavily inflected synthetic language with // rich morphophonology. Nouns carry gender, case, and number in fused endings. // Verbs encode tense, aspect, voice, mood, person, and number. The augment // (ε-) marks past indicative. All polytonic diacritics are preserved in // string literals; comparisons use exact Unicode equality. // // Verb conjugation covered: // Tenses: present, imperfect, aorist, future // Persons: first/second/third × singular/plural (slots 0-5) // Class: thematic (-ω) verbs // Irregulars: εἰναι (be), ἔχειν (have), λέγειν (say), ὁράω (see), // ἔρχεσθαι (come/go) // Canonical map: "be" -> "εἰναι" // // Noun declension covered: // Cases: nominative, accusative, genitive, dative, vocative // Declensions: 1st (-α/-η fem), 2nd masc (-ος), 2nd neut (-ον), 3rd (base) // // Article: full 24-form table for ὁ/ἡ/τό (gender × case × number). // // Depends on: morphology.el (str_ends_with, str_len, str_slice, str_eq) // ── String helpers ───────────────────────────────────────────────────────────── import "morphology.el" fn grc_str_ends(s: String, suf: String) -> Bool { return str_ends_with(s, suf) } fn grc_str_drop_last(s: String, n: Int) -> String { let len: Int = str_len(s) if n >= len { return "" } return str_slice(s, 0, len - n) } fn grc_str_last_char(s: String) -> String { let n: Int = str_len(s) if n == 0 { return "" } return str_slice(s, n - 1, n) } fn grc_str_last2(s: String) -> String { let n: Int = str_len(s) if n < 2 { return s } return str_slice(s, n - 2, n) } fn grc_str_last3(s: String) -> String { let n: Int = str_len(s) if n < 3 { return s } return str_slice(s, n - 3, n) } // ── Person/number slot ───────────────────────────────────────────────────────── // // Maps person × number to a 0-based index used in all paradigm tables. // 0 = 1st singular (ἐγώ) // 1 = 2nd singular (σύ) // 2 = 3rd singular (αὐτός/αὐτή/αὐτό) // 3 = 1st plural (ἡμεῖς) // 4 = 2nd plural (ὑμεῖς) // 5 = 3rd plural (αὐτοί) // // Dual number is not handled; dual inputs fall through to plural. fn grc_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 } // ── Canonical verb mapping ───────────────────────────────────────────────────── // // The semantic layer may pass English canonical labels. Map these to the // Ancient Greek infinitive (or dictionary citation form) before conjugation. fn grc_map_canonical(verb: String) -> String { if str_eq(verb, "be") { return "εἰναι" } if str_eq(verb, "have") { return "ἔχειν" } if str_eq(verb, "say") { return "λέγειν" } if str_eq(verb, "see") { return "ὁράω" } if str_eq(verb, "come") { return "ἔρχεσθαι" } if str_eq(verb, "go") { return "ἔρχεσθαι" } if str_eq(verb, "know") { return "γιγνώσκειν" } if str_eq(verb, "write") { return "γράφειν" } if str_eq(verb, "hear") { return "ἀκούειν" } if str_eq(verb, "want") { return "βούλεσθαι" } if str_eq(verb, "do") { return "ποιεῖν" } if str_eq(verb, "make") { return "ποιεῖν" } return verb } // ── Irregular: εἰναι (to be) ────────────────────────────────────────────────── // // Present indicative active: εἰμί εἶ ἐστί ἐσμέν ἐστέ εἰσί // Imperfect: ἦν ἦσθα ἦν ἦμεν ἦτε ἦσαν // Future: ἔσομαι ἔσῃ ἔσται ἐσόμεθα ἔσεσθε ἔσονται // Aorist: no aorist of εἰμί; use imperfect as fallback fn grc_einai_present(slot: Int) -> String { if slot == 0 { return "εἰμί" } if slot == 1 { return "εἶ" } if slot == 2 { return "ἐστί" } if slot == 3 { return "ἐσμέν" } if slot == 4 { return "ἐστέ" } return "εἰσί" } fn grc_einai_imperfect(slot: Int) -> String { if slot == 0 { return "ἦν" } if slot == 1 { return "ἦσθα" } if slot == 2 { return "ἦν" } if slot == 3 { return "ἦμεν" } if slot == 4 { return "ἦτε" } return "ἦσαν" } fn grc_einai_future(slot: Int) -> String { if slot == 0 { return "ἔσομαι" } if slot == 1 { return "ἔσῃ" } if slot == 2 { return "ἔσται" } if slot == 3 { return "ἐσόμεθα" } if slot == 4 { return "ἔσεσθε" } return "ἔσονται" } // ── Irregular: ἔχειν (to have) ──────────────────────────────────────────────── // // Present: ἔχω ἔχεις ἔχει ἔχομεν ἔχετε ἔχουσι // Imperfect: εἶχον εἶχες εἶχε εἴχομεν εἴχετε εἶχον // Aorist: ἔσχον ἔσχες ἔσχε ἔσχομεν ἔσχετε ἔσχον // Future: ἕξω ἕξεις ἕξει ἕξομεν ἕξετε ἕξουσι fn grc_echein_present(slot: Int) -> String { if slot == 0 { return "ἔχω" } if slot == 1 { return "ἔχεις" } if slot == 2 { return "ἔχει" } if slot == 3 { return "ἔχομεν" } if slot == 4 { return "ἔχετε" } return "ἔχουσι" } fn grc_echein_imperfect(slot: Int) -> String { if slot == 0 { return "εἶχον" } if slot == 1 { return "εἶχες" } if slot == 2 { return "εἶχε" } if slot == 3 { return "εἴχομεν" } if slot == 4 { return "εἴχετε" } return "εἶχον" } fn grc_echein_aorist(slot: Int) -> String { if slot == 0 { return "ἔσχον" } if slot == 1 { return "ἔσχες" } if slot == 2 { return "ἔσχε" } if slot == 3 { return "ἔσχομεν" } if slot == 4 { return "ἔσχετε" } return "ἔσχον" } fn grc_echein_future(slot: Int) -> String { if slot == 0 { return "ἕξω" } if slot == 1 { return "ἕξεις" } if slot == 2 { return "ἕξει" } if slot == 3 { return "ἕξομεν" } if slot == 4 { return "ἕξετε" } return "ἕξουσι" } // ── Irregular: λέγειν (to say) ──────────────────────────────────────────────── // // Present: λέγω λέγεις λέγει λέγομεν λέγετε λέγουσι // Imperfect: ἔλεγον ἔλεγες ἔλεγε ἐλέγομεν ἐλέγετε ἔλεγον // Aorist: εἶπον εἶπες εἶπε εἴπομεν εἴπετε εἶπον // Future: λέξω λέξεις λέξει λέξομεν λέξετε λέξουσι fn grc_legein_present(slot: Int) -> String { if slot == 0 { return "λέγω" } if slot == 1 { return "λέγεις" } if slot == 2 { return "λέγει" } if slot == 3 { return "λέγομεν" } if slot == 4 { return "λέγετε" } return "λέγουσι" } fn grc_legein_imperfect(slot: Int) -> String { if slot == 0 { return "ἔλεγον" } if slot == 1 { return "ἔλεγες" } if slot == 2 { return "ἔλεγε" } if slot == 3 { return "ἐλέγομεν" } if slot == 4 { return "ἐλέγετε" } return "ἔλεγον" } fn grc_legein_aorist(slot: Int) -> String { if slot == 0 { return "εἶπον" } if slot == 1 { return "εἶπες" } if slot == 2 { return "εἶπε" } if slot == 3 { return "εἴπομεν" } if slot == 4 { return "εἴπετε" } return "εἶπον" } fn grc_legein_future(slot: Int) -> String { if slot == 0 { return "λέξω" } if slot == 1 { return "λέξεις" } if slot == 2 { return "λέξει" } if slot == 3 { return "λέξομεν" } if slot == 4 { return "λέξετε" } return "λέξουσι" } // ── Irregular: ὁράω (to see) ────────────────────────────────────────────────── // // Present: ὁράω ὁράς ὁρᾷ ὁρῶμεν ὁρᾶτε ὁρῶσι // Imperfect: ἑώρων ἑώρας ἑώρα ἑωρῶμεν ἑωρᾶτε ἑώρων // Aorist: εἶδον εἶδες εἶδε εἴδομεν εἴδετε εἶδον // Future: ὄψομαι ὄψῃ ὄψεται ὀψόμεθα ὄψεσθε ὄψονται fn grc_horao_present(slot: Int) -> String { if slot == 0 { return "ὁράω" } if slot == 1 { return "ὁράς" } if slot == 2 { return "ὁρᾷ" } if slot == 3 { return "ὁρῶμεν" } if slot == 4 { return "ὁρᾶτε" } return "ὁρῶσι" } fn grc_horao_imperfect(slot: Int) -> String { if slot == 0 { return "ἑώρων" } if slot == 1 { return "ἑώρας" } if slot == 2 { return "ἑώρα" } if slot == 3 { return "ἑωρῶμεν" } if slot == 4 { return "ἑωρᾶτε" } return "ἑώρων" } fn grc_horao_aorist(slot: Int) -> String { if slot == 0 { return "εἶδον" } if slot == 1 { return "εἶδες" } if slot == 2 { return "εἶδε" } if slot == 3 { return "εἴδομεν" } if slot == 4 { return "εἴδετε" } return "εἶδον" } fn grc_horao_future(slot: Int) -> String { if slot == 0 { return "ὄψομαι" } if slot == 1 { return "ὄψῃ" } if slot == 2 { return "ὄψεται" } if slot == 3 { return "ὀψόμεθα" } if slot == 4 { return "ὄψεσθε" } return "ὄψονται" } // ── Irregular: ἔρχεσθαι (to come / to go) ──────────────────────────────────── // // Present: ἔρχομαι ἔρχῃ ἔρχεται ἐρχόμεθα ἔρχεσθε ἔρχονται // Imperfect: ἠρχόμην ἤρχου ἤρχετο ἠρχόμεθα ἤρχεσθε ἤρχοντο // Aorist: ἦλθον ἦλθες ἦλθε ἤλθομεν ἤλθετε ἦλθον // Future: εἶμι εἶ εἶσι ἴμεν ἴτε ἴασι fn grc_erchesthai_present(slot: Int) -> String { if slot == 0 { return "ἔρχομαι" } if slot == 1 { return "ἔρχῃ" } if slot == 2 { return "ἔρχεται" } if slot == 3 { return "ἐρχόμεθα" } if slot == 4 { return "ἔρχεσθε" } return "ἔρχονται" } fn grc_erchesthai_imperfect(slot: Int) -> String { if slot == 0 { return "ἠρχόμην" } if slot == 1 { return "ἤρχου" } if slot == 2 { return "ἤρχετο" } if slot == 3 { return "ἠρχόμεθα" } if slot == 4 { return "ἤρχεσθε" } return "ἤρχοντο" } fn grc_erchesthai_aorist(slot: Int) -> String { if slot == 0 { return "ἦλθον" } if slot == 1 { return "ἦλθες" } if slot == 2 { return "ἦλθε" } if slot == 3 { return "ἤλθομεν" } if slot == 4 { return "ἤλθετε" } return "ἦλθον" } fn grc_erchesthai_future(slot: Int) -> String { if slot == 0 { return "εἶμι" } if slot == 1 { return "εἶ" } if slot == 2 { return "εἶσι" } if slot == 3 { return "ἴμεν" } if slot == 4 { return "ἴτε" } return "ἴασι" } // ── Thematic (-ω) present active endings ────────────────────────────────────── // // Slot: 0 1 2 3 4 5 // -ω -εις -ει -ομεν -ετε -ουσι // // These are attached to the present stem. fn grc_thematic_present_ending(slot: Int) -> String { if slot == 0 { return "ω" } if slot == 1 { return "εις" } if slot == 2 { return "ει" } if slot == 3 { return "ομεν" } if slot == 4 { return "ετε" } return "ουσι" } // ── Thematic imperfect active endings ───────────────────────────────────────── // // Imperfect = augment (ἐ-) + stem + secondary endings // Slot: 0 1 2 3 4 5 // -ον -ες -ε -ομεν -ετε -ον fn grc_thematic_imperfect_ending(slot: Int) -> String { if slot == 0 { return "ον" } if slot == 1 { return "ες" } if slot == 2 { return "ε" } if slot == 3 { return "ομεν" } if slot == 4 { return "ετε" } return "ον" } // ── Thematic future active endings ──────────────────────────────────────────── // // Future = stem + σ + thematic vowel + primary endings. // For most -ω verbs: stem + σ serves as the future stem, then present endings. // Slot: 0 1 2 3 4 5 // -σω -σεις -σει -σομεν -σετε -σουσι fn grc_thematic_future_ending(slot: Int) -> String { if slot == 0 { return "σω" } if slot == 1 { return "σεις" } if slot == 2 { return "σει" } if slot == 3 { return "σομεν" } if slot == 4 { return "σετε" } return "σουσι" } // ── Weak (first) aorist active endings ──────────────────────────────────────── // // Weak aorist = augment (ἐ-) + stem + σ + aorist endings // Slot: 0 1 2 3 4 5 // -σα -σας -σε -σαμεν -σατε -σαν fn grc_weak_aorist_ending(slot: Int) -> String { if slot == 0 { return "σα" } if slot == 1 { return "σας" } if slot == 2 { return "σε" } if slot == 3 { return "σαμεν" } if slot == 4 { return "σατε" } return "σαν" } // ── Stem extraction ──────────────────────────────────────────────────────────── // // Strip the citation-form ending to recover the present stem. // -ειν -> strip 3 chars (λύειν -> λύ-) // -ω -> strip 1 char (λύω -> λύ-) // -αω -> strip 2 chars (ὁράω -> ὁρ-; handled as irregular above) // -εω -> strip 2 chars (contracted -εω verbs) // otherwise: return as-is (already a stem or unrecognised form) fn grc_present_stem(verb: String) -> String { if grc_str_ends(verb, "ειν") { return grc_str_drop_last(verb, 3) } if grc_str_ends(verb, "αω") { return grc_str_drop_last(verb, 2) } if grc_str_ends(verb, "εω") { return grc_str_drop_last(verb, 2) } if grc_str_ends(verb, "ω") { return grc_str_drop_last(verb, 1) } return verb } // ── grc_conjugate: main conjugation entry point ─────────────────────────────── // // verb: Greek infinitive/citation form or English canonical label // tense: "present" | "imperfect" | "aorist" | "future" // person: "first" | "second" | "third" // number: "singular" | "plural" // // Returns the inflected form. Falls back to the citation form for unknown // tenses or unrecognised verbs rather than crashing. fn grc_conjugate(verb: String, tense: String, person: String, number: String) -> String { let v: String = grc_map_canonical(verb) let slot: Int = grc_slot(person, number) // ── Irregulars ──────────────────────────────────────────────────────────── if str_eq(v, "εἰναι") { if str_eq(tense, "present") { return grc_einai_present(slot) } if str_eq(tense, "imperfect") { return grc_einai_imperfect(slot) } if str_eq(tense, "aorist") { return grc_einai_imperfect(slot) } if str_eq(tense, "future") { return grc_einai_future(slot) } return v } if str_eq(v, "ἔχειν") { if str_eq(tense, "present") { return grc_echein_present(slot) } if str_eq(tense, "imperfect") { return grc_echein_imperfect(slot) } if str_eq(tense, "aorist") { return grc_echein_aorist(slot) } if str_eq(tense, "future") { return grc_echein_future(slot) } return v } if str_eq(v, "λέγειν") { if str_eq(tense, "present") { return grc_legein_present(slot) } if str_eq(tense, "imperfect") { return grc_legein_imperfect(slot) } if str_eq(tense, "aorist") { return grc_legein_aorist(slot) } if str_eq(tense, "future") { return grc_legein_future(slot) } return v } if str_eq(v, "ὁράω") { if str_eq(tense, "present") { return grc_horao_present(slot) } if str_eq(tense, "imperfect") { return grc_horao_imperfect(slot) } if str_eq(tense, "aorist") { return grc_horao_aorist(slot) } if str_eq(tense, "future") { return grc_horao_future(slot) } return v } if str_eq(v, "ἔρχεσθαι") { if str_eq(tense, "present") { return grc_erchesthai_present(slot) } if str_eq(tense, "imperfect") { return grc_erchesthai_imperfect(slot) } if str_eq(tense, "aorist") { return grc_erchesthai_aorist(slot) } if str_eq(tense, "future") { return grc_erchesthai_future(slot) } return v } // ── Regular thematic conjugation ────────────────────────────────────────── let stem: String = grc_present_stem(v) if str_eq(tense, "present") { return stem + grc_thematic_present_ending(slot) } if str_eq(tense, "imperfect") { // Augment: prefix ἐ- to the stem return "ἐ" + stem + grc_thematic_imperfect_ending(slot) } if str_eq(tense, "future") { return stem + grc_thematic_future_ending(slot) } if str_eq(tense, "aorist") { // Weak (sigmatic) aorist: ἐ- + stem + σ endings return "ἐ" + stem + grc_weak_aorist_ending(slot) } // Unknown tense: return citation form unchanged return v } // ── Declension detection ─────────────────────────────────────────────────────── // // Infer Greek declension class from the nominative singular ending. // // ends in -ος -> 2nd declension masculine // ends in -ον -> 2nd declension neuter // ends in -α -> 1st declension feminine (alpha-stem) // ends in -η -> 1st declension feminine (eta-stem) // otherwise -> 3rd declension (consonant stem; too varied for full tables) fn grc_declension(noun: String) -> String { if grc_str_ends(noun, "ος") { return "2m" } if grc_str_ends(noun, "ον") { return "2n" } if grc_str_ends(noun, "α") { return "1a" } if grc_str_ends(noun, "η") { return "1e" } return "3" } // ── 2nd declension masculine: -ος nouns ────────────────────────────────────── // // Stem: remove -ος (2 chars) // Singular: nom -ος gen -ου dat -ῳ acc -ον voc -ε // Plural: nom -οι gen -ων dat -οις acc -ους voc -οι fn grc_decline_2m(stem: String, gram_case: String, number: String) -> String { if str_eq(number, "singular") { if str_eq(gram_case, "nominative") { return stem + "ος" } if str_eq(gram_case, "genitive") { return stem + "ου" } if str_eq(gram_case, "dative") { return stem + "ῳ" } if str_eq(gram_case, "accusative") { return stem + "ον" } if str_eq(gram_case, "vocative") { return stem + "ε" } return stem + "ος" } // plural if str_eq(gram_case, "nominative") { return stem + "οι" } if str_eq(gram_case, "genitive") { return stem + "ων" } if str_eq(gram_case, "dative") { return stem + "οις" } if str_eq(gram_case, "accusative") { return stem + "ους" } if str_eq(gram_case, "vocative") { return stem + "οι" } return stem + "οι" } // ── 2nd declension neuter: -ον nouns ───────────────────────────────────────── // // Stem: remove -ον (2 chars) // Singular: nom/acc/voc -ον gen -ου dat -ῳ // Plural: nom/acc/voc -α gen -ων dat -οις fn grc_decline_2n(stem: String, gram_case: String, number: String) -> String { if str_eq(number, "singular") { if str_eq(gram_case, "nominative") { return stem + "ον" } if str_eq(gram_case, "genitive") { return stem + "ου" } if str_eq(gram_case, "dative") { return stem + "ῳ" } if str_eq(gram_case, "accusative") { return stem + "ον" } if str_eq(gram_case, "vocative") { return stem + "ον" } return stem + "ον" } // plural if str_eq(gram_case, "nominative") { return stem + "α" } if str_eq(gram_case, "genitive") { return stem + "ων" } if str_eq(gram_case, "dative") { return stem + "οις" } if str_eq(gram_case, "accusative") { return stem + "α" } if str_eq(gram_case, "vocative") { return stem + "α" } return stem + "α" } // ── 1st declension feminine: alpha-stem (-α) nouns ─────────────────────────── // // Stem: remove -α (1 char) // Singular: nom -α gen -ας dat -ᾳ acc -αν voc -α // Plural: nom -αι gen -ων dat -αις acc -ας voc -αι fn grc_decline_1a(stem: String, gram_case: String, number: String) -> String { if str_eq(number, "singular") { if str_eq(gram_case, "nominative") { return stem + "α" } if str_eq(gram_case, "genitive") { return stem + "ας" } if str_eq(gram_case, "dative") { return stem + "ᾳ" } if str_eq(gram_case, "accusative") { return stem + "αν" } if str_eq(gram_case, "vocative") { return stem + "α" } return stem + "α" } // plural if str_eq(gram_case, "nominative") { return stem + "αι" } if str_eq(gram_case, "genitive") { return stem + "ων" } if str_eq(gram_case, "dative") { return stem + "αις" } if str_eq(gram_case, "accusative") { return stem + "ας" } if str_eq(gram_case, "vocative") { return stem + "αι" } return stem + "αι" } // ── 1st declension feminine: eta-stem (-η) nouns ───────────────────────────── // // Stem: remove -η (1 char) // Singular: nom -η gen -ης dat -ῃ acc -ην voc -η // Plural: nom -αι gen -ων dat -αις acc -ας voc -αι fn grc_decline_1e(stem: String, gram_case: String, number: String) -> String { if str_eq(number, "singular") { if str_eq(gram_case, "nominative") { return stem + "η" } if str_eq(gram_case, "genitive") { return stem + "ης" } if str_eq(gram_case, "dative") { return stem + "ῃ" } if str_eq(gram_case, "accusative") { return stem + "ην" } if str_eq(gram_case, "vocative") { return stem + "η" } return stem + "η" } // plural (same as alpha-stem in the plural) if str_eq(gram_case, "nominative") { return stem + "αι" } if str_eq(gram_case, "genitive") { return stem + "ων" } if str_eq(gram_case, "dative") { return stem + "αις" } if str_eq(gram_case, "accusative") { return stem + "ας" } if str_eq(gram_case, "vocative") { return stem + "αι" } return stem + "αι" } // ── grc_decline: main declension entry point ────────────────────────────────── // // noun: nominative singular Greek noun (e.g. "λόγος", "ἔργον", "χώρα") // gram_case: "nominative" | "accusative" | "genitive" | "dative" | "vocative" // number: "singular" | "plural" // // 3rd declension consonant stems are too unpredictable without a full lexicon; // for those the nominative is returned unchanged as a safe fallback. fn grc_decline(noun: String, gram_case: String, number: String) -> String { let decl: String = grc_declension(noun) if str_eq(decl, "2m") { let stem: String = grc_str_drop_last(noun, 2) return grc_decline_2m(stem, gram_case, number) } if str_eq(decl, "2n") { let stem: String = grc_str_drop_last(noun, 2) return grc_decline_2n(stem, gram_case, number) } if str_eq(decl, "1a") { let stem: String = grc_str_drop_last(noun, 1) return grc_decline_1a(stem, gram_case, number) } if str_eq(decl, "1e") { let stem: String = grc_str_drop_last(noun, 1) return grc_decline_1e(stem, gram_case, number) } // 3rd declension: return the base form unchanged return noun } // ── grc_article: definite article ──────────────────────────────────────────── // // The Ancient Greek definite article ὁ/ἡ/τό is fully declined for gender, // case, and number. There is no indefinite article. // // gender: "masculine" | "feminine" | "neuter" // gram_case: "nominative" | "accusative" | "genitive" | "dative" | "vocative" // number: "singular" | "plural" // // Masc Fem Neut // Nom sg: ὁ ἡ τό // Gen sg: τοῦ τῆς τοῦ // Dat sg: τῷ τῇ τῷ // Acc sg: τόν τήν τό // Voc sg: (none; ὦ used as exclamatory particle, not article) // Nom pl: οἱ αἱ τά // Gen pl: τῶν τῶν τῶν // Dat pl: τοῖς ταῖς τοῖς // Acc pl: τούς τάς τά // Voc pl: (same as nom pl in practice) fn grc_article_masculine(gram_case: String, number: String) -> String { if str_eq(number, "singular") { if str_eq(gram_case, "nominative") { return "ὁ" } if str_eq(gram_case, "genitive") { return "τοῦ" } if str_eq(gram_case, "dative") { return "τῷ" } if str_eq(gram_case, "accusative") { return "τόν" } if str_eq(gram_case, "vocative") { return "ὁ" } return "ὁ" } // plural if str_eq(gram_case, "nominative") { return "οἱ" } if str_eq(gram_case, "genitive") { return "τῶν" } if str_eq(gram_case, "dative") { return "τοῖς" } if str_eq(gram_case, "accusative") { return "τούς" } if str_eq(gram_case, "vocative") { return "οἱ" } return "οἱ" } fn grc_article_feminine(gram_case: String, number: String) -> String { if str_eq(number, "singular") { if str_eq(gram_case, "nominative") { return "ἡ" } if str_eq(gram_case, "genitive") { return "τῆς" } if str_eq(gram_case, "dative") { return "τῇ" } if str_eq(gram_case, "accusative") { return "τήν" } if str_eq(gram_case, "vocative") { return "ἡ" } return "ἡ" } // plural if str_eq(gram_case, "nominative") { return "αἱ" } if str_eq(gram_case, "genitive") { return "τῶν" } if str_eq(gram_case, "dative") { return "ταῖς" } if str_eq(gram_case, "accusative") { return "τάς" } if str_eq(gram_case, "vocative") { return "αἱ" } return "αἱ" } fn grc_article_neuter(gram_case: String, number: String) -> String { if str_eq(number, "singular") { if str_eq(gram_case, "nominative") { return "τό" } if str_eq(gram_case, "genitive") { return "τοῦ" } if str_eq(gram_case, "dative") { return "τῷ" } if str_eq(gram_case, "accusative") { return "τό" } if str_eq(gram_case, "vocative") { return "τό" } return "τό" } // plural if str_eq(gram_case, "nominative") { return "τά" } if str_eq(gram_case, "genitive") { return "τῶν" } if str_eq(gram_case, "dative") { return "τοῖς" } if str_eq(gram_case, "accusative") { return "τά" } if str_eq(gram_case, "vocative") { return "τά" } return "τά" } fn grc_article(gender: String, gram_case: String, number: String) -> String { if str_eq(gender, "masculine") { return grc_article_masculine(gram_case, number) } if str_eq(gender, "feminine") { return grc_article_feminine(gram_case, number) } // neuter return grc_article_neuter(gram_case, number) } // ── Infer gender from noun ending ───────────────────────────────────────────── // // Used by grc_noun_phrase when no explicit gender is provided. // -ος -> masculine (default 2nd), -ον -> neuter, -α/-η -> feminine. fn grc_infer_gender(noun: String) -> String { if grc_str_ends(noun, "ος") { return "masculine" } if grc_str_ends(noun, "ον") { return "neuter" } if grc_str_ends(noun, "α") { return "feminine" } if grc_str_ends(noun, "η") { return "feminine" } return "masculine" } // ── grc_noun_phrase: noun phrase builder ────────────────────────────────────── // // Produces a declined noun with optional definite article prepended. // Gender is inferred from the noun ending when not supplied explicitly. // // noun: nominative singular Greek noun // gram_case: "nominative" | "accusative" | "genitive" | "dative" | "vocative" // number: "singular" | "plural" // definite: "true" | "false" (article is prepended when "true") fn grc_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String { let declined: String = grc_decline(noun, gram_case, number) if str_eq(definite, "true") { let gender: String = grc_infer_gender(noun) let art: String = grc_article(gender, gram_case, number) return art + " " + declined } return declined }