c2cd5e01e1
El SDK CI - dev / build-and-test (pull_request) Successful in 3m34s
elb.el: - Auto-detect Homebrew OpenSSL (-L$(brew --prefix openssl)/lib) so -lssl resolves on macOS without manual flags; no-op on Linux - Add -include elp-c-decls.h when present in out_dir: resolves undeclared cross-module calls in packages like ELP that lack explicit imports ELP source: - Add import "morphology.el" to all 29 language morphology modules - Add language module imports to morphology.el (all langs it dispatches to) These were missing since ELP was originally built as a monolithic unit
547 lines
21 KiB
EmacsLisp
547 lines
21 KiB
EmacsLisp
// morphology-pi.el - Pali morphology for the NLG engine.
|
|
//
|
|
// Implements Pali verb conjugation and noun declension using standard IAST-subset
|
|
// Latin transliteration. Pali is the liturgical language of Theravada Buddhism
|
|
// (canonical form of Middle Indo-Aryan, ca. 3rd century BCE).
|
|
//
|
|
// Language profile: code=pi, name=Pali, morph_type=fusional, word_order=SOV,
|
|
// question_strategy=particle, script=latin-iast, family=indo-aryan.
|
|
//
|
|
// Verb conjugation covered:
|
|
// Tenses: present (bhū-ādi class), aorist (past), future
|
|
// Persons: first/second/third x singular/plural (slots 0-5)
|
|
// Endings: present -āmi/-asi/-ati/-āma/-atha/-anti
|
|
// aorist -iṃ/-i/-i/-imhā/-ittha/-iṃsu
|
|
// future -issāmi/-issasi/-issati/-issāma/-issatha/-issanti
|
|
// Irregulars: atthi/hoti (be), gacchati (go), passati (see),
|
|
// vadati (say), karoti (do)
|
|
// Canonical map: "be" -> "hoti"
|
|
//
|
|
// Noun declension covered:
|
|
// a-stem masculine (paradigm: "purisa" — man): 8 cases, sg + pl
|
|
// ā-stem feminine (paradigm: "kaññā" — girl): 8 cases, sg (pl approx.)
|
|
// Cases: nominative, accusative, instrumental, dative, ablative,
|
|
// genitive, locative, vocative
|
|
//
|
|
// Articles:
|
|
// Pali has no articles. pi_noun_phrase returns the declined noun directly.
|
|
//
|
|
// Depends on: morphology.el (str_ends_with, str_len, str_slice, str_eq)
|
|
|
|
// ── String helpers ─────────────────────────────────────────────────────────────
|
|
|
|
import "morphology.el"
|
|
fn pi_str_ends(s: String, suf: String) -> Bool {
|
|
return str_ends_with(s, suf)
|
|
}
|
|
|
|
fn pi_drop(s: String, n: Int) -> String {
|
|
let len: Int = str_len(s)
|
|
if n >= len { return "" }
|
|
return str_slice(s, 0, len - n)
|
|
}
|
|
|
|
fn pi_last_char(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 (ahaṃ)
|
|
// 1 = 2nd singular (tvaṃ)
|
|
// 2 = 3rd singular (so/sā/taṃ)
|
|
// 3 = 1st plural (mayaṃ)
|
|
// 4 = 2nd plural (tumhe)
|
|
// 5 = 3rd plural (te/tā/tāni)
|
|
|
|
fn pi_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
|
|
}
|
|
|
|
// ── Present tense endings (bhū-ādi class) ─────────────────────────────────────
|
|
//
|
|
// The standard present active endings for the most common Pali verb class:
|
|
// 1sg -āmi 2sg -asi 3sg -ati
|
|
// 1pl -āma 2pl -atha 3pl -anti
|
|
|
|
fn pi_present_ending(slot: Int) -> String {
|
|
if slot == 0 { return "āmi" }
|
|
if slot == 1 { return "asi" }
|
|
if slot == 2 { return "ati" }
|
|
if slot == 3 { return "āma" }
|
|
if slot == 4 { return "atha" }
|
|
return "anti"
|
|
}
|
|
|
|
// ── Aorist (past) tense endings ───────────────────────────────────────────────
|
|
//
|
|
// The Pali aorist is the standard simple past. The most common set:
|
|
// 1sg -iṃ 2sg -i 3sg -i
|
|
// 1pl -imhā 2pl -ittha 3pl -iṃsu
|
|
//
|
|
// These are appended to the verb root (or a modified stem). For regular
|
|
// weak aorists, the root is taken from the infinitive by stripping -ati.
|
|
|
|
fn pi_aorist_ending(slot: Int) -> String {
|
|
if slot == 0 { return "iṃ" }
|
|
if slot == 1 { return "i" }
|
|
if slot == 2 { return "i" }
|
|
if slot == 3 { return "imhā" }
|
|
if slot == 4 { return "ittha" }
|
|
return "iṃsu"
|
|
}
|
|
|
|
// ── Future tense endings ───────────────────────────────────────────────────────
|
|
//
|
|
// Future is formed with the suffix -issa- inserted between root and personal ending:
|
|
// 1sg -issāmi 2sg -issasi 3sg -issati
|
|
// 1pl -issāma 2pl -issatha 3pl -issanti
|
|
|
|
fn pi_future_ending(slot: Int) -> String {
|
|
if slot == 0 { return "issāmi" }
|
|
if slot == 1 { return "issasi" }
|
|
if slot == 2 { return "issati" }
|
|
if slot == 3 { return "issāma" }
|
|
if slot == 4 { return "issatha" }
|
|
return "issanti"
|
|
}
|
|
|
|
// ── Irregular verb tables ──────────────────────────────────────────────────────
|
|
//
|
|
// atthi/hoti (to be): two parallel paradigms.
|
|
// The "hoti" paradigm is used by default (canonical "be" maps here).
|
|
// "atthi" paradigm is included for the commonly seen alternative.
|
|
|
|
fn pi_hoti_present(slot: Int) -> String {
|
|
if slot == 0 { return "homi" }
|
|
if slot == 1 { return "hosi" }
|
|
if slot == 2 { return "hoti" }
|
|
if slot == 3 { return "homa" }
|
|
if slot == 4 { return "hotha" }
|
|
return "honti"
|
|
}
|
|
|
|
fn pi_atthi_present(slot: Int) -> String {
|
|
if slot == 0 { return "amhi" }
|
|
if slot == 1 { return "asi" }
|
|
if slot == 2 { return "atthi" }
|
|
if slot == 3 { return "amha" }
|
|
if slot == 4 { return "attha" }
|
|
return "santi"
|
|
}
|
|
|
|
// Past (aorist) of hoti/atthi: āsi paradigm (a-aorist)
|
|
fn pi_hoti_aorist(slot: Int) -> String {
|
|
if slot == 0 { return "āsiṃ" }
|
|
if slot == 1 { return "āsi" }
|
|
if slot == 2 { return "āsi" }
|
|
if slot == 3 { return "āsimhā" }
|
|
if slot == 4 { return "āsittha" }
|
|
return "āsiṃsu"
|
|
}
|
|
|
|
// Future of hoti: regular -issa- on root "ho-"
|
|
fn pi_hoti_future(slot: Int) -> String {
|
|
if slot == 0 { return "hossāmi" }
|
|
if slot == 1 { return "hossasi" }
|
|
if slot == 2 { return "hossati" }
|
|
if slot == 3 { return "hossāma" }
|
|
if slot == 4 { return "hossatha" }
|
|
return "hossanti"
|
|
}
|
|
|
|
// gacchati (to go): present is suppletive; aorist uses root "gam-"/"agamā-"
|
|
fn pi_gacchati_present(slot: Int) -> String {
|
|
if slot == 0 { return "gacchāmi" }
|
|
if slot == 1 { return "gacchasi" }
|
|
if slot == 2 { return "gacchati" }
|
|
if slot == 3 { return "gacchāma" }
|
|
if slot == 4 { return "gacchatha" }
|
|
return "gacchanti"
|
|
}
|
|
|
|
fn pi_gacchati_aorist(slot: Int) -> String {
|
|
if slot == 0 { return "agamāsiṃ" }
|
|
if slot == 1 { return "agamāsi" }
|
|
if slot == 2 { return "agamāsi" }
|
|
if slot == 3 { return "agamāsimhā" }
|
|
if slot == 4 { return "agamāsittha" }
|
|
return "agamaṃsu"
|
|
}
|
|
|
|
fn pi_gacchati_future(slot: Int) -> String {
|
|
if slot == 0 { return "gamissāmi" }
|
|
if slot == 1 { return "gamissasi" }
|
|
if slot == 2 { return "gamissati" }
|
|
if slot == 3 { return "gamissāma" }
|
|
if slot == 4 { return "gamissatha" }
|
|
return "gamissanti"
|
|
}
|
|
|
|
// passati (to see): regular present; aorist root "dis-"/"addasā-"
|
|
fn pi_passati_present(slot: Int) -> String {
|
|
if slot == 0 { return "passāmi" }
|
|
if slot == 1 { return "passasi" }
|
|
if slot == 2 { return "passati" }
|
|
if slot == 3 { return "passāma" }
|
|
if slot == 4 { return "passatha" }
|
|
return "passanti"
|
|
}
|
|
|
|
fn pi_passati_aorist(slot: Int) -> String {
|
|
if slot == 0 { return "addasāsiṃ" }
|
|
if slot == 1 { return "addasāsi" }
|
|
if slot == 2 { return "addasāsi" }
|
|
if slot == 3 { return "addasāsimhā" }
|
|
if slot == 4 { return "addasāsittha" }
|
|
return "addasāsiṃsu"
|
|
}
|
|
|
|
fn pi_passati_future(slot: Int) -> String {
|
|
if slot == 0 { return "dakkhissāmi" }
|
|
if slot == 1 { return "dakkhissasi" }
|
|
if slot == 2 { return "dakkhissati" }
|
|
if slot == 3 { return "dakkhissāma" }
|
|
if slot == 4 { return "dakkhissatha" }
|
|
return "dakkhissanti"
|
|
}
|
|
|
|
// vadati (to say): regular throughout; aorist uses avadi-
|
|
fn pi_vadati_present(slot: Int) -> String {
|
|
if slot == 0 { return "vadāmi" }
|
|
if slot == 1 { return "vadasi" }
|
|
if slot == 2 { return "vadati" }
|
|
if slot == 3 { return "vadāma" }
|
|
if slot == 4 { return "vadatha" }
|
|
return "vadanti"
|
|
}
|
|
|
|
fn pi_vadati_aorist(slot: Int) -> String {
|
|
if slot == 0 { return "avadāsiṃ" }
|
|
if slot == 1 { return "avadāsi" }
|
|
if slot == 2 { return "avadāsi" }
|
|
if slot == 3 { return "avadāsimhā" }
|
|
if slot == 4 { return "avadāsittha" }
|
|
return "avadāsiṃsu"
|
|
}
|
|
|
|
fn pi_vadati_future(slot: Int) -> String {
|
|
if slot == 0 { return "vadissāmi" }
|
|
if slot == 1 { return "vadissasi" }
|
|
if slot == 2 { return "vadissati" }
|
|
if slot == 3 { return "vadissāma" }
|
|
if slot == 4 { return "vadissatha" }
|
|
return "vadissanti"
|
|
}
|
|
|
|
// karoti (to do/make): karo- present stem; kāri-/akāsi aorist
|
|
fn pi_karoti_present(slot: Int) -> String {
|
|
if slot == 0 { return "karomi" }
|
|
if slot == 1 { return "karosi" }
|
|
if slot == 2 { return "karoti" }
|
|
if slot == 3 { return "karoma" }
|
|
if slot == 4 { return "karotha" }
|
|
return "karonti"
|
|
}
|
|
|
|
fn pi_karoti_aorist(slot: Int) -> String {
|
|
if slot == 0 { return "akāsiṃ" }
|
|
if slot == 1 { return "akāsi" }
|
|
if slot == 2 { return "akāsi" }
|
|
if slot == 3 { return "akāsimhā" }
|
|
if slot == 4 { return "akāsittha" }
|
|
return "akāsiṃsu"
|
|
}
|
|
|
|
fn pi_karoti_future(slot: Int) -> String {
|
|
if slot == 0 { return "karissāmi" }
|
|
if slot == 1 { return "karissasi" }
|
|
if slot == 2 { return "karissati" }
|
|
if slot == 3 { return "karissāma" }
|
|
if slot == 4 { return "karissatha" }
|
|
return "karissanti"
|
|
}
|
|
|
|
// ── Canonical verb mapping ─────────────────────────────────────────────────────
|
|
//
|
|
// Maps English semantic labels to Pali verb citation forms (3rd sg present).
|
|
|
|
fn pi_map_canonical(verb: String) -> String {
|
|
if str_eq(verb, "be") { return "hoti" }
|
|
if str_eq(verb, "go") { return "gacchati" }
|
|
if str_eq(verb, "see") { return "passati" }
|
|
if str_eq(verb, "say") { return "vadati" }
|
|
if str_eq(verb, "do") { return "karoti" }
|
|
if str_eq(verb, "make") { return "karoti" }
|
|
return verb
|
|
}
|
|
|
|
// ── Regular verb stem derivation ───────────────────────────────────────────────
|
|
//
|
|
// For bhū-ādi class verbs, the present stem is derived by stripping -ati from
|
|
// the 3sg present form (the citation form), then appending the appropriate ending.
|
|
// The same root (without -ati) is used for the aorist and future.
|
|
//
|
|
// e.g. "bhavati" -> root "bhava" -> present "bhavāmi", future "bhavissāmi"
|
|
// -> aorist root = "bhavi" -> "bhaviṃ"
|
|
|
|
fn pi_regular_root(verb: String) -> String {
|
|
// Strip -ati if present to get the thematic stem
|
|
if pi_str_ends(verb, "ati") { return pi_drop(verb, 3) }
|
|
// Some forms end in -eti (e-class verbs)
|
|
if pi_str_ends(verb, "eti") { return pi_drop(verb, 3) }
|
|
// Otherwise treat the whole form as the root
|
|
return verb
|
|
}
|
|
|
|
// ── pi_conjugate: main conjugation entry point ────────────────────────────────
|
|
//
|
|
// verb: Pali 3sg present (citation form, e.g. "bhavati", "hoti") or English
|
|
// canonical label
|
|
// tense: "present" | "past" | "future"
|
|
// person: "first" | "second" | "third"
|
|
// number: "singular" | "plural"
|
|
//
|
|
// Returns the inflected form. Falls back to the citation form on unknown input.
|
|
|
|
fn pi_conjugate(verb: String, tense: String, person: String, number: String) -> String {
|
|
let v: String = pi_map_canonical(verb)
|
|
let slot: Int = pi_slot(person, number)
|
|
|
|
// ── Irregulars ────────────────────────────────────────────────────────────
|
|
|
|
if str_eq(v, "hoti") {
|
|
if str_eq(tense, "present") { return pi_hoti_present(slot) }
|
|
if str_eq(tense, "past") { return pi_hoti_aorist(slot) }
|
|
if str_eq(tense, "future") { return pi_hoti_future(slot) }
|
|
return v
|
|
}
|
|
|
|
if str_eq(v, "atthi") {
|
|
if str_eq(tense, "present") { return pi_atthi_present(slot) }
|
|
if str_eq(tense, "past") { return pi_hoti_aorist(slot) }
|
|
if str_eq(tense, "future") { return pi_hoti_future(slot) }
|
|
return v
|
|
}
|
|
|
|
if str_eq(v, "gacchati") {
|
|
if str_eq(tense, "present") { return pi_gacchati_present(slot) }
|
|
if str_eq(tense, "past") { return pi_gacchati_aorist(slot) }
|
|
if str_eq(tense, "future") { return pi_gacchati_future(slot) }
|
|
return v
|
|
}
|
|
|
|
if str_eq(v, "passati") {
|
|
if str_eq(tense, "present") { return pi_passati_present(slot) }
|
|
if str_eq(tense, "past") { return pi_passati_aorist(slot) }
|
|
if str_eq(tense, "future") { return pi_passati_future(slot) }
|
|
return v
|
|
}
|
|
|
|
if str_eq(v, "vadati") {
|
|
if str_eq(tense, "present") { return pi_vadati_present(slot) }
|
|
if str_eq(tense, "past") { return pi_vadati_aorist(slot) }
|
|
if str_eq(tense, "future") { return pi_vadati_future(slot) }
|
|
return v
|
|
}
|
|
|
|
if str_eq(v, "karoti") {
|
|
if str_eq(tense, "present") { return pi_karoti_present(slot) }
|
|
if str_eq(tense, "past") { return pi_karoti_aorist(slot) }
|
|
if str_eq(tense, "future") { return pi_karoti_future(slot) }
|
|
return v
|
|
}
|
|
|
|
// ── Regular bhū-ādi class verb ────────────────────────────────────────────
|
|
|
|
let root: String = pi_regular_root(v)
|
|
|
|
if str_eq(tense, "present") {
|
|
return root + pi_present_ending(slot)
|
|
}
|
|
|
|
if str_eq(tense, "past") {
|
|
// Aorist: root + i-aorist ending
|
|
return root + pi_aorist_ending(slot)
|
|
}
|
|
|
|
if str_eq(tense, "future") {
|
|
return root + pi_future_ending(slot)
|
|
}
|
|
|
|
// Unknown tense: return citation form unchanged
|
|
return v
|
|
}
|
|
|
|
// ── a-stem masculine declension ("purisa" — man) ─────────────────────────────
|
|
//
|
|
// The a-stem masculine is the most frequent Pali declension class.
|
|
// Paradigm based on "puriso" (nominative singular).
|
|
//
|
|
// Eight cases: nominative, accusative, instrumental, dative, ablative,
|
|
// genitive, locative, vocative.
|
|
//
|
|
// Singular:
|
|
// nom puriso acc purisaṃ instr purisena dat purisāya (or purissā)
|
|
// abl purisā gen purisassa loc purisasmiṃ voc purisa
|
|
//
|
|
// Plural:
|
|
// nom purisā acc purise instr purisehi dat purisānaṃ
|
|
// abl purisānaṃ gen purisānaṃ loc purisesu voc purisā
|
|
//
|
|
// The caller passes the stem (without final vowel), e.g. "purisa".
|
|
// Detection: strip the final -o (nom sg) or use the stem directly.
|
|
|
|
fn pi_decline_a_masc_sg(stem: String, gram_case: String) -> String {
|
|
if str_eq(gram_case, "nominative") { return stem + "o" }
|
|
if str_eq(gram_case, "accusative") { return stem + "ṃ" }
|
|
if str_eq(gram_case, "instrumental") { return stem + "ena" }
|
|
if str_eq(gram_case, "dative") { return stem + "āya" }
|
|
if str_eq(gram_case, "ablative") { return stem + "ā" }
|
|
if str_eq(gram_case, "genitive") { return stem + "ssa" }
|
|
if str_eq(gram_case, "locative") { return stem + "smiṃ" }
|
|
if str_eq(gram_case, "vocative") { return stem }
|
|
// Default: nominative
|
|
return stem + "o"
|
|
}
|
|
|
|
fn pi_decline_a_masc_pl(stem: String, gram_case: String) -> String {
|
|
if str_eq(gram_case, "nominative") { return stem + "ā" }
|
|
if str_eq(gram_case, "accusative") { return stem + "e" }
|
|
if str_eq(gram_case, "instrumental") { return stem + "ehi" }
|
|
if str_eq(gram_case, "dative") { return stem + "ānaṃ" }
|
|
if str_eq(gram_case, "ablative") { return stem + "ānaṃ" }
|
|
if str_eq(gram_case, "genitive") { return stem + "ānaṃ" }
|
|
if str_eq(gram_case, "locative") { return stem + "esu" }
|
|
if str_eq(gram_case, "vocative") { return stem + "ā" }
|
|
return stem + "ā"
|
|
}
|
|
|
|
// ── ā-stem feminine declension ("kaññā" — girl) ───────────────────────────────
|
|
//
|
|
// ā-stem feminines are the second most common class. Paradigm based on "kaññā".
|
|
//
|
|
// Singular:
|
|
// nom kaññā acc kaññaṃ instr kaññāya dat kaññāya
|
|
// abl kaññāya gen kaññāya loc kaññāyaṃ voc kaññe
|
|
//
|
|
// Plural (approximated from standard tables; many forms merge):
|
|
// nom kaññā acc kaññā instr kaññāhi dat kaññānaṃ
|
|
// abl kaññānaṃ gen kaññānaṃ loc kaññāsu voc kaññā
|
|
//
|
|
// The caller passes the stem without the final ā, e.g. "kaññ".
|
|
|
|
fn pi_decline_a_fem_sg(stem: String, gram_case: String) -> String {
|
|
if str_eq(gram_case, "nominative") { return stem + "ā" }
|
|
if str_eq(gram_case, "accusative") { return stem + "aṃ" }
|
|
if str_eq(gram_case, "instrumental") { return stem + "āya" }
|
|
if str_eq(gram_case, "dative") { return stem + "āya" }
|
|
if str_eq(gram_case, "ablative") { return stem + "āya" }
|
|
if str_eq(gram_case, "genitive") { return stem + "āya" }
|
|
if str_eq(gram_case, "locative") { return stem + "āyaṃ" }
|
|
if str_eq(gram_case, "vocative") { return stem + "e" }
|
|
return stem + "ā"
|
|
}
|
|
|
|
fn pi_decline_a_fem_pl(stem: String, gram_case: String) -> String {
|
|
if str_eq(gram_case, "nominative") { return stem + "ā" }
|
|
if str_eq(gram_case, "accusative") { return stem + "ā" }
|
|
if str_eq(gram_case, "instrumental") { return stem + "āhi" }
|
|
if str_eq(gram_case, "dative") { return stem + "ānaṃ" }
|
|
if str_eq(gram_case, "ablative") { return stem + "ānaṃ" }
|
|
if str_eq(gram_case, "genitive") { return stem + "ānaṃ" }
|
|
if str_eq(gram_case, "locative") { return stem + "āsu" }
|
|
if str_eq(gram_case, "vocative") { return stem + "ā" }
|
|
return stem + "ā"
|
|
}
|
|
|
|
// ── Declension class detection ─────────────────────────────────────────────────
|
|
//
|
|
// Detect whether a noun is an a-stem masculine or ā-stem feminine based on its
|
|
// citation form (nominative singular).
|
|
//
|
|
// ends in -o -> a-stem masculine (puriso, devo, loko)
|
|
// ends in -ā -> ā-stem feminine (kaññā, mātu[?], nadī)
|
|
// ends in -a -> treat as a-stem masculine stem (some words cited without -o)
|
|
//
|
|
// For other stems the module falls back to a-stem masculine as the safest default.
|
|
|
|
fn pi_detect_class(noun: String) -> String {
|
|
if pi_str_ends(noun, "o") { return "a_masc" }
|
|
if pi_str_ends(noun, "ā") { return "a_fem" }
|
|
// Some a-masc nouns may be cited as stems ending in -a
|
|
if pi_str_ends(noun, "a") { return "a_masc" }
|
|
// Default to a-stem masculine
|
|
return "a_masc"
|
|
}
|
|
|
|
// ── pi_decline: main declension entry point ───────────────────────────────────
|
|
//
|
|
// noun: Pali nominative singular (citation form, e.g. "puriso", "kaññā")
|
|
// gram_case: "nominative" | "accusative" | "instrumental" | "dative" |
|
|
// "ablative" | "genitive" | "locative" | "vocative"
|
|
// number: "singular" | "plural"
|
|
//
|
|
// Returns the inflected form. Falls back to the citation form on unknown input.
|
|
|
|
fn pi_decline(noun: String, gram_case: String, number: String) -> String {
|
|
let nclass: String = pi_detect_class(noun)
|
|
|
|
if str_eq(nclass, "a_masc") {
|
|
// Derive stem: strip final -o or -a to get the consonant stem
|
|
let stem: String = noun
|
|
if pi_str_ends(noun, "o") {
|
|
let stem = pi_drop(noun, 1)
|
|
}
|
|
if pi_str_ends(noun, "a") {
|
|
let stem = pi_drop(noun, 1)
|
|
}
|
|
if str_eq(number, "singular") { return pi_decline_a_masc_sg(stem, gram_case) }
|
|
return pi_decline_a_masc_pl(stem, gram_case)
|
|
}
|
|
|
|
if str_eq(nclass, "a_fem") {
|
|
// Derive stem: strip final -ā
|
|
let stem: String = noun
|
|
if pi_str_ends(noun, "ā") {
|
|
let stem = pi_drop(noun, 1)
|
|
}
|
|
if str_eq(number, "singular") { return pi_decline_a_fem_sg(stem, gram_case) }
|
|
return pi_decline_a_fem_pl(stem, gram_case)
|
|
}
|
|
|
|
// Unknown class: return citation form unchanged
|
|
return noun
|
|
}
|
|
|
|
// ── pi_noun_phrase: noun phrase builder ──────────────────────────────────────
|
|
//
|
|
// Pali has no articles (definite or indefinite). The declined form is the
|
|
// complete noun phrase. The definite parameter is accepted for interface
|
|
// compatibility with other language modules but has no effect.
|
|
//
|
|
// noun: nominative singular Pali noun (e.g. "puriso", "kaññā")
|
|
// gram_case: "nominative" | "accusative" | "instrumental" | "dative" |
|
|
// "ablative" | "genitive" | "locative" | "vocative"
|
|
// number: "singular" | "plural"
|
|
// definite: ignored (Pali has no articles)
|
|
//
|
|
// Returns the inflected noun form.
|
|
|
|
fn pi_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String {
|
|
return pi_decline(noun, gram_case, number)
|
|
}
|