Module:sl-verbs

From Wiktionary, the free dictionary
Jump to navigation Jump to search

This module needs documentation.
Please document this module by describing its purpose and usage on the documentation page.

local lang = require("Module:languages").getByCode("sl")

local export = {}

local u = mw.ustring.char
local GRAVE		= u(0x0300)
local ACUTE		= u(0x0301)
local MACRON	= u(0x0304)
local DGRAVE	= u(0x030F)
local INVBREVE	= u(0x0311)
local ACCENT = GRAVE .. ACUTE .. MACRON .. DGRAVE .. INVBREVE


-- Returns the accent diacritic and the number of syllables from the end that it was found (0=last syllable)
local function find_accent(form)
	form = mw.ustring.toNFD(form)
	local accent, rest = mw.ustring.match(form, "([" .. ACCENT .. "])(.-)$")
	if not accent then
		return nil
	end
	local _, count = mw.ustring.gsub(rest, "[aeiou]", "")
	return accent, count
end

local function matches_accents(form, accents)
	local a, p = find_accent(form)
	
	for _, accent in ipairs(accents) do
		if accent[1] == a and accent[2] == p then
			return true
		end
	end
	
	return false
end


local function matches_accents_multiple(forms, ending, accents)
	for _, form in ipairs(forms) do
		form = mw.ustring.gsub(form, ending, "")
		if not matches_accents(form, accents) then
			return false
		end
	end
	
	return true
end


-- Inflection functions

function export.manual(frame)
	local names = {"inf", "1|s|pres", "3|s|pres", "3|p|pres", "2|s|impr", "2|p|impr", "pres|actv|ptcp", "pres|actv|converb", "m|s|l-ptcp", "f|s|l-ptcp", "n|s|l-ptcp", "supine", "past|pasv|ptcp", "past|actv|converb", "vnoun", "short|inf"}
	local params = {
		["accent"] = {list = true},
	}
	
	for _, val in ipairs(names) do
		params[(val:gsub("|", "_"))] = {list = true}
	end
	
	params["inf"].required = true
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	if #args["short_inf"] == 0 then
		require("Module:debug").track("sl-verbs/needs short")
	end
	
	for _, val in ipairs(args["short_inf"]) do
		if not require("Module:sl-common").has_accents(val) then
			require("Module:debug").track("sl-verbs/needs short")
		end
	end
	
	if #args["accent"] == 0 then
		require("Module:debug").track("sl-verbs/needs accent")
	end
	
	local data = {
		forms = {},
		info = "",
		categories = {},
	}
	
	local inf_na = (lang:makeEntryName(args["inf"][1] or "foo"))
	data.info = {}
	
	for _, pres in ipairs(#args["1_s_pres"] > 0 and args["1_s_pres"] or args["3_s_pres"]) do
		local pres_na = (lang:makeEntryName((pres:gsub("m$", ""))))
		
		if mw.ustring.gsub(pres_na, "a$", "ati") == inf_na then
			if not data.info["-ati -am"] then
				data.info["-ati -am"] = true
				table.insert(data.info, "-ati -am")
			end
		elseif mw.ustring.gsub(pres_na, "i$", "iti") == inf_na then
			if not data.info["-iti -im"] then
				data.info["-iti -im"] = true
				table.insert(data.info, "-iti -im")
			end
		elseif mw.ustring.gsub(pres_na, "i$", "eti") == inf_na then
			if not data.info["-eti -im"] then
				data.info["-eti -im"] = true
				table.insert(data.info, "-eti -im")
			end
		elseif mw.ustring.gsub(pres_na, "i$", "ati") == inf_na then
			if not data.info["-ati -im"] then
				data.info["-ati -im"] = true
				table.insert(data.info, "-ati -im")
			end
		elseif mw.ustring.gsub(pres_na, "ne$", "niti") == inf_na then
			if not data.info["-niti -nem"] then
				data.info["-niti -nem"] = true
				table.insert(data.info, "-niti -nem")
			end
		elseif mw.ustring.gsub(inf_na, "[eo]vati$", "uje") == pres_na then
			if not data.info["-ovati -ujem"] then
				data.info["-ovati -ujem"] = true
				table.insert(data.info, "-ovati -ujem")
			end
		elseif mw.ustring.gsub(pres_na, "([aeiou])je$", "%1ti") == inf_na or mw.ustring.gsub(pres_na, "oje$", "eti") == inf_na then
			if not data.info["vowel + -ti -jem"] then
				data.info["vowel + -ti -jem"] = true
				table.insert(data.info, "vowel + -ti -jem")
			end
		elseif mw.ustring.gsub(pres_na, "([aeiou])je$", "%1jati") == inf_na then
			if not data.info["-Vjati -Vjem"] then
				data.info["-Vjati -Vjem"] = true
				table.insert(data.info, "-Vjati -Vjem")
			end
		elseif require("Module:sl-common").t((mw.ustring.gsub(pres_na, "e$", ""))) .. "i" == inf_na or mw.ustring.gsub(inf_na, "lesti$", "olze") == pres_na or mw.ustring.gsub(inf_na, "reči$", "rže") == pres_na then
			if not data.info["obstruent + -ti -em"] then
				data.info["obstruent + -ti -em"] = true
				table.insert(data.info, "obstruent + -ti -em")
			end
		elseif mw.ustring.find(inf_na, "ati$") and require("Module:sl-common").iotation((mw.ustring.gsub(inf_na, "ati$", ""))) .. "e" == pres_na then
			if not data.info["-Cati -Cjem"] then
				data.info["-Cati -Cjem"] = true
				table.insert(data.info, "-Cati -Cjem")
			end
		elseif mw.ustring.gsub(pres_na, "[ae]?([lr])j?e$", "%1eti") == inf_na or mw.ustring.gsub(pres_na, "[ae]?[mn]j?e$", "eti") == inf_na or mw.ustring.find(inf_na, "uti$") and mw.ustring.gsub(inf_na, "uti$", "ove") == pres_na then
			if not data.info["sonorant + -ti -(j)em"] then
				data.info["sonorant + -ti -(j)em"] = true
				table.insert(data.info, "sonorant + -ti -(j)em")
			end
		elseif mw.ustring.find(inf_na, "[aeiou]ti$") and mw.ustring.find(pres_na, "e$") then
			if mw.ustring.find(inf_na, "ati$") and mw.ustring.gsub(inf_na, "ati$", "e") == pres_na then
				require("Module:debug").track("sl-verbs/-ati -em")
			elseif mw.ustring.find(inf_na, "u?vati$") and mw.ustring.gsub(inf_na, "u?vati$", "uje") == pres_na then
				require("Module:debug").track("sl-verbs/-vati -ujem")
			elseif mw.ustring.find(inf_na, "lati$") and mw.ustring.gsub(inf_na, "lati$", "olje") == pres_na then
				require("Module:debug").track("sl-verbs/-lati -oljem")
			elseif mw.ustring.find(inf_na, "ati$") and mw.ustring.gsub(inf_na, "ati$", "ane") == pres_na then
				require("Module:debug").track("sl-verbs/-ati -anem")
			elseif mw.ustring.find(inf_na, "gnati$") and mw.ustring.gsub(inf_na, "gnati$", "žene") == pres_na then
				require("Module:debug").track("sl-verbs/-gnati -ženem")
			elseif mw.ustring.gsub(pres_na, "erj?e$", "rati") == inf_na then
				require("Module:debug").track("sl-verbs/-rati -er(j)em")
			elseif mw.ustring.find(inf_na, "vati$") and mw.ustring.gsub(inf_na, "vati$", "ove") == pres_na then
				require("Module:debug").track("sl-verbs/-vati -ovem")
			elseif mw.ustring.find(inf_na, "eti$") and mw.ustring.gsub(inf_na, "eti$", "e") == pres_na then
				require("Module:debug").track("sl-verbs/-eti -em")
			elseif mw.ustring.find(inf_na, "eti$") and mw.ustring.gsub(inf_na, "eti$", "eve") == pres_na then
				require("Module:debug").track("sl-verbs/-eti -evem")
			elseif mw.ustring.find(inf_na, "iti$") and mw.ustring.gsub(inf_na, "ti$", "de") == pres_na then
				require("Module:debug").track("sl-verbs/-iti -idem")
			else
				require("Module:debug").track("sl-verbs/other")
			end
		else
			require("Module:debug").track("sl-verbs/other")
			
			if mw.ustring.find(inf_na, "ati$") and mw.ustring.gsub(inf_na, "ati$", "oji") == pres_na then
				require("Module:debug").track("sl-verbs/-ati -ojim")
			elseif mw.ustring.find(inf_na, "eti$") and mw.ustring.gsub(inf_na, "eti$", "a") == pres_na then
				require("Module:debug").track("sl-verbs/-eti -am")
			elseif mw.ustring.find(inf_na, "jti$") and mw.ustring.gsub(inf_na, "ti$", "de") == pres_na then
				require("Module:debug").track("sl-verbs/-jti -jdem")
			end
		end
	end
	
	for key, val in ipairs(data.info) do
		table.insert(data.categories, lang:getCanonicalName() .. " verbs in " .. val)
		
		for key2, val2 in ipairs(args["accent"]) do
			if val2:find("^[abc]$") then
				args["accent"][key2] = "<abbr title=\"accent pattern\">AP</abbr> ''" .. val2 .. "''"
				val2 = "accent pattern " .. val2
			elseif val2 == "circ" then
				val2 = "circumflex"
				args["accent"][key2] = val2
			end
			
			table.insert(data.categories, lang:getCanonicalName() .. " verbs in " .. val .. " (" .. val2 .. ")")
		end
		
		val = val:gsub("-[a-zčšž()]+", function(t) return require("Module:links").full_link({lang = lang, alt = t}, "term") end)
		val = val:gsub("V", "<abbr title=\"vowel\">V</abbr>"):gsub("C", "<abbr title=\"consonant\">C</abbr>"):gsub("R", "<abbr title=\"sonorant\">R</abbr>")
		data.info[key] = val
	end
	
	if #data.info > 0 then
		data.info = mw.getContentLanguage():ucfirst(table.concat(data.info, " or "))
		
		if #args["accent"] > 0 then
			data.info = data.info .. " (" .. table.concat(args["accent"], " or ") .. ")"
		end
	else
		data.info = ""
	end
	
	data.forms = require("Module:auto-subtable")()
	
	for _, val in ipairs(names) do
		local forms = args[(val:gsub("|", "_"))]
		
		if forms[1] then
			if val == "n|s|l-ptcp" then
				for _, form in ipairs(forms) do
					local base, count = form:gsub("o$", "")
					local end_accent = false
					
					if count == 0 then
						base, count = form:gsub("ȍ$", "")
						end_accent = true
					end
					
					if count == 0 then
						error("The neuter singular l-participle must end in -o")
					end
					
					table.insert(data.forms["n|s|l-ptcp"], base .. "o" .. (end_accent and DGRAVE or ""))
					table.insert(data.forms["m|d|l-ptcp"], base .. "a" .. (end_accent and DGRAVE or ""))
					table.insert(data.forms["f|d|l-ptcp"], base .. "i" .. (end_accent and DGRAVE or ""))
					table.insert(data.forms["n|d|l-ptcp"], base .. "i" .. (end_accent and DGRAVE or ""))
					table.insert(data.forms["m|p|l-ptcp"], base .. "i" .. (end_accent and DGRAVE or ""))
					table.insert(data.forms["f|p|l-ptcp"], base .. "e" .. (end_accent and DGRAVE or ""))
					table.insert(data.forms["n|p|l-ptcp"], base .. "a" .. (end_accent and DGRAVE or ""))
				end
			elseif val == "1|s|pres" then
				for _, form in ipairs(forms) do
					local base, count = form:gsub("m$", "")
					
					if count == 0 then
						error("The first-person singular present tense must end in -m")
					end
					
					table.insert(data.forms["1|s|pres"], base .. "m")
					table.insert(data.forms["2|s|pres"], base .. "š")
					table.insert(data.forms["3|s|pres"], base)
					table.insert(data.forms["1|d|pres"], base:gsub("ȅ$", "é") .. "va")
					table.insert(data.forms["2|d|pres"], base:gsub("ȅ$", "é") .. "ta")
					table.insert(data.forms["3|d|pres"], base:gsub("ȅ$", "é") .. "ta")
					table.insert(data.forms["1|p|pres"], base:gsub("ȅ$", "é") .. "mo")
					table.insert(data.forms["2|p|pres"], base:gsub("ȅ$", "é") .. "te")
					table.insert(data.forms["3|p|pres"], base:gsub("ȅ$", "é") .. "jo")
				end
			elseif val == "3|s|pres" then
				if #args["1_s_pres"] > 0 or #args["3_p_pres"] > 0 then
					error("The 3_s_pres parameter can only be used with impersonal verbs, which cannot have a 1_s_pres or 3_p_pres parameter")
				end
				
				for _, form in ipairs(forms) do
					table.insert(data.forms["3|s|pres"], form)
				end
				
				data.impersonal = true
			elseif val == "3|p|pres" then
				for _, form in ipairs(forms) do
					table.insert(data.forms["3|p|pres"], form)
				end
			elseif val == "2|p|impr" then
				for _, form in ipairs(forms) do
					local base, count = form:gsub("te$", "")
					
					if count == 0 then
						error("The second-person plural imperative must end in -te")
					end
					
					table.insert(data.forms["1|d|impr"], base .. "va")
					table.insert(data.forms["2|d|impr"], base .. "ta")
					table.insert(data.forms["1|p|impr"], base .. "mo")
					table.insert(data.forms["2|p|impr"], base .. "te")
				end
			else
				data.forms[val] = forms
			end
		end
	end
	
	data.forms:un_auto_subtable()
	
	return make_table(data)
end


function export.biti(frame)
	local params = {
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	local data = {
		forms = {},
		info = "athematic, irregular, suppletive",
		categories = {lang:getCanonicalName() .. " athematic verbs", lang:getCanonicalName() .. " irregular verbs", lang:getCanonicalName() .. " suppletive verbs"},
		has_neg = true,
		has_futr = true,
	}
	
	data.forms["inf"] = {"bíti"}
	data.forms["short|inf"] = {"bȉt"}
	data.forms["pres|actv|ptcp"] = {"bijọ̄č"}
	data.forms["cond"] = {"bȉ"}
	
	data.forms["m|s|l-ptcp"] = {"bȋł"}
	data.forms["f|s|l-ptcp"] = {"bilȁ"}
	data.forms["n|s|l-ptcp"] = {"bilọ̑", "bilȍ"}
	data.forms["m|d|l-ptcp"] = {"bilȁ"}
	data.forms["f|d|l-ptcp"] = {"bilȉ"}
	data.forms["n|d|l-ptcp"] = {"bilȉ"}
	data.forms["m|p|l-ptcp"] = {"bilȋ", "bilȉ"}
	data.forms["f|p|l-ptcp"] = {"bilȅ"}
	data.forms["n|p|l-ptcp"] = {"bilȁ"}
	
	data.forms["1|s|pres"] = {"sȅm"}
	data.forms["2|s|pres"] = {"sȉ"}
	data.forms["3|s|pres"] = {"jȅ"}
	data.forms["1|d|pres"] = {"svȁ"}
	data.forms["2|d|pres"] = {"stȁ"}
	data.forms["3|d|pres"] = {"stȁ"}
	data.forms["1|p|pres"] = {"smȍ"}
	data.forms["2|p|pres"] = {"stȅ"}
	data.forms["3|p|pres"] = {"sȍ"}
	
	data.forms["neg|1|s|pres"] = {"nísem"}
	data.forms["neg|2|s|pres"] = {"nísi"}
	data.forms["neg|3|s|pres"] = {"ní"}
	data.forms["neg|1|d|pres"] = {"nísva"}
	data.forms["neg|2|d|pres"] = {"nísta"}
	data.forms["neg|3|d|pres"] = {"nísta"}
	data.forms["neg|1|p|pres"] = {"nísmo"}
	data.forms["neg|2|p|pres"] = {"níste"}
	data.forms["neg|3|p|pres"] = {"níso"}
	
	data.forms["1|s|futr"] = {"bọ̑m"}
	data.forms["2|s|futr"] = {"bọ̑š"}
	data.forms["3|s|futr"] = {"bọ̑"}
	data.forms["1|d|futr"] = {"bọ̑va"}
	data.forms["2|d|futr"] = {"bọ̑sta"}
	data.forms["3|d|futr"] = {"bọ̑sta"}
	data.forms["1|p|futr"] = {"bọ̑mo"}
	data.forms["2|p|futr"] = {"bọ̑ste"}
	data.forms["3|p|futr"] = {"bọ̑do", "bọ̑jo"}
	
	data.forms["2|s|impr"] = {"bọ́di"}
	data.forms["1|d|impr"] = {"bọ́dite", "bodȋte"}
	data.forms["2|d|impr"] = {"bọ́dita", "bodȋta"}
	data.forms["1|p|impr"] = {"bọ́dimo", "bodȋmo"}
	data.forms["2|p|impr"] = {"bọ́dite", "bodȋte"}
	
	return make_table(data)
end


function export.dati(frame)
	local params = {
		[1] = {default = ""},
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	local data = {
		forms = {},
		info = "athematic",
		categories = {lang:getCanonicalName() .. " athematic verbs"},
	}
	
	data.forms["inf"] = {args[1] .. "dáti"}
	data.forms["short|inf"] = {args[1] .. "dȁt"}
	data.forms["supine"] = {args[1] .. "dȃt"}
	data.forms["past|pasv|ptcp"] = {args[1] .. "dán"}
	
	data.forms["m|s|l-ptcp"] = {args[1] .. "dȃł"}
	data.forms["f|s|l-ptcp"] = {args[1] .. "dála"}
	data.forms["n|s|l-ptcp"] = {args[1] .. "dȃlo"}
	data.forms["m|d|l-ptcp"] = {args[1] .. "dȃla"}
	data.forms["f|d|l-ptcp"] = {args[1] .. "dȃli"}
	data.forms["n|d|l-ptcp"] = {args[1] .. "dȃli"}
	data.forms["m|p|l-ptcp"] = {args[1] .. "dȃli"}
	data.forms["f|p|l-ptcp"] = {args[1] .. "dȃle"}
	data.forms["n|p|l-ptcp"] = {args[1] .. "dȃla"}
	
	data.forms["1|s|pres"] = {args[1] .. "dám"}
	data.forms["2|s|pres"] = {args[1] .. "dáš"}
	data.forms["3|s|pres"] = {args[1] .. "dá"}
	data.forms["1|d|pres"] = {args[1] .. "dáva"}
	data.forms["2|d|pres"] = {args[1] .. "dásta", args[1] ~= "" and args[1] .. "dáta" or nil}
	data.forms["3|d|pres"] = {args[1] .. "dásta"}
	data.forms["1|p|pres"] = {args[1] .. "dámo"}
	data.forms["2|p|pres"] = {args[1] .. "dáste", args[1] ~= "" and args[1] .. "dáte" or nil}
	data.forms["3|p|pres"] = {args[1] .. "dájo", args[1] ..  "dadọ́", args[1] ..  "dadẹ́"}
	
	data.forms["2|s|impr"] = {args[1] .. "dȁj"}
	data.forms["1|d|impr"] = {args[1] .. "dȃjva"}
	data.forms["2|d|impr"] = {args[1] .. "dȃjta"}
	data.forms["1|p|impr"] = {args[1] .. "dȃjmo"}
	data.forms["2|p|impr"] = {args[1] .. "dȃjte"}
	
	return make_table(data)
end


function export.hoteti(frame)
	local params = {
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	local data = {
		forms = {},
		info = "irregular",
		categories = {lang:getCanonicalName() .. " irregular verbs"},
		has_neg = true,
	}
	
	data.forms["inf"] = {"hotẹ́ti"}
	data.forms["short|inf"] = {"hotȅt", "hotẹ̑t"}
	data.forms["vnoun"] = {"hoténje"}
	data.forms["pres|actv|ptcp"] = {"hotȅč"}
	data.forms["past|pasv|ptcp"] = {"hotȅn"}
	
	data.forms["m|s|l-ptcp"] = {"hóteł"}
	data.forms["f|s|l-ptcp"] = {"hotẹ̄la"}
	data.forms["n|s|l-ptcp"] = {"hotẹ́lo"}
	data.forms["m|d|l-ptcp"] = {"hotẹ́la"}
	data.forms["f|d|l-ptcp"] = {"hotẹ́li"}
	data.forms["n|d|l-ptcp"] = {"hotẹ́li"}
	data.forms["m|p|l-ptcp"] = {"hotẹ́li"}
	data.forms["f|p|l-ptcp"] = {"hotẹ́le"}
	data.forms["n|p|l-ptcp"] = {"hotẹ́la"}
	
	data.forms["1|s|pres"] = {"họ́čem", "čȅm"}
	data.forms["2|s|pres"] = {"họ́češ", "čȅš"}
	data.forms["3|s|pres"] = {"họ́če", "čȅ"}
	data.forms["1|d|pres"] = {"họ́čeva", "čéva", "čvȁ"}
	data.forms["2|d|pres"] = {"họ́četa", "čéta", "čtȁ"}
	data.forms["3|d|pres"] = {"họ́četa", "čéta", "čtȁ"}
	data.forms["1|p|pres"] = {"họ́čemo", "čémo", "čmȍ"}
	data.forms["2|p|pres"] = {"họ́čete", "čéte", "čtȅ"}
	data.forms["3|p|pres"] = {"họ́čejo", "čéjo", "čjȍ"}
	
	data.forms["neg|1|s|pres"] = {"nọ́čem", "néčem"}
	data.forms["neg|2|s|pres"] = {"nọ́češ", "néčeš"}
	data.forms["neg|3|s|pres"] = {"nọ́če", "néče"}
	data.forms["neg|1|d|pres"] = {"nọ́čeva", "néčeva"}
	data.forms["neg|2|d|pres"] = {"nọ́četa", "néčeta"}
	data.forms["neg|3|d|pres"] = {"nọ́četa", "néčeta"}
	data.forms["neg|1|p|pres"] = {"nọ́čemo", "néčemo"}
	data.forms["neg|2|p|pres"] = {"nọ́čete", "néčete"}
	data.forms["neg|3|p|pres"] = {"nọ́čejo", "néčejo"}
	
	data.forms["2|s|impr"] = {"hóti"}
	data.forms["1|d|impr"] = {"hotȋte"}
	data.forms["2|d|impr"] = {"hotȋta"}
	data.forms["1|p|impr"] = {"hotȋmo"}
	data.forms["2|p|impr"] = {"hotȋte"}
	
	return make_table(data)
end


function export.iti(frame)
	local params = {
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	local data = {
		forms = {},
		info = "athematic, suppletive",
		categories = {lang:getCanonicalName() .. " athematic verbs", lang:getCanonicalName() .. " suppletive verbs"},
		has_futr = true,
	}
	
	data.forms["inf"] = {"īti"}
	data.forms["pres|actv|ptcp"] = {"gredọ̄č"}
	
	data.forms["m|s|l-ptcp"] = {"šə̏ł"}
	data.forms["f|s|l-ptcp"] = {"šlȁ"}
	data.forms["n|s|l-ptcp"] = {"šlȍ"}
	data.forms["m|d|l-ptcp"] = {"šlȁ"}
	data.forms["f|d|l-ptcp"] = {"šlȉ"}
	data.forms["n|d|l-ptcp"] = {"šlȉ"}
	data.forms["m|p|l-ptcp"] = {"šlȉ"}
	data.forms["f|p|l-ptcp"] = {"šlȅ"}
	data.forms["n|p|l-ptcp"] = {"šlȁ"}
	
	data.forms["1|s|pres"] = {"grẹ́m", "grȅm"}
	data.forms["2|s|pres"] = {"grẹ́š", "grȅš"}
	data.forms["3|s|pres"] = {"grẹ́", "grȅ"}
	data.forms["1|d|pres"] = {"grẹ́va", "gréva"}
	data.forms["2|d|pres"] = {"grẹ́sta", "grésta"}
	data.forms["3|d|pres"] = {"grẹ́sta", "grésta"}
	data.forms["1|p|pres"] = {"grẹ́mo", "grémo"}
	data.forms["2|p|pres"] = {"grẹ́ste", "gréste"}
	data.forms["3|p|pres"] = {"gredọ́", "gredȍ", "gréjo"}
	
	data.forms["1|s|futr"] = {"pọ́jdem"}
	data.forms["2|s|futr"] = {"pọ́jdeš"}
	data.forms["3|s|futr"] = {"pọ́jde"}
	data.forms["1|d|futr"] = {"pọ́jdeva"}
	data.forms["2|d|futr"] = {"pọ́jdeta"}
	data.forms["3|d|futr"] = {"pọ́jdeta"}
	data.forms["1|p|futr"] = {"pọ́jdemo"}
	data.forms["2|p|futr"] = {"pọ́jdete"}
	data.forms["3|p|futr"] = {"pọ́jdejo"}
	
	data.forms["2|s|impr"] = {"pọ̄jdi"}
	data.forms["1|d|impr"] = {"pọ̄jdiva", "pojdȋva"}
	data.forms["2|d|impr"] = {"pọ̄jdita", "pojdȋta"}
	data.forms["1|p|impr"] = {"pọ̄jdimo", "pojdȋmo"}
	data.forms["2|p|impr"] = {"pọ̄jdite", "pojdȋte"}
	
	return make_table(data)
end


function export.jesti(frame)
	local params = {
		[1] = {default = ""},
		["past_pasv_ptcp"] = {type = "boolean"},
		["vnoun"] = {type = "boolean"},
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	local data = {
		forms = {},
		info = "athematic",
		categories = {lang:getCanonicalName() .. " athematic verbs"},
	}
	
	data.forms["inf"] = {args[1] .. "jẹ́sti"}
	data.forms["short|inf"] = {args[1] .. "jẹ̑st", args[1] .. "jȅst"}

	if args[1] == "" then
		data.forms["supine"] = {"jẹ̑st"}
		data.forms["pres|actv|ptcp"] = {"jedọ̄č"}
	else
		data.forms["supine"] = {args[1] .. "jȅst", args[1] .. "jẹ̑st"}
	end
	
	if args["past_pasv_ptcp"] then
		data.forms["past|pasv|ptcp"] = {args[1] .. "jẹ̑den"}
	end
	
	if args["vnoun"] then
		data.forms["vnoun"] = {args[1] .. "jẹ́denje"}
	end
	
	data.forms["m|s|l-ptcp"] = {args[1] .. "jẹ̑dəł"}
	data.forms["f|s|l-ptcp"] = {args[1] .. "jẹ́dla"}
	data.forms["n|s|l-ptcp"] = {args[1] .. "jẹ́dlo"}
	data.forms["m|d|l-ptcp"] = {args[1] .. "jẹ́dla"}
	data.forms["f|d|l-ptcp"] = {args[1] .. "jẹ́dli"}
	data.forms["n|d|l-ptcp"] = {args[1] .. "jẹ́dli"}
	data.forms["m|p|l-ptcp"] = {args[1] .. "jẹ́dli"}
	data.forms["f|p|l-ptcp"] = {args[1] .. "jẹ́dle"}
	data.forms["n|p|l-ptcp"] = {args[1] .. "jẹ́dla"}
	
	data.forms["1|s|pres"] = {args[1] .. "jẹ́m"}
	data.forms["2|s|pres"] = {args[1] .. "jẹ́š"}
	data.forms["3|s|pres"] = {args[1] .. "jẹ́"}
	data.forms["1|d|pres"] = {args[1] .. "jẹ́va"}
	data.forms["2|d|pres"] = {args[1] .. "jẹ́sta"}
	data.forms["3|d|pres"] = {args[1] .. "jẹ́sta"}
	data.forms["1|p|pres"] = {args[1] .. "jẹ́mo"}
	data.forms["2|p|pres"] = {args[1] .. "jẹ́ste"}
	data.forms["3|p|pres"] = {args[1] .. "jedọ́", args[1] .. "jéjo"}
	
	data.forms["2|s|impr"] = {args[1] .. "jȅj", "jẹ̑j"}
	data.forms["1|d|impr"] = {args[1] .. "jẹ̑jva"}
	data.forms["2|d|impr"] = {args[1] .. "jẹ̑jta"}
	data.forms["1|p|impr"] = {args[1] .. "jẹ̑jmo"}
	data.forms["2|p|impr"] = {args[1] .. "jẹ̑jte"}
	
	return make_table(data)
end


function export.vedeti(frame)
	local params = {
		[1] = {default = ""},
		["vnoun"] = {type = "boolean"},
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	local data = {
		forms = {},
		info = "athematic",
		categories = {lang:getCanonicalName() .. " athematic verbs"},
	}
	
	data.forms["inf"] = {args[1] .. "vẹ́deti"}
	data.forms["short|inf"] = {args[1] .. "vẹ́det"}
	
	if args[1] == "" then
		data.forms["pres|actv|ptcp"] = {"vedọ̄č"}
	end
	
	if args["vnoun"] then
		data.forms["vnoun"] = {args[1] .. "vẹ́denje"}
	end
	
	data.forms["m|s|l-ptcp"] = {args[1] .. "vẹ́deł"}
	data.forms["f|s|l-ptcp"] = {args[1] .. "vẹ̄dela"}
	data.forms["n|s|l-ptcp"] = {args[1] .. "vẹ́delo"}
	data.forms["m|d|l-ptcp"] = {args[1] .. "vẹ́dela"}
	data.forms["f|d|l-ptcp"] = {args[1] .. "vẹ́deli"}
	data.forms["n|d|l-ptcp"] = {args[1] .. "vẹ́deli"}
	data.forms["m|p|l-ptcp"] = {args[1] .. "vẹ́deli"}
	data.forms["f|p|l-ptcp"] = {args[1] .. "vẹ́dele"}
	data.forms["n|p|l-ptcp"] = {args[1] .. "vẹ́dela"}
	
	data.forms["1|s|pres"] = {args[1] .. "vẹ́m"}
	data.forms["2|s|pres"] = {args[1] .. "vẹ́š"}
	data.forms["3|s|pres"] = {args[1] .. "vẹ́"}
	data.forms["1|d|pres"] = {args[1] .. "vẹ́va"}
	data.forms["2|d|pres"] = {args[1] .. "vẹ́sta"}
	data.forms["3|d|pres"] = {args[1] .. "vẹ́sta"}
	data.forms["1|p|pres"] = {args[1] .. "vẹ́mo"}
	data.forms["2|p|pres"] = {args[1] .. "vẹ́ste"}
	data.forms["3|p|pres"] = {args[1] .. "véjo", args[1] .. "vedọ́"}
	
	data.forms["2|s|impr"] = {args[1] .. "vẹ́di"}
	data.forms["1|d|impr"] = {args[1] .. "vẹ́diva"}
	data.forms["2|d|impr"] = {args[1] .. "vẹ́dita"}
	data.forms["1|p|impr"] = {args[1] .. "vẹ́dimo"}
	data.forms["2|p|impr"] = {args[1] .. "vẹ́dite"}
	
	return make_table(data)
end

-- Helper functions
local function gcd(m, n)
    while n ~= 0 do
        local q = m
        m = n
        n = q % n
    end
    return m
end

local function lcm(m, n)
    return (m ~= 0 and n ~= 0) and m * n / gcd(m, n) or 0
end


-- Make the table
function make_table(data)
	local function repl(param)
		local accel = false  -- Temporary
		local no_store = false
		
		if param == "info" then
			return mw.getContentLanguage():ucfirst(data.info or "")
		elseif string.sub(param, 1, 1) == "!" then
			no_store = true
			param = string.sub(param, 2)
		elseif string.sub(param, 1, 1) == "#" then
			accel = false
			param = string.sub(param, 2)
		end
		
		local forms = data.forms[param]
		
		if not forms or not forms[1] then
			return "&mdash;"
		end
		
		local ret = {}
		
		for key, subform in ipairs(forms) do
			table.insert(ret, require("Module:links").full_link({lang = lang, term = subform, accel = accel and {form = param, no_store = no_store} or nil}))
		end
		
		return table.concat(ret, ", ")
	end
	
	local names = {
		["1|s"] = "1st&nbsp;singular",
		["2|s"] = "2nd&nbsp;singular",
		["3|s"] = "3rd&nbsp;singular",
		["1|d"] = "1st&nbsp;dual",
		["2|d"] = "2nd&nbsp;dual",
		["3|d"] = "3rd&nbsp;dual",
		["1|p"] = "1st&nbsp;plural",
		["2|p"] = "2nd&nbsp;plural",
		["3|p"] = "3rd&nbsp;plural",
	}
	
	local num_cols = 2 + (data.has_neg and 1 or 0) + (data.has_futr and 1 or 0)
	local total_cols = lcm(num_cols, 6)
	
	local wikicode = {}
	
	table.insert(wikicode, [=[
{| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="background: #F9F9F9; border: 1px solid #aaaaaa;"
|- style="background: #d9ebff; text-align: left;"
! class="vsToggleElement" colspan="]=] .. (total_cols + 1) .. [=[" | {{{info}}}
|- class="vsShow"
! style="min-width: 11em; background: #eff7ff;" | infinitive
| style="min-width: 11em;" colspan="]=] .. total_cols .. [=[" | {{{!inf}}}
|- class="vsShow"
! style="background: #eff7ff;" | ]=] .. (data.impersonal and "3rd" or "1st") .. [=[&nbsp;singular
| colspan="]=] .. total_cols .. [=[" | {{{!]=] .. (data.impersonal and "3" or "1") .. [=[|s|pres}}}
|- class="vsHide"
! style="background: #eff7ff;" | infinitive
| colspan="]=] .. (total_cols / 2) .. [=[" | {{{inf}}}
| colspan="]=] .. (total_cols / 2) .. [=[" | {{{short|inf}}}
|- class="vsHide"
! style="background: #eff7ff;" | supine
| colspan="]=] .. total_cols .. [=[" | {{{supine}}}
|- class="vsHide"
! style="background: #eff7ff;" | verbal&nbsp;noun
| colspan="]=] .. total_cols .. [=[" | {{{#vnoun}}}
|- class="vsHide" style="background: #d9ebff;"
!
! colspan="]=] .. (total_cols / 2) .. [=[" | participle
! colspan="]=] .. (total_cols / 2) .. [=[" | converb
|- class="vsHide"
! style="background: #eff7ff;" | present
| colspan="]=] .. (total_cols / 2) .. [=[" | {{{pres|actv|ptcp}}}
| colspan="]=] .. (total_cols / 2) .. [=[" | {{{pres|actv|converb}}}
|- class="vsHide"
! style="background: #eff7ff;" | past
| colspan="]=] .. (total_cols / 2) .. [=[" | {{{past|pasv|ptcp}}}
| colspan="]=] .. (total_cols / 2) .. [=[" | {{{past|actv|converb}}}
|- class="vsHide" style="background: #d9ebff;"
! style="min-width: 11em;" | l-participle
! colspan="]=] .. (total_cols / 3) .. [=[" style="min-width: 11em;" | masculine
! colspan="]=] .. (total_cols / 3) .. [=[" style="min-width: 11em;" | feminine
! colspan="]=] .. (total_cols / 3) .. [=[" style="min-width: 11em;" | neuter
|- class="vsHide"
! style="background: #eff7ff;" | singular
| colspan="]=] .. (total_cols / 3) .. [=[" | {{{m|s|l-ptcp}}}
| colspan="]=] .. (total_cols / 3) .. [=[" | {{{f|s|l-ptcp}}}
| colspan="]=] .. (total_cols / 3) .. [=[" | {{{n|s|l-ptcp}}}
|- class="vsHide"
! style="background: #eff7ff;" | dual
| colspan="]=] .. (total_cols / 3) .. [=[" | {{{m|d|l-ptcp}}}
| colspan="]=] .. (total_cols / 3) .. [=[" | {{{f|d|l-ptcp}}}
| colspan="]=] .. (total_cols / 3) .. [=[" | {{{n|d|l-ptcp}}}
|- class="vsHide"
! style="background: #eff7ff;" | plural
| colspan="]=] .. (total_cols / 3) .. [=[" | {{{m|p|l-ptcp}}}
| colspan="]=] .. (total_cols / 3) .. [=[" | {{{f|p|l-ptcp}}}
| colspan="]=] .. (total_cols / 3) .. [=[" | {{{n|p|l-ptcp}}}
|- class="vsHide" style="background: #d9ebff;"
!]=])

	table.insert(wikicode, "\n! colspan=\"" .. (total_cols / num_cols) .. "\" style=\"min-width: 11em;\" | present")
	
	if data.has_neg then
		table.insert(wikicode, "\n! colspan=\"" .. (total_cols / num_cols) .. "\" style=\"min-width: 11em;\" | present<br/>negative")
	end
	
	if data.has_futr then
		table.insert(wikicode, "\n! colspan=\"" .. (total_cols / num_cols) .. "\" style=\"min-width: 11em;\" | future")
	end
	
	table.insert(wikicode, "\n! colspan=\"" .. (total_cols / num_cols) .. "\" style=\"min-width: 11em;\" | imperative")
	
	for _, pn in ipairs({"1|s", "2|s", "3|s", "1|d", "2|d", "3|d", "1|p", "2|p", "3|p"}) do
		table.insert(wikicode, "\n|- class=\"vsHide\"")
		table.insert(wikicode, "\n! style=\"background: #eff7ff;\" | ")
		table.insert(wikicode, names[pn])
		
		table.insert(wikicode, "\n| colspan=\"" .. (total_cols / num_cols) .. "\" | {{{")
		table.insert(wikicode, pn)
		table.insert(wikicode, "|pres}}}")
		
		if data.has_neg then
			table.insert(wikicode, "\n| colspan=\"" .. (total_cols / num_cols) .. "\" | {{{neg|")
			table.insert(wikicode, pn)
			table.insert(wikicode, "|pres}}}")
		end
		
		if data.has_futr then
			table.insert(wikicode, "\n| colspan=\"" .. (total_cols / num_cols) .. "\" | {{{")
			table.insert(wikicode, pn)
			table.insert(wikicode, "|futr}}}")
		end
		
		table.insert(wikicode, "\n| colspan=\"" .. (total_cols / num_cols) .. "\" | {{{")
		table.insert(wikicode, pn)
		table.insert(wikicode, "|impr}}}")
	end
	
	table.insert(wikicode, "\n|}")
	
	return mw.ustring.gsub(table.concat(wikicode), "{{{([^}]+)}}}", repl) .. require("Module:utilities").format_categories(data.categories, lang)
end

return export