Module:User:Surjection/cv-decl

This is a private module sandbox of Surjection, for their own experimentation. Items in this module may be added and removed at Surjection's discretion; do not rely on this module's stability.


local export = {}
local m_links = require("Module:links")
local lang = require("Module:languages").getByCode("cv")

-- vowel harmony

-- true for front, false for back.
local function get_harmony(harmony)
	local index = mw.ustring.len(harmony)
	while index > 0 do
		local character = mw.ustring.sub(harmony, index, index)
		if mw.ustring.find(character, "[иӳӗе]") then
			return true
		elseif mw.ustring.find(character, "[ыуӑао]") then
			return false
		end
		index = index - 1
	end
	return false
end

local function harmonize(suffix, harmony)
	if harmony then
		suffix = mw.ustring.gsub(suffix, "[аӑуы]", {
			["а"] = "е", ["ӑ"] = "ӗ", ["у"] = "ӳ", ["ы"] = "и"
		})
	end
	return suffix
end

-- utilities

local function add_form_with_suffix(forms, form, harmony, base, ...)
    local suffixes = { ... }
    local results = {}

    for _, suffix in ipairs(suffixes) do
        table.insert(results, base .. harmonize(suffix, harmony))
    end

    forms[form] = results
end

-- plural forms

local function inflect_plural(forms, nom_sg)
    add_form_with_suffix(forms, "nom_pl", nil, nom_sg, "сем")
    add_form_with_suffix(forms, "acc_pl", nil, nom_sg, "сене")
    add_form_with_suffix(forms, "gen_pl", nil, nom_sg, "сен", "сенӗн")
    add_form_with_suffix(forms, "ins_pl", nil, nom_sg, "семпе")
    add_form_with_suffix(forms, "loc_pl", nil, nom_sg, "сенче")
    add_form_with_suffix(forms, "abl_pl", nil, nom_sg, "сенчен")
    add_form_with_suffix(forms, "abe_pl", nil, nom_sg, "семсӗр")
    add_form_with_suffix(forms, "cau_pl", nil, nom_sg, "семшӗн")
    return forms
end

-- inflection classes

local function inflect_consonant(nom_sg, stem, harmony)
    local forms = {["nom_sg"] = {nom_sg}}
    stem = stem or nom_sg
    add_form_with_suffix(forms, "acc_sg", harmony, stem, "а")
    add_form_with_suffix(forms, "gen_sg", harmony, stem, "ӑн")
    add_form_with_suffix(forms, "ins_sg", harmony, nom_sg, "па")
    add_form_with_suffix(forms, "loc_sg", harmony, nom_sg, "ра")
    add_form_with_suffix(forms, "abl_sg", harmony, nom_sg, "ран")
    add_form_with_suffix(forms, "abe_sg", harmony, nom_sg, "сӑр")
    add_form_with_suffix(forms, "cau_sg", harmony, nom_sg, "шӑн")
    return inflect_plural(forms, nom_sg)
end

local function inflect_resonant(nom_sg, stem, harmony)
    local forms = {["nom_sg"] = {nom_sg}}
    stem = stem or nom_sg
    add_form_with_suffix(forms, "acc_sg", harmony, stem, "а")
    add_form_with_suffix(forms, "gen_sg", harmony, stem, "ӑн")
    add_form_with_suffix(forms, "ins_sg", harmony, nom_sg, "па")
    add_form_with_suffix(forms, "loc_sg", harmony, nom_sg, "та")
    add_form_with_suffix(forms, "abl_sg", harmony, nom_sg, "тан")
    add_form_with_suffix(forms, "abe_sg", harmony, nom_sg, "сӑр")
    add_form_with_suffix(forms, "cau_sg", harmony, nom_sg, "шӑн")
    return inflect_plural(forms, nom_sg)
end

local function inflect_vowel(nom_sg, stem, harmony)
    local forms = {["nom_sg"] = {nom_sg}}
    stem = stem or nom_sg
    add_form_with_suffix(forms, "acc_sg", harmony, stem, "на")
    add_form_with_suffix(forms, "gen_sg", harmony, stem, "н")
    add_form_with_suffix(forms, "ins_sg", harmony, nom_sg, "па")
    add_form_with_suffix(forms, "loc_sg", harmony, nom_sg, "ра")
    add_form_with_suffix(forms, "abl_sg", harmony, nom_sg, "ран")
    add_form_with_suffix(forms, "abe_sg", harmony, nom_sg, "сӑр")
    add_form_with_suffix(forms, "cau_sg", harmony, nom_sg, "шӑн")
    return inflect_plural(forms, nom_sg)
end

local function inflect_reduced(nom_sg, stem, harmony)
    local forms = {["nom_sg"] = {nom_sg}}
    if not stem then
        stem = mw.ustring.sub(nom_sg, 1, -2)
        local final_consonant = mw.ustring.sub(stem, -1, -1)
        if not mw.ustring.find(mw.ustring.sub(stem, -2, -2), final_consonant) then
            stem = stem .. final_consonant
        end
    end
    add_form_with_suffix(forms, "acc_sg", harmony, stem, "а")
    add_form_with_suffix(forms, "gen_sg", harmony, stem, "ӑн")
    add_form_with_suffix(forms, "ins_sg", harmony, nom_sg, "па")
    add_form_with_suffix(forms, "loc_sg", harmony, nom_sg, "ра")
    add_form_with_suffix(forms, "abl_sg", harmony, nom_sg, "ран")
    add_form_with_suffix(forms, "abe_sg", harmony, nom_sg, "сӑр")
    add_form_with_suffix(forms, "cau_sg", harmony, nom_sg, "шӑн")
    return inflect_plural(forms, nom_sg)
end

local function inflect_rounded(nom_sg, stem, harmony)
    local forms = {["nom_sg"] = {nom_sg}}
    if not stem or not mw.ustring.find(stem, "в$") then
        error("Must specify a stem ending in в as the first parameter for nouns ending in у/ӳ in the nominative singular form")
    end
    add_form_with_suffix(forms, "acc_sg", harmony, stem, "а")
    add_form_with_suffix(forms, "gen_sg", harmony, stem, "ӑн")
    add_form_with_suffix(forms, "ins_sg", harmony, nom_sg, "па")
    add_form_with_suffix(forms, "loc_sg", harmony, nom_sg, "ра")
    add_form_with_suffix(forms, "abl_sg", harmony, nom_sg, "ран")
    add_form_with_suffix(forms, "abe_sg", harmony, nom_sg, "сӑр")
    add_form_with_suffix(forms, "cau_sg", harmony, nom_sg, "шӑн")
    return inflect_plural(forms, nom_sg)
end

-- inflection entry point

local function inflect(nominative_singular, stem, harmony)
	harmony = get_harmony(harmony or stem or nominative_singular)

	local final = mw.ustring.sub(nominative_singular, -1, -1)
	if mw.ustring.find(final, "[рлмн]") then
        return inflect_resonant(nominative_singular, stem, harmony)
    elseif mw.ustring.find(final, "[уӳ]") then
        return inflect_rounded(nominative_singular, stem, harmony)
    elseif mw.ustring.find(final, "[ӑӗ]") then
        return inflect_reduced(nominative_singular, stem, harmony)
    elseif mw.ustring.find(final, "[ае]") then
        return inflect_vowel(nominative_singular, stem, harmony)
    elseif mw.ustring.find(final, "[вйкпсҫтхчш]") then
        return inflect_consonant(nominative_singular, stem, harmony)
    else
        error("Unsupported inflection type")
    end
end

-- inflection table

local infl_table = [=[{| class="inflection-table vsSwitcher" data-toggle-category="declension" style="border:1px solid #CCCCFF"
|-
!colspan=3 class="vsToggleElement" style="background:rgb(80%,80%,100%);text-align:left;"|Declension of {{{title}}}
|- class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
! style="width:11em;" |
! style="width:12em;" | singular
! style="width:12em;" | plural
|- class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;" |
! style="background:rgb(80%,80%,100%);width:11em" | nominative
|style="width:12em" | {{{nom_sg}}}
|style="width:12em" | {{{nom_pl}}}
|- class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;" |
! style="background:rgb(80%,80%,100%);" | dative-accusative
|{{{acc_sg}}}
|{{{acc_pl}}}
|- class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;" |
! style="background:rgb(80%,80%,100%);" | genitive
|{{{gen_sg}}}
|{{{gen_pl}}}
|- class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;" |
! style="background:rgb(80%,80%,100%);" | instrumental
|{{{ins_sg}}}
|{{{ins_pl}}}
|- class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;" |
! style="background:rgb(80%,80%,100%);" | locative
|{{{loc_sg}}}
|{{{loc_pl}}}
|- class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;" |
! style="background:rgb(80%,80%,100%);" | ablative
|{{{abl_sg}}}
|{{{abl_pl}}}
|- class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;" |
! style="background:rgb(80%,80%,100%);" | abessive
|{{{abe_sg}}}
|{{{abe_pl}}}
|- class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;" |
! style="background:rgb(80%,80%,100%);" | causative
|{{{cau_sg}}}
|{{{cau_pl}}}
|}]=]

local function link(text)
	return require("Module:links").full_link{ term = text, lang = lang }
end

local function show_forms(data)
	local function repl(form)
		if form == "title" then
			return "'''" .. data.title .. "'''"
		else
			local value = data[form]
			if not value then
				return "—"
			elseif type(value) == "table" then
				local result = {}
				for _, f in ipairs(value) do
					table.insert(result, link(f))
				end
				return table.concat(result, ", ")
			else
				return link(value)
			end
		end
	end

	local result = mw.ustring.gsub(infl_table, "{{{([a-z0-9_:]+)}}}", repl)
	return result
end

-- module entry point

function export.show(frame)
	local args = frame:getParent().args
	local title = args["title"] or mw.title.getCurrentTitle()
	local stem = args[1] or nil
	local harmony = args[2] or nil

	local forms = inflect(title, stem, harmony)
    forms["title"] = title
	return show_forms(forms)
end

return export