Module:User:Victar/iir-decl-noun

Definition from Wiktionary, the free dictionary
Jump to navigation Jump to search

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


local export = {}

local m_links = require("Module:links")
local m_utils = require("Module:utilities")

local lang = require("Module:languages").getByCode("iir-pro")

local decl_data = require("Module:User:Victar/iir-decl-noun/data")

local decl_data_irreg = require("Module:User:Victar/iir-decl-noun/data/irreg")

local endings = {
	["ás"] = "a-m", ["as"] = "a-m", ["ám"] = "a-n", ["am"] = "a-n",
	["áH"] = "aH-f", ["aH"] = "aH-f",
	["íš"] = "i-mf", ["iš"] = "i-mf", ["i"] = "i-n",
	["íH"] = "yaH-f", ["iH"] = "yaH-f",
	["íHs"] = "iH-f", ["iHs"] = "iH-f",
	["uš"] = "u-mf", ["u"] = "u-n",
	["úHs"] = "uH-f", ["uHs"] = "uH-f",
}

local endings_reverse = {
	["a-m"] = "ás", ["a-m"] = "as", ["a-n"] = "ám", ["a-n"] = "am",
	["aH-f"] = "áH", ["aH-f"] = "aH",
	["i-mf"] = "íš", ["i-mf"] = "iš", ["i-m"] = "íš", ["i-m"] = "iš", ["i-f"] = "íš", ["i-f"] = "iš", ["i-n"] = "i",
	["yaH-f"] = "íH", ["yaH-f"] = "iH",
	["iH-f"] = "íHs", ["iH-f"] = "iHs",
	["u-mf"] = "uš", ["u-m"] = "uš", ["u-f"] = "uš", ["u-n"] = "u",
	["uH-f"] = "úHs", ["uH-f"] = "uHs",
	["r-n"] = "ā́", ["r-n"] = "ā",
	["cons-n"] = "",
}

local function detect_decl(word, stem, gender)
	
	if stem and gender then
		local decl = stem .. "-" .. gender
		return decl, {mw.ustring.sub(word, 1, -(mw.ustring.len(endings_reverse[decl]) + 1))}
	elseif stem == "r" and mw.ustring.sub(word, -2) == "ā́" then --r-stem
		return "r-n", {mw.ustring.sub(word, 1, -3)}
	elseif mw.ustring.find(word, "ô$") then -- an-stem
		if gender then
			return "n-" .. gender, {mw.ustring.sub(word, 1, -2)}
		else
			error("Gender must be specified for an-stems.")
		end
	else
		for ending, decl in pairs(endings) do
			if mw.ustring.find(word, ending .. "$") then
				return decl, {mw.ustring.sub(word, 1, -(mw.ustring.len(ending) + 1))}
			end
		end
		-- No matches, assume consonant stem. Now check for s-stems
		local stem = ""
		if mw.ustring.sub(word, -1, -1) == "s" and not mw.ustring.find(mw.ustring.sub(word, -2, -2), "[fhkptþ]") then
			stem = word
		else
			stem = mw.ustring.sub(word, 1, -2)
		end
		return (gender and "cons-" .. gender or "cons-mf"), {stem}
	end

end

function destress_if_stressed(ending)
	local word = mw.title.getCurrentTitle().subpageText
	
	if mw.ustring.find(mw.ustring.sub(word, 1, -3), "[áíĺḿńŕúā́]") then
		ending = mw.ustring.gsub(ending, "á", "a")
		ending = mw.ustring.gsub(ending, "í", "i")
		ending = mw.ustring.gsub(ending, "ó", "o")
		ending = mw.ustring.gsub(ending, "ú", "u")
		ending = mw.ustring.gsub(ending, "ā́", "ā")
		ending = mw.ustring.gsub(ending, "́", "")
	end
	
	return ending
end
	
local function add_asterisks(forms, data)
	for _, form in ipairs(forms) do
		for i, subform in ipairs(data.forms[form]) do
			data.forms[form][i] = "*" .. subform
		end
	end
end

-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
	local parent_args = frame:getParent().args
	if mw.title.getCurrentTitle().nsText ~= "Reconstruction" then return end
	
	local stems = nil
	local decl_type = {}
	local word = mw.title.getCurrentTitle().subpageText
	local args = {}

	if not decl_data_irreg[word] then
		if frame.args.decl then
			decl_type = frame.args.decl
		else
			if parent_args.stem and parent_args.g and parent_args[1] then
				decl_type = parent_args.stem .. "-" .. parent_args.g
				stems = {parent_args[1]}
			else
				decl_type, stems = detect_decl(word, parent_args.stem, parent_args.g)
			end
			
		end
		
		if not decl_type then
			error("Unknown declension '" .. decl_type .. "'")
		end
		
		args = require("Module:parameters").process(parent_args, decl_data[decl_type].params, true)
	
		if stems then
			for i, stem in ipairs(stems) do
				args[i] = stem
			end
		end
	end

	local data = {forms = {}, categories = {}}
	
	data.head = parent_args["head"] or nil
	
	-- Generate the forms
	if decl_data_irreg[word] then
		table.insert(data.categories, "Proto-Indo-Iranian irregular nouns")
		decl_data_irreg[word](parent_args, data)
	else
		decl_data[decl_type](args, data)
	end

	-- Make the table
	return make_table(data)
end

function make_table(data)

	local function show_form(form)
		if not form then
			return "—"
		end
		
		local ret = {}
		
		for key, subform in ipairs(form) do
			if subform ~= "—" then
				subform = "*" .. subform
			end
			table.insert(ret, subform)
		end
			
		return table.concat(ret, ", ")
	end
	
	local function repl(param)
		if param == "decl_type" then
			return data.decl_type
		elseif param == "title" then
			return "*" .. data.forms.nom_sg[1]
		else
			return show_form(data.forms[param])
		end
	end

	local function make_cases(data)
		local cases = {"nominative", "vocative", "accusative", "instrumental", "ablative", "dative", "genitive", "locative"}
		local ret = {}
		
		for _, case in ipairs(cases) do
			local case_short = mw.ustring.sub(case, 1, 3)
		--	assert(false, case_short)
			table.insert(ret, '|-\n! style="background: #FAEBD7" | [[Appendix:Glossary#' .. case .. "_case|" .. case .. "]]\n")
			table.insert(ret, "| " .. show_form(data.forms[case_short .. "_sg"]) .. "\n")
			table.insert(ret, "| " .. show_form(data.forms[case_short .. "_du"]) .. "\n")
			if data.forms[case_short .. "_pl"] then
				table.insert(ret, "| " .. show_form(data.forms[case_short .. "_pl"]) .. "\n")
			end
		end
		return table.concat(ret)
	end

	local no_plural = data.forms.nom_pl == nil

	local wikicode = [=[
<div class="NavFrame" style="float: left; width: 45%;">
<div class="NavHead" style="text-align: center">Declension of {{{title}}} ({{{decl_type}}})</div>
<div class="NavContent">
{| style="width: 100%; line-height: 125%; background-color:#F9F9F9; text-align:center; border: 1px solid #CCCCFF;" cellpadding="3" cellspacing="1" class="inflection-table"
|- style="background-color:#EFEFEF; "
|-
| 
! style="width: ]=] .. (no_plural and "50%" or "33.33%") .. [=[; background-color:#F3E5AB" | singular 
! style="width: ]=] .. (no_plural and "50%" or "33.33%") .. [=[; background-color:#F3E5AB" | dual]=] .. (no_plural and "\n" or [=[

! style="width: 33.33%; background-color:#F3E5AB" | plural
]=]) .. make_cases(data) .. [=[
|}</div></div>
<br clear="all" />]=]

	return (mw.ustring.gsub(wikicode, "{{{([a-z0-9_]+)}}}", repl)) .. m_utils.format_categories(data.categories, lang)
end

return export