Jump to content

Module:kbt-conj

From Wiktionary, the free dictionary


local export = {}

-- gabadi subject markers (sm) - page 23 of [1]
local subjects_sm = {
    ["1sg"] = "a-",
    ["2sg"] = "o-",
    ["3sg"] = "e-",
    ["1pl.incl"] = "ka-",
    ["1pl.excl"] = "i-", -- documented as |-, aniani table shows i-
    ["2pl"] = "u-",
    ["3pl"] = "ge-",
}

-- gabadi future subject markers (futsm) - page 25 of [1] and aniani example
local subjects_fut_sm = {
    ["1sg"] = "va-",
    ["2sg"] = "vo-", -- assumed pattern
    ["3sg"] = "ve-",
    ["1pl.incl"] = "isa-", -- exception to v-
    ["1pl.excl"] = "vi-", -- assumed pattern
    ["2pl"] = "vu-", -- assumed pattern
    ["3pl"] = "eda-", -- exception to v-
}

-- gabadi medial suffixes (om.posssfx from aniani example, page 40 of [1])
local medial_om_poss_sfx = {
    ["1sg"] = "’u",
    ["2sg"] = "mu",
    ["3sg"] = "na",
    ["1pl.incl"] = "ga",
    ["1pl.excl"] = "mai",
    ["2pl"] = "mui",
    ["3pl"] = "da",
}

-- function to apply prefix to stem and handle phonological changes / alternative forms
-- is_simple_sm_prefix: boolean, true if the prefix is from subjects_sm (for i-stem merger logic)
local function apply_prefix_to_stem(prefix_str_hyphen, current_stem, is_simple_sm_prefix)
    local forms = {}
    local prefix_base = prefix_str_hyphen:gsub("-$", "") -- "a", "ve", "ama"

    local stem_char1 = mw.ustring.sub(current_stem, 1, 1)
    local prefix_last_char = mw.ustring.sub(prefix_base, -1)
    local prefix_is_vowel = mw.ustring.find(prefix_last_char, "[aeiou]")
    local stem_is_vowel_initial = mw.ustring.find(stem_char1, "[aeiou]")

    local primary_form

    if mw.ustring.match(current_stem, "^i") and is_simple_sm_prefix and subjects_sm[prefix_base:gsub("ma$","")] then -- check if prefix_base (or its root for commands) is a simple sm key
        -- specific mergers for simple sms + i-initial stems
        local sm_root = prefix_base -- for simple sms like "a", "o", "e", etc.
        local mapping = {a="ai", o="oi", e="ei", ka="kai", i="i", u="ui", ge="gei"}
        if mapping[sm_root] then
            if sm_root == "i" then -- i- + isa'aku -> isa'aku
                primary_form = current_stem
            else
                primary_form = mapping[sm_root] .. mw.ustring.sub(current_stem, 2)
            end
        else
             -- this case should ideally not be hit if is_simple_sm_prefix is set correctly
            primary_form = prefix_base .. "'" .. current_stem
        end
    elseif stem_is_vowel_initial and prefix_is_vowel then
        primary_form = prefix_base .. "'" .. current_stem
    else
        primary_form = prefix_base .. current_stem
    end
    table.insert(forms, primary_form)

    -- handle alternative forms for reduplicated stems with specific prefixes
    -- this applies to stems like "aniani", where half_stem * 2 == full_stem.
    -- for certain prefixes, an alternative form prefix_base .. short_stem .. "a" can be generated.
    local stem_len = mw.ustring.len(current_stem)
    if stem_len > 1 and stem_len % 2 == 0 then -- must be even length and at least 2 chars (e.g. "aa")
        local half_len = stem_len / 2
        local first_half = mw.ustring.sub(current_stem, 1, half_len)
        local second_half = mw.ustring.sub(current_stem, half_len + 1)

        if first_half == second_half then -- stem is reduplicated, e.g., aniani -> ani + ani
            local short_stem = first_half
            -- prefixes (without trailing hyphen) that trigger this alternative form
            -- these are derived from the prefixes used with 'aniani' alternatives in the reference
            local alternative_trigger_prefixes = {
                ["e"] = true,    -- from 3sg past/present sm 'e-'
                ["ge"] = true,   -- from 3pl past/present sm 'ge-'
                ["ve"] = true,   -- from 3sg future sm 've-'
                ["eda"] = true,  -- from 3pl future sm 'eda-'
                ["ema"] = true,  -- from 3sg command (e.g., e- + ma-)
                ["gema"] = true  -- from 3pl command (e.g., ge- + ma-)
            }

            if alternative_trigger_prefixes[prefix_base] then
                local alternative_form = prefix_base .. short_stem .. "a" -- e.g., e + ani + a = eania

                local already_exists = false
                for _, f_existing in ipairs(forms) do
                    if f_existing == alternative_form then
                        already_exists = true
                        break
                    end
                end
                if not already_exists then
                    table.insert(forms, alternative_form)
                end
            end
        end
    end
    return forms
end


function export.show(frame)
    local pagename = mw.loadData("Module:headword/data").pagename
    local stem = pagename -- lemma is the stem in gabadi for this purpose

    local conj_table_lines = {}

    table.insert(conj_table_lines, '{| class="wikitable" style="text-align:center;"')
    table.insert(conj_table_lines, '! rowspan="2" | ')
    table.insert(conj_table_lines, '! colspan="2" | past (real)<br/><small>sm + stem</small>')
    table.insert(conj_table_lines, '! colspan="2" | present (real)<br/><small>sm + stem + -va <small>(pr)</small></small>')
    table.insert(conj_table_lines, '! colspan="2" | future (irr)<br/><small>futsm + stem</small>')
    table.insert(conj_table_lines, '! colspan="2" | command (irr)<br/><small>sm + ma- <small>(irr)</small> + stem</small>')
    table.insert(conj_table_lines, '! rowspan="2" | medial<br/><small>stem + om.posssfx + -nai</small>')
    table.insert(conj_table_lines, "|-")
    table.insert(conj_table_lines, "! positive !! negative !! positive !! negative !! positive !! negative !! positive !! negative")

    local persons = {"1sg", "2sg", "3sg", "1pl.incl", "1pl.excl", "2pl", "3pl"}
    local person_display_sm_map = {
        ["1sg"] = subjects_sm["1sg"], ["2sg"] = subjects_sm["2sg"], ["3sg"] = subjects_sm["3sg"],
        ["1pl.incl"] = subjects_sm["1pl.incl"], ["1pl.excl"] = subjects_sm["1pl.excl"],
        ["2pl"] = subjects_sm["2pl"], ["3pl"] = subjects_sm["3pl"],
    }

    for _, person_code in ipairs(persons) do
        local row_elements = {}
        table.insert(row_elements, "! " .. person_code .. "<br/>" .. person_display_sm_map[person_code]:gsub("-",""))

        local function format_forms_cell(forms_list)
            return table.concat(forms_list, "<br/>''or''<br/>")
        end
        local function format_negative_forms_cell(positive_forms_list)
            local neg_parts = {}
            for _, pf_part in ipairs(positive_forms_list) do
                table.insert(neg_parts, "da " .. pf_part)
            end
            return format_forms_cell(neg_parts)
        end

        -- past (sm + stem)
        local sm_past = subjects_sm[person_code]
        local past_forms_positive = apply_prefix_to_stem(sm_past, stem, true)
        table.insert(row_elements, "| " .. format_forms_cell(past_forms_positive))
        table.insert(row_elements, "| " .. format_negative_forms_cell(past_forms_positive))

        -- present (sm + stem + -va)
        local sm_pres = subjects_sm[person_code]
        local pres_base_forms = apply_prefix_to_stem(sm_pres, stem, true)
        local pres_forms_positive_suffixed = {}
        for _, bf in ipairs(pres_base_forms) do table.insert(pres_forms_positive_suffixed, bf .. "va") end
        table.insert(row_elements, "| " .. format_forms_cell(pres_forms_positive_suffixed))
        table.insert(row_elements, "| " .. format_negative_forms_cell(pres_forms_positive_suffixed))

        -- future (futsm + stem)
        local fut_sm = subjects_fut_sm[person_code]
        local fut_forms_positive = apply_prefix_to_stem(fut_sm, stem, false) -- not a simple sm for i-stem merger
        table.insert(row_elements, "| " .. format_forms_cell(fut_forms_positive))
        table.insert(row_elements, "| " .. format_negative_forms_cell(fut_forms_positive))

        -- command (sm + ma- + stem)
        local sm_for_cmd = subjects_sm[person_code] -- base sm
        local cmd_prefix_effective = sm_for_cmd:gsub("-$", "") .. "ma-" -- e.g., "a-ma-", "ge-ma-"
        local cmd_forms_positive = apply_prefix_to_stem(cmd_prefix_effective, stem, false) -- not a simple sm for i-stem merger
        table.insert(row_elements, "| " .. format_forms_cell(cmd_forms_positive))
        table.insert(row_elements, "| " .. format_negative_forms_cell(cmd_forms_positive))

        -- medial (stem + om.posssfx + -nai)
        local medial_form = stem .. medial_om_poss_sfx[person_code] .. "nai"
        table.insert(row_elements, "| " .. medial_form)

        table.insert(conj_table_lines, "|-\n" .. table.concat(row_elements, "\n"))
    end

    table.insert(conj_table_lines, "|}")
    return table.concat(conj_table_lines, "\n")
end

return export