Модул:ine-nominals

Документацију овог модула можете да направите на страници Модул:ine-nominals/док

local m_utilities = require("Модул:utilities")
local m_links = require("Модул:links")
local m_common = require("Модул:ine-common")

local export = {}

local lang = require("Модул:languages").getByCode("ine-pro")

local endings = {
	["anim"] = {
		["athem"] = {
			["nom_sg"] = {"s"},
			["voc_sg"] = {""},
			["acc_sg"] = {"m̥"},
			["gen_sg"] = {{stressed = "és", unstressed = "s"}},
			["abl_sg"] = {{stressed = "és", unstressed = "s"}},
			["dat_sg"] = {"éy"},
			["loc_sg"] = {"", "i"},
			["ins_sg"] = {{stressed = "éh₁", unstressed = "h₁"}},
			
			["nom_du"] = {"h₁(e)"},
			["voc_du"] = {"h₁(e)"},
			["acc_du"] = {"h₁(e)"},
			["gen_du"] = "?",
			["abl_du"] = "?",
			["dat_du"] = "?",
			["loc_du"] = "?",
			["ins_du"] = "?",
			
			["nom_pl"] = {"es"},
			["voc_pl"] = {"es"},
			["acc_pl"] = {"m̥s"},
			["gen_pl"] = {"óHom"},
			["abl_pl"] = {"mós"},
			["dat_pl"] = {"mós"},
			["loc_pl"] = {"sú"},
			["ins_pl"] = {"bʰí"},
			},
		
		["them"] = {
			["nom_sg"] = {"ós"},
			["voc_sg"] = {"é"},
			["acc_sg"] = {"óm"},
			["gen_sg"] = {"ósyo"},
			["abl_sg"] = {"éad"},
			["dat_sg"] = {"óey"},
			["loc_sg"] = {"éy", "óy"},
			["ins_sg"] = {"óh₁"},
			
			["nom_du"] = {"óh₁"},
			["voc_du"] = {"óh₁"},
			["acc_du"] = {"óh₁"},
			["gen_du"] = "?",
			["abl_du"] = "?",
			["dat_du"] = "?",
			["loc_du"] = "?",
			["ins_du"] = "?",
			
			["nom_pl"] = {"óes"},
			["voc_pl"] = {"óes"},
			["acc_pl"] = {"óms"},
			["gen_pl"] = {"óoHom"},
			["abl_pl"] = {"ómos"},
			["dat_pl"] = {"ómos"},
			["loc_pl"] = {"óysu"},
			["ins_pl"] = {"ṓys"},
			},
		},
	
	["inan"] = {
		["athem"] = {
			["nom_sg"] = {""},
			["voc_sg"] = {""},
			["acc_sg"] = {""},
			
			["nom_du"] = {"ih₁"},
			["voc_du"] = {"ih₁"},
			["acc_du"] = {"ih₁"},
			
			["nom_pl"] = {"h₂"},
			["voc_pl"] = {"h₂"},
			["acc_pl"] = {"h₂"},
			},
		
		["them"] = {
			["nom_sg"] = {"óm"},
			["voc_sg"] = {"óm"},
			["acc_sg"] = {"óm"},
			
			["nom_du"] = {"óy(h₁)"},
			["voc_du"] = {"óy(h₁)"},
			["acc_du"] = {"óy(h₁)"},
			
			["nom_pl"] = {"éh₂"},
			["voc_pl"] = {"éh₂"},
			["acc_pl"] = {"éh₂"},
			},
		},
	
	["coll"] = {
		["athem"] = {
			["nom_sg"] = {"h₂"},
			["voc_sg"] = {"h₂"},
			["acc_sg"] = {"h₂"},
			},
		
		["them"] = {
			["nom_sg"] = {"éh₂"},
			["voc_sg"] = {"éh₂"},
			["acc_sg"] = {"éh₂"},
			},
		},
}

-- Copy over endings which are the same for animate and inanimate.
for _, t in ipairs({"athem", "them"}) do
	for cn, _ in pairs(endings["anim"][t]) do
		if not endings["inan"][t][cn] then
			endings["inan"][t][cn] = endings["anim"][t][cn]
		end
		
		if cn:find("_sg$") and not endings["coll"][t][cn] then
			endings["coll"][t][cn] = endings["anim"][t][cn]
		end
	end
end


local endings_pron = {
	["m"] = {
		["nom_sg"] = {"ós"},
		["acc_sg"] = {"óm"},
		["gen_sg"] = {"ósyo"},
		["abl_sg"] = {"ósmead"},
		["dat_sg"] = {"ósmey"},
		["loc_sg"] = {"ósmi"},
		["ins_sg"] = {"ónoh₁"},
		
		["nom_du"] = {"óh₁"},
		["acc_du"] = {"óh₁"},
		["gen_du"] = "?",
		["abl_du"] = "?",
		["dat_du"] = "?",
		["loc_du"] = "?",
		["ins_du"] = "?",
		
		["nom_pl"] = {"óy"},
		["acc_pl"] = {"óms"},
		["gen_pl"] = {"óysoHom"},
		["abl_pl"] = {"óymos"},
		["dat_pl"] = {"óymos"},
		["loc_pl"] = {"óysu"},
		["ins_pl"] = {"ṓys"},
		},
	
	["f"] = {
		["nom_sg"] = {"éh₂"},
		["acc_sg"] = {"éh₂m̥"},
		["gen_sg"] = {"ósyeh₂s"},
		["abl_sg"] = {"ósyeh₂s"},
		["dat_sg"] = {"ósyeh₂ey"},
		["loc_sg"] = {"ósyeh₂"},
		["ins_sg"] = {"éh₂(e)h₁"},
		
		["nom_du"] = "?",
		["acc_du"] = "?",
		["gen_du"] = "?",
		["abl_du"] = "?",
		["dat_du"] = "?",
		["loc_du"] = "?",
		["ins_du"] = "?",
		
		["nom_pl"] = {"éh₂es"},
		["acc_pl"] = {"éh₂m̥s"},
		["gen_pl"] = {"éh₂soHom"},
		["abl_pl"] = {"éh₂mos"},
		["dat_pl"] = {"éh₂mos"},
		["loc_pl"] = {"éh₂su"},
		["ins_pl"] = {"éh₂bʰi"},
		},
	
	["n"] = {
		["nom_sg"] = {"ód"},
		["acc_sg"] = {"ód"},
		
		["nom_du"] = {"óy"},
		["acc_du"] = {"óy"},
		
		["nom_pl"] = {"éh₂"},
		["acc_pl"] = {"éh₂"},
		},
}

-- Copy over endings which are the same for animate and inanimate.
for cn, _ in pairs(endings_pron["m"]) do
	if not endings_pron["n"][cn] then
		endings_pron["n"][cn] = endings_pron["m"][cn]
	end
end


local function inflect(data, prefix, endings, stem1, stem2, loc_sg_stem)
	stem2 = stem2 or stem1
	
	-- Is the stem thematic?
	local thematic_unstressed = false
	
	if mw.ustring.find(stem1, "[eoéó]$") then
		endings = mw.clone(endings.them or endings)
		
		if mw.ustring.find(stem1, "[eo]$") then
			thematic_unstressed = true
		end
		
		stem1 = mw.ustring.gsub(stem1, "[eoéó]$", "")
		stem2 = stem1
	else
		endings = endings.athem or endings
		
		if mw.ustring.find(stem1, "[eoéó]h₂$") and stem1 == stem2 then
			thematic_unstressed = true
		end
	end
	
	if not loc_sg_stem then
		if mw.ustring.find(stem2, "[áéíĺḿńóŕúḗṓ́]") then
			loc_sg_stem = stem2
		else
			loc_sg_stem = stem1
		end
	end
	
	local stem2_zero = stem2
	
	if mw.ustring.find(stem1, "[iu]$") then
		stem2_zero = mw.ustring.gsub(stem2, "é[wy]$", {["éw"] = "ú", ["éy"] = "í"})
	end
	
	local stem1_full = stem1
	
	if stem1 ~= stem2 and mw.ustring.gsub(stem1, "os$", "es") == stem2 then
		stem1_full = stem2
	end
	
	local nom_pl_stem = mw.ustring.gsub(stem1, "[íiu]$", {["í"] = "éy", ["i"] = "ey", ["u"] = "ew"})
	
	-- Go over each case-number combination
	for cn, cnendings in pairs(endings) do
		if cnendings == "?" then
			data.forms[(prefix and prefix .. "_" or "") .. cn] = {"?"}
		elseif cnendings then
			data.forms[(prefix and prefix .. "_" or "") .. cn] = {}
			
			for _, cnending in ipairs(cnendings) do
				local stem = stem1
				
				-- Use stem2 if the ending can be stressed, stem1 otherwise
				if cn == "loc_sg" then
					stem = loc_sg_stem
				elseif cn == "ins_sg" or cn == "abl_pl" or cn == "dat_pl" or cn == "loc_pl" or cn == "ins_pl" then
					stem = stem2_zero
				elseif (cn == "nom_du" or cn == "voc_du" or cn == "acc_du") then
					stem = stem1_full
				elseif (cn == "nom_pl" or cn == "voc_pl") and cnending == "es" then
					stem = nom_pl_stem
				elseif cnending.stressed or mw.ustring.find(cnending, "[áéíĺḿńóŕúḗṓ́]") then
					stem = stem2
				end
				
				local ending = (thematic_unstressed and (cnending.unstressed or m_common.destress(cnending))) or cnending.stressed or cnending
				local ending_unstr = cnending.unstressed
				
				if (cn == "gen_sg" or cn == "abl_sg") and ending_unstr == "s" and mw.ustring.find(stem, "s$") then
					ending_unstr = "os"
				end
				
				if mw.ustring.find(stem, "[iu]$") then
					if cn == "acc_sg" and ending == "m̥" then
						ending = "m"
					elseif cn == "acc_pl" and ending == "m̥s" then
						ending = "ms"
					end
				end
				
				if mw.ustring.find(stem, "[eéoóaáiíuú]h₂$") and cn == "nom_sg" and ending == "s" then
					ending = ""
				end
				
				if not (cnending == "i" and mw.ustring.find(stem, "i$")) then
					table.insert(data.forms[(prefix and prefix .. "_" or "") .. cn], m_common.add_ending(stem, ending, ending_unstr, cn == "nom_sg" and ending == "s"))
				end
			end
		end
	end
end

local function postprocess(data)
	for key, form in pairs(data.forms) do
		-- Do not show singular, dual or plural forms for nouns that don't have them
		if (not data.sg and key:find("_sg$")) or (not data.du and key:find("_du$")) or (not data.pl and key:find("_pl$")) or (not data.coll and key:find("_coll$")) then
			form = nil
		end
		
		data.forms[key] = form
	end
end

function export.masc(frame)
	local params = {
		[1] = {required = true},
		[2] = {},
		["nom_sg"] = {},
		["loc_sg"] = {},
		
		["coll"] = {},
		["coll2"] = {},
		["coll_loc"] = {},
		
		["ac"] = {},
		["n"] = {},
		}
	
	local args = require("Модул:parameters").process(frame:getParent().args, params)
	
	if mw.title.getCurrentTitle().nsText == "Шаблон" then
		args[1] = args[1] or "h₂éǵro"
	end
	
	args[2] = args[2] or args[1]
	
	local data = {forms = {}, title = nil, categories = {}}
	data.sg = true
	data.du = true
	data.pl = true
	data.coll = false
	data.voc = true
	
	if args["n"] then
		if not mw.ustring.find(args["n"], "s") then
			data.sg = false
		end
		
		if not mw.ustring.find(args["n"], "d") then
			data.du = false
		end
		
		if not mw.ustring.find(args["n"], "p") then
			data.pl = false
		end
	end
	
	if mw.ustring.find(args[1], "[eoéó]$") then
		data.info = "Thematic"
		table.insert(data.categories, lang:getCanonicalName() .. " thematic nouns")
	elseif mw.ustring.find(args[1], "[eoéó]h₂$") and args[1] == args[2] then
		data.info = "Thematic in " .. m_links.full_link({lang = lang, alt = "*-eh₂"}, "term")
		table.insert(data.categories, lang:getCanonicalName() .. " thematic nouns in *-eh₂")
	else
		data.info = "Athematic"
		
		if args["ac"] then
			data.info = data.info .. ", " .. args["ac"]
			table.insert(data.categories, lang:getCanonicalName() .. " " .. args["ac"] .. " именице")
		else
			table.insert(data.categories, lang:getCanonicalName() .. " athematic nouns")
		end
	end
	
	-- Create the forms
	inflect(data, nil, endings["anim"], args[1], args[2], args["loc_sg"])
	
	if args["nom_sg"] then
		data.forms["nom_sg"] = {args["nom_sg"]}
	end
	
	-- Collective
	if args["coll"] then
		args["coll2"] = args["coll2"] or args["coll"]
		data.coll = true
		
		local tempdata = {forms = {}}
		
		inflect(tempdata, nil, endings["coll"], args["coll"], args["coll2"], args["coll_loc"])
		
		for cn, forms in pairs(tempdata.forms) do
			if cn:find("_sg$") then
				local coll = cn:gsub("_sg$", "_coll")
				data.forms[coll] = forms
			end
		end
	end
	
	postprocess(data)
	
	return make_table(data)
end

function export.neut(frame)
	local params = {
		[1] = {required = true},
		[2] = {},
		["loc_sg"] = {},
		
		["coll"] = {},
		["coll2"] = {},
		["coll_loc"] = {},
		
		["ac"] = {},
		["n"] = {},
		}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	if mw.title.getCurrentTitle().nsText == "Шаблон" then
		args[1] = args[1] or "wérǵo"
	end
	
	args[2] = args[2] or args[1]
	
	local data = {forms = {}, title = nil, categories = {}}
	data.sg = true
	data.du = true
	data.pl = true
	data.coll = false
	data.voc = true
	
	if args["n"] then
		if not mw.ustring.find(args["n"], "s") then
			data.sg = false
		end
		
		if not mw.ustring.find(args["n"], "d") then
			data.du = false
		end
		
		if not mw.ustring.find(args["n"], "p") then
			data.pl = false
		end
	end
	
	if mw.ustring.find(args[1], "[eoéó]$") then
		data.info = "Thematic"
		table.insert(data.categories, lang:getCanonicalName() .. " thematic именице")
	else
		data.info = "Athematic"
		
		if args["ac"] then
			data.info = data.info .. ", " .. args["ac"]
			table.insert(data.categories, lang:getCanonicalName() .. " " .. args["ac"] .. " именице")
		else
			table.insert(data.categories, lang:getCanonicalName() .. " athematic именице")
		end
	end
	
	-- Create the forms
	inflect(data, nil, endings["inan"], args[1], args[2], args["loc_sg"])
	
	-- Collective
	if args["coll"] then
		args["coll2"] = args["coll2"] or args["coll"]
		data.coll = true
		
		local tempdata = {forms = {}}
		
		inflect(tempdata, nil, endings["coll"], args["coll"], args["coll2"], args["coll_loc"])
		
		for cn, forms in pairs(tempdata.forms) do
			if cn:find("_sg$") then
				local coll = cn:gsub("_sg$", "_coll")
				data.forms[coll] = forms
			end
		end
	end
	
	postprocess(data)
	
	return make_table(data)
end

function export.adj(frame)
	local params = {
		[1] = {required = true},
		[2] = {},
		["loc_sg"] = {},
		
		[3] = {},
		[4] = {},
		
		["ac"] = {},
		["n"] = {},
		}
	
	local args = require("Модул:parameters").process(frame:getParent().args, params)
	
	if mw.title.getCurrentTitle().nsText == "Шаблон" then
		args[1] = args[1] or "néwo"
	end
	
	args[2] = args[2] or args[1]
	
	local data = {forms = {}, title = nil, categories = {}}
	data.genders = true
	data.sg = true
	data.du = true
	data.pl = true
	data.voc = true
	
	if args["n"] then
		if not mw.ustring.find(args["n"], "s") then
			data.sg = false
		end
		
		if not mw.ustring.find(args["n"], "d") then
			data.du = false
		end
		
		if not mw.ustring.find(args["n"], "p") then
			data.pl = false
		end
	end
	
	if mw.ustring.find(args[1], "[eoéó]$") then
		data.info = "Thematic"
		table.insert(data.categories, lang:getCanonicalName() .. " thematic adjectives")
		
		if not args[3] then
			args[3] = mw.ustring.gsub(args[1], "[eoéó]$", {["e"] = "eh₂", ["o"] = "eh₂", ["é"] = "éh₂", ["ó"] = "éh₂"})
			args[4] = args[3]
		end
	else
		data.info = "Athematic"
		
		if args["ac"] then
			data.info = data.info .. ", " .. args["ac"]
			table.insert(data.categories, lang:getCanonicalName() .. " " .. args["ac"] .. " adjectives")
		else
			table.insert(data.categories, lang:getCanonicalName() .. " athematic adjectives")
		end
	end
	
	-- Create the forms
	inflect(data, "m", endings["anim"], args[1], args[2], args["loc_sg"])
	inflect(data, "f", endings["anim"], args[3], args[4])
	inflect(data, "n", endings["inan"], args[1], args[2], args["loc_sg"])
	
	postprocess(data)
	
	return make_table(data)
end

function export.pron_adj(frame)
	local params = {
		[1] = {required = true},
		
		["m_nom_sg"] = {},
		["f_nom_sg"] = {},
		}
	
	local args = require("Модул:parameters").process(frame:getParent().args, params)
	
	if mw.title.getCurrentTitle().nsText == "Шаблон" then
		args[1] = args[1] or "h₂élyo"
	end
	
	local data = {forms = {}, title = nil, categories = {}}
	data.genders = true
	data.sg = true
	data.du = true
	data.pl = true
	data.voc = false
	
	if mw.ustring.find(args[1], "[eoéó]$") then
		data.info = "Thematic pronominal"
	else
		error("Thematic only for now.")
	end
	
	-- Create the forms
	inflect(data, "m", endings_pron["m"], args[1])
	inflect(data, "f", endings_pron["f"], args[1])
	inflect(data, "n", endings_pron["n"], args[1])
	
	data.forms["m_nom_sg"] = args["m_nom_sg"] and {args["m_nom_sg"]} or data.forms["m_nom_sg"]
	data.forms["f_nom_sg"] = args["f_nom_sg"] and {args["f_nom_sg"]} or data.forms["f_nom_sg"]
	
	postprocess(data)
	
	return make_table(data)
end


local names = {
	["nom"] = "nominative",
	["voc"] = "vocative",
	["acc"] = "accusative",
	["gen"] = "genitive",
	["abl"] = "ablative",
	["dat"] = "dative",
	["loc"] = "locative",
	["ins"] = "instrumental",
	
	["sg"] = "singular",
	["du"] = "dual",
	["pl"] = "plural",
	["coll"] = "collective",
	
	["m"] = "masculine",
	["f"] = "feminine",
	["n"] = "neuter",
}

-- Make the table
function make_table(data)
	local function repl(param)
		if param == "info" then
			return mw.getContentLanguage():ucfirst(data.info or "")
		end
		
		local form = data.forms[param]
		
		if not form or #form == 0 then
			return "—"
		end
		
		local ret = {}
		
		for key, subform in ipairs(form) do
			table.insert(ret, m_links.full_link({lang = lang, alt = "*" .. subform}))
		end
		
		return table.concat(ret, ", ")
	end
	
	local numbers = {"sg", "du", "pl"}
	local genders = {"x"}
	local cases = {"nom", "acc", "gen", "abl", "dat", "loc", "ins"}
	
	if data.voc then
		table.insert(cases, 2, "voc")
	end
	
	if data.genders then
		genders = {"m", "f", "n"}
	elseif data.coll then
		table.insert(numbers, "coll")
	end
	
	local first_number = "sg"
	
	if not data.sg then
		first_number = "du"
		
		if not data.du then
			first_number = "pl"
		end
	end
	
	local wikicode = {}
	
	table.insert(wikicode, "{| class=\"inflection-table vsSwitcher vsToggleCategory-inflection\" style=\"background: #FAFAFA; border: 1px solid #d0d0d0; text-align: left;\" cellspacing=\"1\" cellpadding=\"2\"")
	table.insert(wikicode, "|- style=\"background: #CCCCFF;\"\n! class=\"vsToggleElement\" colspan=\"" .. (#numbers + 1) .. "\" | {{{info}}}")
	
	table.insert(wikicode, "|- class=\"vsShow\" style=\"background: #CCCCFF;\"")
	table.insert(wikicode, "!")
	
	if data.genders then
		table.insert(wikicode, "! style=\"min-width: 11em; background: #CCCCFF;\" | " .. names["m"])
		table.insert(wikicode, "! style=\"min-width: 11em; background: #CCCCFF;\" | " .. names["f"])
	else
		table.insert(wikicode, "! style=\"min-width: 11em; background: #CCCCFF;\" | " .. names[first_number])
		
		if data.coll then
			table.insert(wikicode, "! style=\"min-width: 11em; background: #CCCCFF;\" | " .. names["coll"])
		end
	end
	
	table.insert(wikicode, "|- class=\"vsShow\" style=\"background: #F2F2FF;\"")
	table.insert(wikicode, "! style=\"min-width: 8em; background: #E6E6FF;\" | " .. names["nom"])
	
	if data.genders then
		table.insert(wikicode, "| style=\"min-width: 11em;\" | {{{m_nom_" .. first_number .. "}}}")
		table.insert(wikicode, "| style=\"min-width: 11em;\" | {{{f_nom_" .. first_number .. "}}}")
	else
		table.insert(wikicode, "| style=\"min-width: 11em;\" | {{{nom_" .. first_number .. "}}}")
		
		if data.coll then
			table.insert(wikicode, "| style=\"min-width: 11em;\" | {{{nom_coll}}}")
		end
	end
	
	table.insert(wikicode, "|- class=\"vsShow\" style=\"background: #F2F2FF;\"")
	table.insert(wikicode, "! style=\"min-width: 8em; background: #E6E6FF;\" | " .. names["gen"])
	
	if data.genders then
		table.insert(wikicode, "| style=\"min-width: 11em;\" | {{{m_gen_" .. first_number .. "}}}")
		table.insert(wikicode, "| style=\"min-width: 11em;\" | {{{f_gen_" .. first_number .. "}}}")
	else
		table.insert(wikicode, "| style=\"min-width: 11em;\" | {{{gen_" .. first_number .. "}}}")
		
		if data.coll then
			table.insert(wikicode, "| style=\"min-width: 11em;\" | {{{gen_coll}}}")
		end
	end
	
	for _, gender in ipairs(genders) do
		table.insert(wikicode, "|- class=\"vsHide\" style=\"background: #CCCCFF;\"")
		
		if data.genders then
			table.insert(wikicode, "! " .. names[gender])
		else
			table.insert(wikicode, "!")
		end
		
		for _, number in ipairs(numbers) do
			table.insert(wikicode, "! style=\"min-width: 11em; background: #CCCCFF;\" | " .. names[number])
		end
		
		for _, case in ipairs(cases) do
			table.insert(wikicode, "|- class=\"vsHide\" style=\"background-color: #F2F2FF;\"\n! style=\"min-width: 8em; background-color: #E6E6FF;\" | " .. names[case])
			
			for _, number in ipairs(numbers) do
				if data.genders then
					table.insert(wikicode, "| {{{" .. gender .. "_" .. case .. "_" .. number .. "}}}")
				else
					table.insert(wikicode, "| {{{" .. case .. "_" .. number .. "}}}")
				end
			end
		end
	end
	
	table.insert(wikicode, [=[|}]=])
	
	wikicode = table.concat(wikicode, "\n")
	
	return (mw.ustring.gsub(wikicode, "{{{([a-z0-9_]+)}}}", repl)) .. m_utilities.format_categories(data.categories, lang)
end

return export