モジュール:vep-nominals

出典: フリー多機能辞典『ウィクショナリー日本語版(Wiktionary)』
ナビゲーションに移動 検索に移動

このモジュールについての説明文ページを モジュール:vep-nominals/doc に作成できます

local m_utilities = require("モジュール:utilities")
local m_links = require("モジュール:links")

local export = {}

local lang = require("モジュール:languages").getByCode("vep")

-- Functions that do the actual inflecting by creating the forms of a basic term.
local inflections = {}

-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
	local infl_type = frame.args[1] or error("Inflection type has not been specified. Please pass parameter 1 to the module invocation")
	local args = frame:getParent().args
	
	if not inflections[infl_type] then
		error("Unknown inflection type '" .. infl_type .. "'")
	end
	
	local data = {forms = {}, title = mw.title.getCurrentTitle().text, info = nil, categories = {}}
	data.n = args["n"]; if data.n == "" then data.n = nil end
	
	if mw.title.getCurrentTitle().namespace == 10 then
		data.title = args["title"] or data.title
	end

    local lemma = data.title
    if args["suffix"] and #args["suffix"] > 0 then
        local suffix = args["suffix"]
        if mw.ustring.sub(lemma, -mw.ustring.len(suffix)) ~= suffix then
            error("|suffix= does not match the lemma")
        end
        lemma = mw.ustring.sub(lemma, 1, -mw.ustring.len(suffix) - 1)
    end
    data.lemma = lemma
    
	-- Generate the forms
	inflections[infl_type](args, data)
	
	-- Postprocess
	if infl_type ~= "ppron" then
		postprocess(args, data)
	end
	
	return make_table(data) .. m_utilities.format_categories(data.categories, lang)
end


--[=[
	Inflection functions
]=]--

local function get_param(args, first, default)
	default = default or ""
	local param = args[first] or default
	
	if param == default and mw.title.getCurrentTitle().nsText == "テンプレート" then
		return "{{{" .. first .. "}}}"
	end
	
	return param
end

local function append(stems, suffix)
	local result = {}
	for _, stem in ipairs(stems) do
		table.insert(result, stem .. suffix)
	end
	return result
end

local function shorten_illative(stem, ending)
	if mw.ustring.match(ending, "^h") and mw.ustring.match(stem, "[aeiouäöü]$") then
		return mw.ustring.sub(stem, 1, -2)
	end
	-- return nothing
end

inflections["ppron"] = function(args, data)
	local person = args[1]
	
	if not person or person == "" then
		error("Please specify the person, 1, 2 or 3.")
	else
		person = tonumber(person)
	end
	
	local sg_letter
	local sg
	local pl
	
	if person == 1 then
		sg_letter = "m"
		sg = "minu"
		pl = "m"
	elseif person == 2 then
		sg_letter = "s"
		sg = "sinu"
		pl = "t"
	elseif person == 3 then
		sg_letter = "h"
		sg = "häne"
		pl = "h"
	end
	
	data.forms["nom_sg"] = {person == 3 and "hän" or sg_letter .. "inä"}
	data.forms["acc_sg"] = {sg .. "n"}
	data.forms["gen_sg"] = {sg .. "n"}
	data.forms["par_sg"] = {person == 3 and "händast" or sg_letter .. "indai"}
	
	data.forms["ine_sg"] = {sg .. "s"}
	data.forms["ela_sg"] = {sg .. "späi"}
	data.forms["ill_sg"] = {sg .. "h" .. (person == 3 and "e" or "u")}
	
	data.forms["ade_sg"] = {person == 3 and "hänel" or sg_letter .. "inai"}
	data.forms["abl_sg"] = {person == 3 and "hänelpäi" or sg_letter .. "inaipäi"}
	data.forms["all_sg"] = {person == 3 and "hänele" or sg_letter .. "inei"}
	
	data.forms["abe_sg"] = {sg .. "ta"}
	data.forms["com_sg"] = {sg .. "nke"}
	
	data.forms["nom_pl"] = {pl .. "ö"}
	data.forms["acc_pl"] = {pl .. "ö"}
	data.forms["gen_pl"] = {pl .. "eiden"}
	data.forms["par_pl"] = {pl .. "eid"}
	
	data.forms["ine_pl"] = {pl .. "eiš"}
	data.forms["ela_pl"] = {pl .. "eišpäi"}
	data.forms["ill_pl"] = {pl .. "eihe"}
	
	data.forms["ade_pl"] = {pl .. "eil"}
	data.forms["abl_pl"] = {pl .. "eilpäi"}
	data.forms["all_pl"] = {pl .. "eile"}
	
	data.forms["abe_pl"] = {pl .. "eita"}
	data.forms["com_pl"] = {pl .. "eidenke"}
end

inflections["ken"] = function(args, data)
	data.forms["nom_sg"] = {"ken"}
	data.forms["acc_sg"] = {"kenen"}
	data.forms["gen_sg"] = {"kenen"}
	data.forms["par_sg"] = {"keda"}
	data.forms["ess_sg"] = {"kenen"}
	data.forms["tra_sg"] = {"keneks"}
	
	data.forms["ine_sg"] = {"kes", "kenes"}
	data.forms["ela_sg"] = {"kespäi", "kenespäi"}
	data.forms["ill_sg"] = {"kehe", "kenehe"}
	
	data.forms["ade_sg"] = {"kel", "kenel"}
	data.forms["abl_sg"] = {"kelpäi", "kenelpäi"}
	data.forms["all_sg"] = {"kelle", "kenele"}
	
	data.forms["abe_sg"] = {"keneta"}
	data.forms["com_sg"] = {"kenenke"}
	data.forms["pro_sg"] = {"kedame"}
	
	data.forms["ap1_sg"] = {"kenenno"}
	data.forms["ap2_sg"] = {"kenennoks"}
	data.forms["egr_sg"] = {"kenennopäi"}
	
	data.forms["te1_sg"] = {"kehesai", "kenehesai"}
	data.forms["te2_sg"] = {"kellesai", "kenelesai"}
	
	data.forms["ad1_sg"] = {"kehepäi", "kenehepäi"}
	data.forms["ad2_sg"] = {"kellepäi", "kenelepäi"}
	
	if args["prefix"] == "" and args["suffix"] == "" then
		data.forms["nom_pl"] = {"ked"}
	end
end

inflections["mi"] = function(args, data)
	data.forms["nom_sg"] = {"mi"}
	data.forms["acc_sg"] = {"min"}
	data.forms["gen_sg"] = {"min"}
	data.forms["par_sg"] = {"midä"}
	data.forms["ess_sg"] = {"min"}
	data.forms["tra_sg"] = {"mikš"}
	
	data.forms["ine_sg"] = {"miš"}
	data.forms["ela_sg"] = {"mišpäi"}
	data.forms["ill_sg"] = {"mihe"}
	
	data.forms["ade_sg"] = {"mil"}
	data.forms["abl_sg"] = {"milpäi"}
	data.forms["all_sg"] = {"mille"}
	
	data.forms["abe_sg"] = {"mita"}
	data.forms["com_sg"] = {"minke"}
	data.forms["pro_sg"] = {"midäme"}
	
	data.forms["ap1_sg"] = {"minno"}
	data.forms["ap2_sg"] = {"minnoks"}
	data.forms["egr_sg"] = {"minnopäi"}
	
	data.forms["te1_sg"] = {"mihesai"}
	data.forms["te2_sg"] = {"millesai"}
	
	data.forms["ad1_sg"] = {"mihepäi"}
	data.forms["ad2_sg"] = {"millepäi"}
	
	if args["prefix"] == "" and args["suffix"] == "" then
		data.forms["nom_pl"] = {"mid"}
	end
end

inflections["se"] = function(args, data)
	-- Singular
	data.forms["nom_sg"] = {"se"}
	data.forms["acc_sg"] = {"sen"}
	data.forms["gen_sg"] = {"sen"}
	data.forms["par_sg"] = {"sidä"}
	data.forms["ess_sg"] = {"sen"}
	data.forms["tra_sg"] = {"sikš"}
	
	data.forms["ine_sg"] = {"siš"}
	data.forms["ela_sg"] = {"sišpäi"}
	data.forms["ill_sg"] = {"sihe"}
	
	data.forms["ade_sg"] = {"sil"}
	data.forms["abl_sg"] = {"silpäi"}
	data.forms["all_sg"] = {"sile"}
	
	data.forms["abe_sg"] = {"sita"}
	data.forms["com_sg"] = {"senke"}
	data.forms["pro_sg"] = {"sidäme"}
	
	data.forms["ap1_sg"] = {"senno"}
	data.forms["ap2_sg"] = {"sennoks"}
	data.forms["egr_sg"] = {"sennopäi"}
	
	data.forms["te1_sg"] = {"sihesai"}
	data.forms["te2_sg"] = {"silesai"}
	
	data.forms["ad1_sg"] = {"sihepäi"}
	data.forms["ad2_sg"] = {"silepäi"}
	
	-- Plural
	data.forms["nom_pl"] = {"ne", "ned"}
	data.forms["acc_pl"] = {"ne", "ned"}
	data.forms["gen_pl"] = {"niiden"}
	data.forms["par_pl"] = {"niid"}
	data.forms["ess_pl"] = nil
	data.forms["tra_pl"] = {"niikš"}
	
	data.forms["ine_pl"] = {"niiš"}
	data.forms["ela_pl"] = {"niišpäi"}
	data.forms["ill_pl"] = {"niihe"}
	
	data.forms["ade_pl"] = {"niil"}
	data.forms["abl_pl"] = {"niilpäi"}
	data.forms["all_pl"] = {"niile"}
	
	data.forms["abe_pl"] = {"niita"}
	data.forms["com_pl"] = {"niidenke"}
	data.forms["pro_pl"] = {"niidme"}
	
	data.forms["ap1_pl"] = {"niidenno"}
	data.forms["ap2_pl"] = {"niidennoks"}
	data.forms["egr_pl"] = {"niidennopäi"}
	
	data.forms["te1_pl"] = {"niihesai"}
	data.forms["te2_pl"] = {"niilesai"}
	data.forms["te3_pl"] = nil
	
	data.forms["ad1_pl"] = {"niihepäi"}
	data.forms["ad2_pl"] = {"niilepäi"}
end

inflections["nece"] = function(args, data)
	-- Singular
	data.forms["nom_sg"] = {"nece"}
	data.forms["acc_sg"] = {"necen"}
	data.forms["gen_sg"] = {"necen"}
	data.forms["par_sg"] = {"necidä"}
	data.forms["ess_sg"] = {"necen"}
	data.forms["tra_sg"] = {"necikš"}
	
	data.forms["ine_sg"] = {"neciš"}
	data.forms["ela_sg"] = {"necišpäi"}
	data.forms["ill_sg"] = {"neche"}
	
	data.forms["ade_sg"] = {"necil"}
	data.forms["abl_sg"] = {"necilpäi"}
	data.forms["all_sg"] = {"necile"}
	
	data.forms["abe_sg"] = {"necita"}
	data.forms["com_sg"] = {"necenke"}
	data.forms["pro_sg"] = {"necidäme"}
	
	data.forms["ap1_sg"] = {"necenno"}
	data.forms["ap2_sg"] = {"necennoks"}
	data.forms["egr_sg"] = {"necennopäi"}
	
	data.forms["te1_sg"] = {"nechesai"}
	data.forms["te2_sg"] = {"necilesai"}
	
	data.forms["ad1_sg"] = {"nechepäi"}
	data.forms["ad2_sg"] = {"necilepäi"}
	
	-- Plural
	data.forms["nom_pl"] = {"nene", "nened"}
	data.forms["acc_pl"] = {"nene", "nened"}
	data.forms["gen_pl"] = {"neniden"}
	data.forms["par_pl"] = {"nenid"}
	data.forms["ess_pl"] = nil
	data.forms["tra_pl"] = {"nenikš"}
	
	data.forms["ine_pl"] = {"neniš"}
	data.forms["ela_pl"] = {"nenišpäi"}
	data.forms["ill_pl"] = {"nenihe"}
	
	data.forms["ade_pl"] = {"nenil"}
	data.forms["abl_pl"] = {"nenilpäi"}
	data.forms["all_pl"] = {"nenile"}
	
	data.forms["abe_pl"] = {"nenita"}
	data.forms["com_pl"] = {"nenidenke"}
	data.forms["pro_pl"] = {"nenidme"}
	
	data.forms["ap1_pl"] = {"nenidenno"}
	data.forms["ap2_pl"] = {"nenidennoks"}
	data.forms["egr_pl"] = {"nenidennopäi"}
	
	data.forms["te1_pl"] = {"nenihesai"}
	data.forms["te2_pl"] = {"nenilesai"}
	data.forms["te3_pl"] = nil
	
	data.forms["ad1_pl"] = {"nenihepäi"}
	data.forms["ad2_pl"] = {"nenilepäi"}
end

--[=[
	New auto-inflection types
]=]--

local function add_info(data, number, specimen)
	data.info = "inflection type " .. number .. "/" .. m_links.full_link({lang = lang, term = specimen}, "term")
	table.insert(data.categories, lang:getCanonicalName() .. " " .. specimen .. "-type nominals")
end

local function extract_stem(stem, suffix)
	local result = mw.ustring.match(stem, suffix .. "$")
	if not result then
		error("Unsupported stem for this inflection type")
	end
	return mw.ustring.gsub(stem, suffix .. "$", ""), result
end

local function get_final_consonant(stem)
	local stem, final = mw.ustring.match(stem, "(.-)([^aeiouäöü]'?)$")
	if not stem then
		error("Unsupported stem for this inflection type")
	end
	return stem, final
end

-- short_ill_type (nil = 0: none, 1: common, 2: rare)
local DEFAULT_SHORT_ILL_FILTER = "[cčflstz][aeiouüäö]$"
local function generate_from_stems(args, data, nom_sg, gen_sg, par_sg, par_pl, short_ill_type, short_ill_filter)
	local palatalize_sg = mw.ustring.find(gen_sg, "i$")
	local palatalize_pl = mw.ustring.find(par_pl, "i$")
    local ill_sg = gen_sg

	local s_sg = palatalize_sg and "š" or "s"
	local s_pl = palatalize_pl and "š" or "s"

	local ill_sg_ending, ill_pl_ending
	
	short_ill_type = short_ill_type or 0
	if short_ill_type > 0 and short_ill_filter and not mw.ustring.find(ill_sg, short_ill_filter) then
		short_ill_type = 0
	end

	if mw.ustring.find(gen_sg, "h[aeiouäöü]+$") then
		ill_sg_ending = palatalize_sg and "že" or "ze"
	else
		local vowel = mw.ustring.match(gen_sg, "([aeiouäöü])$") or "a"
		ill_sg_ending = "h" .. (vowel == "i" and "e" or vowel)
	end

	if mw.ustring.find(par_pl, "h[aeiouäöü]+$") then
		ill_pl_ending = mw.ustring.find(par_pl, "i$") and "že" or "ze"
	elseif n ~= "sg" then
		local vowel = mw.ustring.match(par_pl, "([aeiouäöü])$") or "i"
		ill_pl_ending = "h" .. (vowel == "i" and "e" or vowel)
	end
	
	local short_ill
	if short_ill_type > 0 then
		local alt_stem = shorten_illative(ill_sg, ill_sg_ending)
		if alt_stem then
			short_ill = alt_stem .. ill_sg_ending
		end
	end
	
	-- Singular
	data.forms["nom_sg"] = {nom_sg}
	data.forms["acc_sg"] = {gen_sg .. "n"}
	data.forms["gen_sg"] = {gen_sg .. "n"}
	data.forms["par_sg"] = {par_sg}
	data.forms["ess_sg"] = {gen_sg .. "n"}
	data.forms["tra_sg"] = {gen_sg .. "k" .. s_sg}
	
	data.forms["ine_sg"] = {gen_sg .. s_sg}
	data.forms["ela_sg"] = {gen_sg .. s_sg .. "päi"}
	data.forms["ill_sg"] = {ill_sg .. ill_sg_ending}
	if short_ill then table.insert(data.forms["ill_sg"], short_ill_type, short_ill) end
	
	data.forms["ade_sg"] = {gen_sg .. "l"}
	data.forms["abl_sg"] = {gen_sg .. "lpäi"}
	data.forms["all_sg"] = {gen_sg .. "le"}
	
	data.forms["abe_sg"] = {gen_sg .. "ta"}
	data.forms["com_sg"] = {gen_sg .. "nke"}
	data.forms["pro_sg"] = {par_sg .. "me"}
	
	data.forms["ap1_sg"] = {gen_sg .. "nno"}
	data.forms["ap2_sg"] = {gen_sg .. "nnoks"}
	data.forms["egr_sg"] = {gen_sg .. "nnopäi"}
	
	data.forms["te1_sg"] = append(data.forms["ill_sg"], "sai")
	data.forms["te2_sg"] = {gen_sg .. "lesai"}
	data.forms["te3_sg"] = {gen_sg .. "ssai"}
	
	data.forms["ad1_sg"] = append(data.forms["ill_sg"], "päi")
	data.forms["ad2_sg"] = {gen_sg .. "lepäi"}
	
	-- Plural
	data.forms["nom_pl"] = {gen_sg .. "d"}
	data.forms["acc_pl"] = {gen_sg .. "d"}
	data.forms["gen_pl"] = {par_pl .. "den"}
	data.forms["par_pl"] = {par_pl .. "d"}
	data.forms["ess_pl"] = {par_pl .. "n"}
	data.forms["tra_pl"] = {par_pl .. "k" .. s_pl}
	
	data.forms["ine_pl"] = {par_pl .. s_pl}
	data.forms["ela_pl"] = {par_pl .. s_pl .. "päi"}
	data.forms["ill_pl"] = {par_pl .. ill_pl_ending}
	
	data.forms["ade_pl"] = {par_pl .. "l"}
	data.forms["abl_pl"] = {par_pl .. "lpäi"}
	data.forms["all_pl"] = {par_pl .. "le"}
	
	data.forms["abe_pl"] = {par_pl .. "ta"}
	data.forms["com_pl"] = {par_pl .. "denke"}
	data.forms["pro_pl"] = {par_pl .. "dme"}
	
	data.forms["ap1_pl"] = {par_pl .. "denno"}
	data.forms["ap2_pl"] = {par_pl .. "dennoks"}
	data.forms["egr_pl"] = {par_pl .. "dennopäi"}
	
	data.forms["te1_pl"] = {par_pl .. ill_pl_ending .. "sai"}
	data.forms["te2_pl"] = {par_pl .. "lesai"}
	data.forms["te3_pl"] = nil
	
	data.forms["ad1_pl"] = {par_pl .. ill_pl_ending .. "päi"}
	data.forms["ad2_pl"] = {par_pl .. "lepäi"}
end

inflections["ilo"] = function(args, data)
	local stem = args[1]
	if not stem or not mw.ustring.find(stem, "[ouöü]$") then
		error("A stem ending in -o, -u, -ö, -ü, equivalent to the genitive singular without the final -n, must be specified.")
	end
	add_info(data, 1, "ilo")
	return generate_from_stems(args, data, data.lemma,
			stem, stem .. "d", stem .. "i",
			1, DEFAULT_SHORT_ILL_FILTER)
end

inflections["samal"] = function(args, data)
	local stem = data.lemma
	local vowel = args[1] or error("The final vowel must be provided.")
	if data.n == "pl" then
		stem = extract_stem(stem, "d")
    else
		stem = extract_stem(stem, "[aä]l'?") .. "l" .. vowel
	end
	add_info(data, 1, "samal")
	return generate_from_stems(args, data, data.lemma,
			stem, stem .. "d", stem .. "i",
			1, DEFAULT_SHORT_ILL_FILTER)
end

inflections["kodi"] = function(args, data)
	local stem = args[1]
	if not stem or not mw.ustring.find(stem, "i$") then
		error("A stem ending in -i, equivalent to the genitive singular without the final -n, must be specified.")
	end
	add_info(data, 2, "kodi")
	return generate_from_stems(args, data, data.lemma,
			stem, stem .. "d", stem,
			1, DEFAULT_SHORT_ILL_FILTER)
end

inflections["kivi"] = function(args, data)
	local stem = args[1]
	if not stem or not mw.ustring.find(stem, "e$") then
		error("A stem ending in -e, equivalent to the genitive singular without the final -n, must be specified.")
	end
	add_info(data, 3, "kivi")
	return generate_from_stems(args, data, data.lemma,
			stem, stem .. "d", mw.ustring.sub(stem, 1, -2) .. "i",
			2, DEFAULT_SHORT_ILL_FILTER)
end

inflections["meri"] = function(args, data)
	local stem = args[1]
	if not stem or not mw.ustring.find(stem, "e$") then
		error("A stem ending in -e, equivalent to the genitive singular without the final -n, must be specified.")
	end
	add_info(data, 4, "meri")
	local part_stem
	if mw.ustring.find(data.lemma, "i$") then
		part_stem = mw.ustring.sub(stem, 1, -2) .. "t"
	else
		part_stem = data.lemma .. "t"
	end
	return generate_from_stems(args, data, data.lemma,
			stem, part_stem, mw.ustring.sub(stem, 1, -2) .. "i",
			2, DEFAULT_SHORT_ILL_FILTER)
end

inflections["sana"] = function(args, data)
	local stem = args[1]
	if not stem or not mw.ustring.find(stem, "[aä]$") then
		error("A stem ending in -a or -ä, equivalent to the genitive singular without the final -n, must be specified.")
	end
	add_info(data, 5, "sana")
	return generate_from_stems(args, data, data.lemma,
			stem, stem .. "d", mw.ustring.sub(stem, 1, -2) .. "oi",
			2, DEFAULT_SHORT_ILL_FILTER)
end

inflections["kuva"] = function(args, data)
	local stem = args[1]
	if not stem or not mw.ustring.find(stem, "[aä]$") then
		error("A stem ending in -a or -ä, equivalent to the genitive singular without the final -n, must be specified.")
	end
	add_info(data, 6, "kuva")
	return generate_from_stems(args, data, data.lemma,
			stem, stem .. "d", mw.ustring.gsub(mw.ustring.gsub(mw.ustring.sub(stem, 1, -2), "'$", ""), "([^aeiouäöü])j$", "%1jj") .. "i",
			2, DEFAULT_SHORT_ILL_FILTER)
end

inflections["pedai"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "jad") .. "ja"
	else
		stem = extract_stem(stem, "i") .. "ja"
	end
	add_info(data, 7, "pedai")
	return generate_from_stems(args, data, data.lemma,
			stem, stem .. "d", mw.ustring.sub(stem, 1, -2) .. "i", 0)
end

inflections["abai"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "d")
	else
		stem = extract_stem(stem, "i") .. "jo"
	end
	add_info(data, 8, "abai")
	return generate_from_stems(args, data, data.lemma,
			stem, stem .. "d", stem.. "i", 0)
end

inflections["čai"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "d")
	else
		stem = extract_stem(stem, "i") .. "ju"
	end
	add_info(data, 9, "čai")
	return generate_from_stems(args, data, data.lemma,
			stem, stem .. "d", stem .. "i", 0)
end

inflections["Biblii"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "ad")
	else
		stem = extract_stem(stem, "i") .. "j"
	end
	add_info(data, 10, "Biblii")
	return generate_from_stems(args, data, data.lemma,
			stem .. "a", stem .. "ad", stem .. "oi", 0)
end

inflections["kofe"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "d")
	end
	add_info(data, 11, "kofe")
	return generate_from_stems(args, data, data.lemma,
			stem, stem .. "d", stem .. "i",
			2, DEFAULT_SHORT_ILL_FILTER)
end

inflections["korged"] = function(args, data)
	local stem = data.lemma
	local strong, weak
	if data.n == "pl" then
		stem = extract_stem(stem, "tad")
	else
		stem = extract_stem(stem, "ed")
		if mw.ustring.match(stem, "[ht]k$") then
			stem = stem
		else
			stem = mw.ustring.sub(stem, 1, -2) .. ({g = "k", k = "t"})[mw.ustring.sub(stem, -1, -1)] or error("Unsupported word for type 8")
		end
	end
	add_info(data, 12, "korged")
	return generate_from_stems(args, data, data.lemma,
			stem .. "ta", stem .. "ta", stem .. "toi", 0)
end

inflections["ma"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "d")
	end
	local pl_stem = mw.ustring.gsub(stem .. "i", "ii$", "i")
	add_info(data, 13, "ma")
	return generate_from_stems(args, data, data.lemma, stem, stem .. "d", pl_stem, 0)
end

inflections["lumi"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "d")
	else
		if mw.ustring.find(stem, "[i']$") then
			stem = mw.ustring.sub(stem, 1, -2)
		end
		stem = stem .. "e"
	end
	if not mw.ustring.find(stem, "me$") then
		error("Unsupported word for type 10")
	end
	stem = mw.ustring.sub(stem, 1, -3)
	add_info(data, 14, "lumi")
	return generate_from_stems(args, data, data.lemma,
			stem .. "me", stem .. "nt", stem .. "mi",
            2, DEFAULT_SHORT_ILL_FILTER)
end

inflections["kümne"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "d")
	end
	stem = extract_stem(stem, "e")
	add_info(data, 15, "kümne")
	return generate_from_stems(args, data, data.lemma,
			stem .. "e", stem .. "ed", stem .. "i", 0)
end

inflections["katuz"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "ed")
	else
		local final
		stem, final = get_final_consonant(stem)
		if final == "z'" then
			stem = stem .. "z"
		elseif mw.ustring.match(final, "[sz]'?") then
			stem = stem .. "s"
		else
			error("Unsupported stem for type 12")
		end
	end
	add_info(data, 16, "katuz")
	return generate_from_stems(args, data, data.lemma,
			stem .. "e", stem .. "t", stem .. "i", 0)
end

inflections["laps'"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "ed")
	else
		stem = mw.ustring.gsub(stem, "'$", "")
	end
	stem = extract_stem(stem, "ps")
	add_info(data, 17, "laps'")
	return generate_from_stems(args, data, data.lemma,
			stem .. "pse", stem .. "st", stem .. "psi", 0)
end

inflections["vezi"] = function(args, data)
	local stem = data.lemma
	local z = "z"
	if data.n == "pl" then
		stem = extract_stem(stem, "ded")
	else
		local final
		stem, final = extract_stem(stem, "[szž]['i]?")
		if mw.ustring.find(final, "ž") then z = "ž" end
	end
	add_info(data, 18, "vezi")
	return generate_from_stems(args, data, data.lemma,
			stem .. "de", stem .. "t", stem .. z .. "i",
			2, DEFAULT_SHORT_ILL_FILTER)
end

inflections["veič"] = function(args, data)
	local stem = data.lemma
	local final
	if data.n == "pl" then
		stem, final = extract_stem(stem, "i[cč]ed")
	else
		stem, final = extract_stem(stem, "i[cč]'?")
	end
	local strong = "c"
	local weak = "s"
	if mw.ustring.find(final, "č") then strong, weak = "č", "š" end
	add_info(data, 19, "veič")
	return generate_from_stems(args, data, data.lemma,
			stem .. "i" .. strong .. "e", stem .. weak .. "t", stem .. "i" .. strong .. "i",
			2, DEFAULT_SHORT_ILL_FILTER)
end

inflections["üks'"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "hted")
	else
		stem = extract_stem(stem, "ks'?")
	end
	add_info(data, 20, "üks'")
	return generate_from_stems(args, data, data.lemma,
			stem .. "hte", stem .. "ht", stem .. "ksi", 0)
end

inflections["sizar"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "ed")
	end
	add_info(data, 21, "sizar")
	return generate_from_stems(args, data, data.lemma,
			stem .. "e", stem .. "t", stem .. "i", 0)
end

inflections["homen"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "ned")
    else
		stem = extract_stem(stem, "en")
	end
	add_info(data, 22, "homen")
	return generate_from_stems(args, data, data.lemma,
			stem .. "ne", stem .. "ent", stem .. "ni", 0)
end

inflections["tütär"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "red")
    else
		stem = extract_stem(stem, "[aä]r'?")
	end
	add_info(data, 23, "tütär")
	return generate_from_stems(args, data, data.lemma,
			stem .. "re", data.lemma .. "t", stem .. "ri", 0)
end

inflections["südäin"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "imed")
    else
		stem = extract_stem(stem, "in")
	end
	add_info(data, 24, "südäin")
	return generate_from_stems(args, data, data.lemma,
			stem .. "ime", stem .. "nt", stem .. "imi", 0)
end

inflections["pähkim"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "med")
    else
		stem = extract_stem(stem, "im")
	end
	add_info(data, 25, "pähkim")
	return generate_from_stems(args, data, data.lemma,
			stem .. "me", stem .. "int", stem .. "mi", 0)
end

inflections["holetoi"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "mad")
    else
		stem = extract_stem(stem, "i")
	end
	add_info(data, 26, "holetoi")
	return generate_from_stems(args, data, data.lemma,
			stem .. "ma", stem .. "nt", stem .. "mi", 0)
end

inflections["toine"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "ižed")
    else
		stem = extract_stem(stem, "ine")
	end
	add_info(data, 27, "toine")
	return generate_from_stems(args, data, data.lemma,
			stem .. "iže", stem .. "št", stem .. "iži",
			2, nil)
end

inflections["sinine"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "žed")
    else
		stem = extract_stem(stem, "ne")
	end
	add_info(data, 28, "sinine")
	return generate_from_stems(args, data, data.lemma,
			stem .. "že", stem .. "št", stem .. "ži", 0)
end

inflections["lambaz"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "had")
    else
		stem = mw.ustring.gsub(extract_stem(stem, "az"), "([kpt])%1$", "%1")
	end
	add_info(data, 29, "lambaz")
	local stem_h = mw.ustring.gsub(stem, "z$", "s")
	return generate_from_stems(args, data, data.lemma,
			mw.ustring.gsub(stem_h, "h$", "") .. "ha", stem .. "ast", stem_h .. "hi", 0)
end

inflections["kunigaz"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "had")
    else
		stem = extract_stem(stem, "z")
	end
	add_info(data, 30, "kunigaz")
	return generate_from_stems(args, data, data.lemma,
			stem .. "ha", stem .. "st", stem .. "hi", 0)
end

inflections["kirvez"] = function(args, data)
	local c_stem, v_stem, par_stem
	if data.n == "pl" then
		v_stem = extract_stem(data.lemma, "d")
        c_stem = extract_stem(v_stem, "[ae]")
        par_stem = v_stem
    else
        local stem, final = extract_stem(data.lemma, "[zž]")
        par_stem = stem .. ({["z"] = "s", ["ž"] = "š"})[final]
        if args["i"] then
        	c_stem, v_stem = stem, "i"
        else
        	c_stem, v_stem = extract_stem(stem, "[aäei]")
        end
        c_stem = mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(c_stem, "'$", ""), "l$", ""), "kk$", "k") .. "h"
        v_stem = c_stem .. mw.ustring.gsub(v_stem, "i", "e")
	end
	add_info(data, 31, "kirvez")
	return generate_from_stems(args, data, data.lemma,
			v_stem, par_stem .. "t", c_stem .. "i", 0)
end

inflections["mez'"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "hed")
    else
		stem = extract_stem(stem, "z'")
	end
	add_info(data, 32, "mez'")
	return generate_from_stems(args, data, data.lemma,
			stem .. "he", stem .. "st", stem .. "hi", 0)
end

inflections["olut"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "ded")
    else
		stem = extract_stem(stem, "[td]")
	end
	add_info(data, 33, "olut")
	return generate_from_stems(args, data, data.lemma,
			stem .. "de", stem .. "t", stem .. "zi", 0)
end

inflections["kolnu"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "d")
	end
	add_info(data, 34, "kolnu")
	return generate_from_stems(args, data, data.lemma,
			stem .. "de", stem .. "t", stem .. "zi", 0)
end

inflections["kuverz'"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "dad")
    else
		stem = extract_stem(stem, "z'?")
	end
	add_info(data, 35, "kuverz'")
	return generate_from_stems(args, data, data.lemma,
			stem .. "da", stem .. "t", stem .. "zi", 0)
end

inflections["kaste"] = function(args, data)
	local stem = args[1]
	if not stem or not mw.ustring.find(stem, "e$") then
		error("A stem ending in -e, equivalent to the genitive singular without the final -n, must be specified.")
	end
    stem = extract_stem(stem, "e")
	add_info(data, 36, "kaste")
	return generate_from_stems(args, data, data.lemma,
			stem .. "e", data.lemma .. "t", stem .. "i", 0)
end

inflections["terveh"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "hed")
    else
		stem = extract_stem(stem, "eh")
	end
	add_info(data, 37, "terveh")
	return generate_from_stems(args, data, data.lemma,
			stem .. "he", stem .. "eht", stem .. "hi", 0)
end

inflections["mitte"] = function(args, data)
	local stem = data.lemma
	if data.n == "pl" then
		stem = extract_stem(stem, "ččed")
    else
		stem = extract_stem(stem, "tte")
	end
	add_info(data, 38, "mitte")
	return generate_from_stems(args, data, data.lemma,
			stem .. "čče", stem .. "ttušt", stem .. "čči", 2, nil)
end

-- Helper functions

function postprocess(args, data)
	local prefix = args["prefix"] or ""
	local suffix = args["suffix"] or ""
	
	for key, form in pairs(data.forms) do
		-- Do not show singular or plural forms for nominals that don't have them
		if (data.n == "pl" and key:find("_sg$")) or (data.n == "sg" and key:find("_pl$")) then
			form = nil
		elseif form then
			for key2, subform in pairs(form) do
				form[key2] = prefix .. subform .. suffix
			end
		end
		
		data.forms[key] = form
	end
	
	-- Check if the lemma form matches the page name
	local lemma_key = data.n == "pl" and "nom_pl" or "nom_sg"
	
	if data.forms[lemma_key] and data.forms[lemma_key][1] and (lang:makeEntryName(data.forms[lemma_key][1])) ~= mw.title.getCurrentTitle().text then
		table.insert(data.categories, lang:getCanonicalName() .. " entries with inflection not matching pagename")
	end
end

-- Make the table
function make_table(data)
	local function show_form(form)
		if not form then
			return "—"
		end
		
		if type(form) ~= "table" then
			error("a non-table value was given in the list of inflected forms.")
		end
		
		local ret = {}
		
		for key, subform in ipairs(form) do
			if mw.ustring.find(subform, "?", nil, true) then
				table.insert(ret, "?")
			else
				table.insert(ret, m_links.full_link({lang = lang, term = subform}))
			end
		end
		
		return table.concat(ret, "<br/>")
	end
	
	local function repl(param)
		if param == "lemma" then
			return m_links.full_link({lang = lang, alt = mw.title.getCurrentTitle().text}, "term")
		elseif param == "info" then
			return data.info and " (" .. data.info .. ")" or ""
		else
			return show_form(data.forms[param])
		end
	end
	
	local collapsed_cells = [=[
|- class="vsShow" style="background: #F2F2FF; vertical-align: top;"
! style="min-width: 11em; background: #CCCCFF;" | 単数主格
| style="min-width: 13em;" | {{{nom_sg}}}
|- class="vsShow" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 単数属格
| {{{gen_sg}}}
|- class="vsShow" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 単数分格
| {{{par_sg}}}
|- class="vsShow" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 複数分格
| {{{par_pl}}}]=]
	
	if data.n == "pl" then
		collapsed_cells = [=[
|- class="vsShow" style="background: #F2F2FF; vertical-align: top;"
! style="min-width: 11em; background: #CCCCFF;" | 単数主格
| style="min-width: 13em;" | {{{nom_sg}}}
|- class="vsShow" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 複数主格
| {{{nom_pl}}}
|- class="vsShow" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 複数分格
| {{{par_pl}}}]=]
	end
	
	local wikicode = [=[
{| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="border: solid 1px #CCCCFF; text-align:left;" cellspacing="1" cellpadding="2"
|- style="background: #CCCCFF; vertical-align: top;"
! class="vsToggleElement" colspan="4" | {{{lemma}}}{{{info}}}の活用
]=] .. collapsed_cells .. [=[

|- class="vsHide" style="background: #CCCCFF; vertical-align: top;"
! style="min-width: 11em;" |
! style="min-width: 13em;" | 単数
! style="min-width: 13em;" | 複数
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 主格
| {{{nom_sg}}}
| {{{nom_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 対格
| {{{acc_sg}}}
| {{{acc_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 属格
| {{{gen_sg}}}
| {{{gen_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 分格
| {{{par_sg}}}
| {{{par_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 様格-具格
| {{{ess_sg}}}
| {{{ess_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 変格
| {{{tra_sg}}}
| {{{tra_pl}}}
|- class="vsHide" style="background: #E6E6FF; vertical-align:top;"
| colspan="3" |
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 内格
| {{{ine_sg}}}
| {{{ine_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 出格
| {{{ela_sg}}}
| {{{ela_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 入格
| {{{ill_sg}}}
| {{{ill_pl}}}
|- class="vsHide" style="background: #E6E6FF; vertical-align:top;"
| colspan="3" |
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 接格
| {{{ade_sg}}}
| {{{ade_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 奪格
| {{{abl_sg}}}
| {{{abl_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 入格
| {{{all_sg}}}
| {{{all_pl}}}
|- class="vsHide" style="background: #E6E6FF; vertical-align:top;"
| colspan="3" |
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 欠格
| {{{abe_sg}}}
| {{{abe_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 共格
| {{{com_sg}}}
| {{{com_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 通格
| {{{pro_sg}}}
| {{{pro_pl}}}
|- class="vsHide" style="background: #E6E6FF; vertical-align:top;"
| colspan="3" |
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | approximative I
| {{{ap1_sg}}}
| {{{ap1_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | approximative II
| {{{ap2_sg}}}
| {{{ap2_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | egressive
| {{{egr_sg}}}
| {{{egr_pl}}}
|- class="vsHide" style="background: #E6E6FF; vertical-align:top;"
| colspan="3" |
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 到格I
| {{{te1_sg}}}
| {{{te1_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 到格II
| {{{te2_sg}}}
| {{{te2_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | 到格III
| {{{te3_sg}}}
| {{{te3_pl}}}
|- class="vsHide" style="background: #E6E6FF; vertical-align:top;"
| colspan="3" |
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | additive I
| {{{ad1_sg}}}
| {{{ad1_pl}}}
|- class="vsHide" style="background: #F2F2FF; vertical-align: top;"
! style="background: #CCCCFF;" | additive II
| {{{ad2_sg}}}
| {{{ad2_pl}}}
|}]=]
	return mw.ustring.gsub(wikicode, "{{{([a-z0-9_]+)}}}", repl)
end

return export