বিষয়বস্তুতে চলুন

মডিউল:enm-conj

উইকিঅভিধান, মুক্ত অভিধান থেকে

এই মডিউলের জন্য মডিউল:enm-conj/নথি-এ নথিপত্র তৈরি করা হয়ে থাকতে পারে

local export = {}

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

local concat = table.concat
local explode = require("Module:string utilities").explode_utf8
local insert = table.insert
local remove = table.remove

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

function table_find(t, pattern)
	for _, v in pairs(t) do
		if v == pattern then 
			return true
		end
	end
end

local slots_and_accel = {
	["inf"] = "inf",
	["pres_ind_1s"] = "1|s|pres|indc",
	["pres_ind_2s"] = "2|s|pres|indc",
	["pres_ind_3s"] = "3|s|pres|indc",
	["pres_ind_p"] = "p|pres|indc",
	["pres_sub_s"] = "s|pres|subj",
	["pres_sub_p"] = "p|pres|subj",
	["past_ind_1s"] = "1//3|s|past|indc",
	["past_ind_2s"] = "2|s|past|indc",
	["3sg_past_indc"] = "3|s|past|indc",
	["past_ind_p"] = "p|past|indc",
	["past_sub_s"] = "s|past|subj",
	["past_sub_p"] = "p|past|subj",
	["imp_s"] = "s|impr",
	["imp_p"] = "p|impr",
	["pres_part"] = "pres|part",
	["past_part"] = "past|part",
}

local function weak_forms(args, data, class, stem, alt_stem, irr_stem, conj_type)
	local classnames, s_stem = {}
	if table_find(class, "irr") then
		s_stem = alt_stem
	else
		s_stem = irr_stem 
	end	
	
	for k, v in ipairs(class) do
		if conj_type == "wk" then
			k = k - 1
		end	
		if v == "irr" then 
			if not args[2] then
				error("Past stem required for weak irregular verbs")
			end
			if table_find(classnames, "irregular") ~= true then
				insert(classnames, "irregular")
			end
			insert(data.forms.past_ind_1s, irr_stem .. "e")
			insert(data.forms.past_ind_2s, irr_stem .. "est")
			insert(data.forms.past_sub_s, irr_stem .. "e")
			insert(data.forms.past_ind_p, irr_stem .. "en")
			insert(data.forms.past_ind_p, irr_stem .. "e")
			insert(data.forms.past_part, irr_stem)
			if args.nocat == false then
				insert(data.categories, "Middle English irregular weak verbs")
			end
		end
		if v == "sl" then 
			if table_find(classnames, "suffixless") ~= true then
				insert(classnames, "suffixless")
			end
			insert(data.forms.past_ind_1s, (args.w_p[k] or s_stem or stem) .. "e")
			insert(data.forms.past_ind_2s, (args.w_p[k] or s_stem or stem) .. "est")
			insert(data.forms.past_sub_s, (args.w_p[k] or s_stem or stem) .. "e")
			insert(data.forms.past_ind_p, (args.w_p[k] or s_stem or stem) .. "en")
			insert(data.forms.past_ind_p, (args.w_p[k] or s_stem or stem) .. "e")
			insert(data.forms.past_part, args.w_p[k] or s_stem or stem)
		end
		if v == "te" then 
			if table_find(classnames, "in -te") ~= true then
				insert(classnames, "in -te")
			end
			insert(data.forms.past_ind_1s, (args.w_p[k] or s_stem or stem) .. "te")
			insert(data.forms.past_ind_2s, (args.w_p[k] or s_stem or stem) .. "test")
			insert(data.forms.past_sub_s, (args.w_p[k] or s_stem or stem) .. "te")
			insert(data.forms.past_ind_p, (args.w_p[k] or s_stem or stem) .. "ten")
			insert(data.forms.past_ind_p, (args.w_p[k] or s_stem or stem) .. "te")
			insert(data.forms.past_part, (args.w_p[k] or s_stem or stem) .. "t")
		end
		if v == "de" then 
			if table_find(classnames, "in -de") ~= true then
				insert(classnames, "in -de")
			end
			insert(data.forms.past_ind_1s, (args.w_p[k] or s_stem or stem) .. "de")
			insert(data.forms.past_ind_2s, (args.w_p[k] or s_stem or stem) .. "dest")
			insert(data.forms.past_sub_s, (args.w_p[k] or s_stem or stem) .. "de")
			insert(data.forms.past_ind_p, (args.w_p[k] or s_stem or stem) .. "den")
			insert(data.forms.past_ind_p, (args.w_p[k] or s_stem or stem) .. "de")
			insert(data.forms.past_part, (args.w_p[k] or s_stem or stem) .. "d")
		end
		if v == "ed" then 
			if table_find(classnames, "in -ed") ~= true then
				insert(classnames, "in -ed")
			end
			insert(data.forms.past_ind_1s, (args.w_p[k] or s_stem or stem) .. "ed")
			insert(data.forms.past_ind_2s, (args.w_p[k] or s_stem or stem) .. "edest")
			insert(data.forms.past_sub_s, (args.w_p[k] or s_stem or stem) .. "ed")
			insert(data.forms.past_ind_p, (args.w_p[k] or s_stem or stem) .. "eden")
			insert(data.forms.past_ind_p, (args.w_p[k] or s_stem or stem) .. "ede")
			insert(data.forms.past_part, (args.w_p[k] or s_stem or stem) .. "ed")
		end
	end
	return classnames
end

local function build_wk_classnames(names)
	local names = concat(names, "/")
		:gsub("-ed/in ", "-ed/")
		:gsub("-te/in ", "-te/")
		:gsub("-te/in ", "-de/")
	return names
end	

local ch1_set = require("Module:table").listToSet{"d", "l", "n", "r", "s", "t"}

local function custom_form(forms, slot)
	if table_find(forms, "—") == true then
		for k, _ in pairs(forms) do
			slot[k] = nil
		end
		slot[1] = "—"
		slot[2] = nil
	end
	for k, v in pairs(slot) do
		v = explode(v)
		local i, n = 3, #v
		while i <= n do
			local ch1, ch2, ch3 = v[i - 2], v[i - 1], v[i]
			if (ch3 == "d" or ch3 == "t") and (
				(ch1 == "l" or ch1 == "s") and ch2 == ch1 or (
					(ch2 == "d" or (ch2 == "t" and ch3 == "t")) and
					(ch1_set[ch1] or v[i - 3] == "g" and ch1 == "h")
				)
			) then
				remove(v, i - 1)
				n = n - 1
			end
			i = i + 1
		end
		slot[k] = concat(v)
	end
end

local function generate_conj(args, data, conj_type)
	if conj_type ~= "st" and conj_type ~= "wk" and conj_type ~= "irr" then
		error("Unknown conjugation '" .. conj_type .. "'")
	end
	
	if args[1]:sub(1,1) == "*" then
		error("Redundant asterisks")
	end
	
	data.forms["inf"] = {args.head or (args[1] .. "en"), (args[1] .. "e")}
	
	local s_23
	if conj_type == "st" then
		s_23 = args[5]
	elseif conj_type == "wk" then
		s_23 = args[3]
	end
	
	data.forms["pres_ind_1s"] = {args[1] .. "e"}
	data.forms["pres_ind_2s"] = {(s_23 or args[1]) .. "est"}
	data.forms["pres_ind_3s"] = {(s_23 or args[1]) .. "eth"}
	data.forms["pres_ind_p"] = {args[1] .. "en", args[1] .. "e"}

	data.forms["pres_sub_s"] = {args[1] .. "e"}
	data.forms["imp_p"] = {args[1] .. "eth", args[1] .. "e"}
	data.forms["pres_part"] = {(args[1] .. "ynge"), (args[1] .. "ende")}
	
	if conj_type == "st" then
		if mw.title.getCurrentTitle().nsText == "Template" then
			data.conj_type = "[[Appendix:Middle English verbs#Strong verbs|strong class 1]]"
		elseif args.class[1] == "ed" then
			error("Class parameter required for strong verbs")
		elseif not args[2] then
			error("Past stem required for strong verbs")
		elseif args.irr == true then
			data.conj_type = "[[Appendix:Middle English verbs#Strong verbs|strong class " .. concat(args.class, "/") .. ", irregular]]"
			if args.nocat == false then
				insert(data.categories, "Middle English irregular strong verbs")
			end
		else
			data.conj_type = "[[Appendix:Middle English verbs#Strong verbs|strong class " .. concat(args.class, "/") .. "]]" 
		end
		
		data.forms["past_ind_1s"] = {args[2]}
		data.forms["past_ind_2s"] = {(args[3] or args[2]) .. "e"}
		data.forms["past_ind_p"] = {(args[3] or args[2]) .. "en", (args[3] or args[2]) .. "e"}

		data.forms["past_sub_s"] = {(args[3] or args[2]) .. "e"}
		data.forms["past_part"] = {(args[4] or args[1]) .. "en", (args[4] or args[1]) .. "e"}
		
		for _, v in ipairs(args["1a"]) do
			insert(data.forms.pres_ind_1s, v .. "e")
			insert(data.forms.pres_ind_2s, v .. "est")
			insert(data.forms.pres_ind_3s, v .. "eth")
			insert(data.forms.inf, v .. "en")
			insert(data.forms.inf, v .. "e")
			insert(data.forms.pres_ind_p, v .. "en")
			insert(data.forms.pres_ind_p, v .. "e")
			insert(data.forms.pres_sub_s, v .. "e")
			insert(data.forms.pres_part, v .. "ynge")
			insert(data.forms.pres_part, v .. "ende")
			insert(data.forms.imp_p, v .. "eth")
			insert(data.forms.imp_p, v .. "e")
		end
		
		for _, v in ipairs(args["3a"]) do
			insert(data.forms.past_ind_2s, v .. "e")
			insert(data.forms.past_sub_s, v .. "e")
			insert(data.forms.past_ind_p, v .. "en")
			insert(data.forms.past_ind_p, v .. "e")
		end
		
		-- Must be inserted here to keep similar second singular past forms together
		insert(data.forms.past_ind_2s, args[2])
		
		for _, v in ipairs(args["2a"]) do
			insert(data.forms.past_ind_1s, v)
			insert(data.forms.past_ind_2s, v)
		end
		for _, v in ipairs(args["4a"]) do
			insert(data.forms.past_part, v .. "en")
			insert(data.forms.past_part, v .. "e")
		end	
	end
	
	if conj_type == "wk" then
		
		data.forms.past_ind_1s = {}
		data.forms.past_ind_2s = {}
		data.forms.past_ind_p = {}
		data.forms.past_sub_s = {}
		data.forms.past_part = {}
		
		args["w_p"] = args["2a"]
		
		local ext_classes = args.class

		for k = 1, 10 do
			if ext_classes[k] == nil and ext_classes[k+1] ~= nil then
				insert(ext_classes, k, args.class[1])
			end	
		end	

		if #ext_classes < #args["2a"] + 1 then
			repeat 
				insert(ext_classes, 2, args.class[1])
			until #ext_classes == #args["2a"] + 1
		end
		
		local classnames = weak_forms(args, data, ext_classes, args[1], args.s, args[2], conj_type)

		data.conj_type = "[[Appendix:Middle English verbs#Weak verbs|weak " .. build_wk_classnames(classnames) .. "]]"
		
		if args.s_class[1] == "none" and (args.s2[1] or args.s3[1] or args.s4[1]) then
			error("Class parameter required for strong forms")
		end
		
		if args.s_class[1] ~= "none" then
			if not (args.s2[1] or args.s3[1] or args.s4[1]) then
				error("At least one strong past form must be set")
			end
			for _, v in ipairs(args["s3"]) do
				insert(data.forms.past_ind_2s, v .. "e")
				insert(data.forms.past_sub_s, v .. "e")
				insert(data.forms.past_ind_p, v .. "en")
				insert(data.forms.past_ind_p, v .. "e")
			end
			for _, v in ipairs(args["s2"]) do
				insert(data.forms.past_ind_1s, v)
				insert(data.forms.past_ind_2s, v)
			end
			for _, v in ipairs(args["s4"]) do
				insert(data.forms.past_part, v .. "en")
				insert(data.forms.past_part, v .. "e")
			end
			if not data.s_set then
				data.conj_type = data.conj_type .. " or [[Appendix:Middle English verbs#Strong verbs|strong class " .. concat(args.s_class, "/") .. "]]"
				data.s_set = true
			end
		end
	end	
	
	if conj_type == "irr" then
		
		data.forms.past_sub_s = {}
		
		if args.type == "been" then
			data.conj_type = "[[Appendix:Middle English verbs#Anomalous verbs|irregular]], [[suppletive]]"
	
			data.forms["inf"] = {"been", "be"}
	
			data.forms["pres_ind_1s"] = {"am", "be"}
			data.forms["pres_ind_2s"] = {"art", "bist"}
			data.forms["pres_ind_3s"] = {"is", "bith"}
			data.forms["pres_ind_p"] = {"aren", "are", "been", "be"}
	
			data.forms["past_ind_1s"] = {"was"}
			data.forms["past_ind_2s"] = {"were"}
			data.forms["past_ind_p"] = {"weren", "were"}
		
			data.forms["pres_sub_s"] = {"be"}
			data.forms["pres_sub_p"] = {"been", "be"}
			data.forms["imp_p"] = {"beth", "be"}
		
			data.forms["pres_part"] = {"beynge", "beende"}
			data.forms["past_part"] = {"been", "be"}
			if args.nocat == false then
				insert(data.categories, "Middle English suppletive verbs")
			end
		elseif args.type == "don" then
			data.conj_type = "[[Appendix:Middle English verbs#Anomalous verbs|irregular]]"
		
			data.forms["inf"] = {"don", "do"}
		
			data.forms["pres_ind_1s"] = {"do"}
			data.forms["pres_ind_2s"] = {"dost", "dest"}
			data.forms["pres_ind_3s"] = {"doth", "deth"}
			data.forms["pres_ind_p"] = {"don", "do"}
	
			data.forms["past_ind_1s"] = {"dide"}
			data.forms["past_ind_2s"] = {"didest", "dide"}
			data.forms["past_ind_p"] = {"diden", "dide"}
		
			data.forms["pres_sub_s"] = {"do"}
			data.forms["imp_p"] = {"doth", "do"}
		
			data.forms["pres_part"] = {"doynge", "donde"}
			data.forms["past_part"] = {"don", "do"}
			if args.nocat == false then
				insert(data.categories, "Middle English irregular verbs")
			end
		elseif args.type == "gon" then
			data.conj_type = "[[Appendix:Middle English verbs#Anomalous verbs|irregular]], [[suppletive]]"
		
			data.forms["inf"] = {"gon", "go"}
		
			data.forms["pres_ind_1s"] = {"go"}
			data.forms["pres_ind_2s"] = {"gost", "gest"}
			data.forms["pres_ind_3s"] = {"goth", "geth"}
			data.forms["pres_ind_p"] = {"gon", "go"}
	
			data.forms["past_ind_1s"] = {"yede", "wente"}
			data.forms["past_ind_2s"] = {"yedest", "wentest"}
			data.forms["past_ind_p"] = {"yeden", "yede", "wenten", "wente"}
		
			data.forms["pres_sub_s"] = {"go"}
			data.forms["imp_p"] = {"goth", "go"}
		
			data.forms["pres_part"] = {"goynge", "gonde"}
			data.forms["past_part"] = {"gon", "go"}
			if args.nocat == false then
				insert(data.categories, "Middle English suppletive verbs")
			end
		elseif args.type == "willen" then
			data.conj_type = "[[Appendix:Middle English verbs#Anomalous verbs|irregular]]"
			
			data.forms["inf"] = {"willen", "wille", "wollen", "wolle"}
		
			data.forms["pres_ind_1s"] = {"wille", "wolle"}
			data.forms["pres_ind_2s"] = {"wilt", "wolt"}
			data.forms["pres_ind_3s"] = {"wille", "wolle"}
			data.forms["pres_ind_p"] = {"willen", "wille", "wollen", "wolle"}
	
			data.forms["past_ind_1s"] = {"wolde"}
			data.forms["past_ind_2s"] = {"woldest", "wolde"}
			data.forms["past_ind_p"] = {"wolden", "wolde"}
		
			data.forms["pres_sub_s"] = {"wille"}
			data.forms["imp_p"] = {"—"}
		
			data.forms["pres_part"] = {"willynge", "willende"}
			data.forms["past_part"] = {"—"}
			if args.nocat == false then
				insert(data.categories, "Middle English defective verbs")
			end
		else
			data.conj_type = "[[Appendix:Middle English verbs#Preterite-present verbs|preterite-present]]"
			
			if not args[2] then
				error("Past stem required for preterite-present verbs")
			end
	
			data.forms["inf"] = {args.head or ((args[3] or args[1]) .. "en"), ((args[3] or args[1]) .. "e")}
		
			data.forms["pres_ind_1s"] = {args[1]}
			data.forms["pres_ind_2s"] = {args[4] or (args[1] .. "st")}
			data.forms["pres_ind_3s"] = {args[1]}
			data.forms["pres_ind_p"] = {(args[3] or args[1]) .. "en", (args[3] or args[1]) .. "e"}
	
			data.forms["past_ind_1s"] = {args[2] .. "e"}
			data.forms["past_ind_2s"] = {args[2] .. "est"}
			data.forms["past_ind_p"] = {args[2] .. "en", args[2] .. "e"}
	
			data.forms["pres_sub_s"] = {(args[3] or args[1]) .. "e"}
			data.forms["imp_p"] = {(args[3] or args[1]) .. "eth", (args[3] or args[1]) .. "e"}
		
			data.forms["pres_part"] = {((args[3] or args[1]) .. "ynge"), ((args[3] or args[1]) .. "ende")}
			data.forms["past_part"] = {(args[3] or args[1]) .. "en", (args[3] or args[1]) .. "e"}
			
			if args.w_class[1] ~= "none" then
				insert(data.forms.pres_ind_2s, args[2] .. "est")
				insert(data.forms.pres_ind_3s, args[2] .. "eth")
			end	
			
			if args.nocat == false then
				insert(data.categories, "Middle English preterite-present verbs")
			end
		end
			
		for _, v in ipairs(args["1a"]) do
			insert(data.forms.pres_ind_1s, v)
			insert(data.forms.pres_ind_3s, v)
		end
		for _, v in ipairs(args["2a"]) do
			insert(data.forms.past_ind_1s, v .. "e")
			insert(data.forms.past_ind_2s, v .. "est")
			insert(data.forms.past_ind_p, v .. "en")
			insert(data.forms.past_ind_p, v .. "e")
		end
		for _, v in ipairs(args["obl"]) do
			insert(data.forms.inf, v .. "e")
			insert(data.forms.pres_ind_p, v .. "en")
			insert(data.forms.pres_ind_p, v .. "e")
			insert(data.forms.pres_sub_s, v .. "e")
			insert(data.forms.imp_p, v .. "eth")
			insert(data.forms.imp_p, v .. "e")
		end
		for _, v in ipairs(args["3a"]) do
			insert(data.forms.inf, v .. "e")
			insert(data.forms.pres_ind_p, v .. "en")
			insert(data.forms.pres_ind_p, v .. "e")
			insert(data.forms.pres_sub_s, v .. "e")
			insert(data.forms.pres_part, v .. "ynge")
			insert(data.forms.pres_part, v .. "ende")
			insert(data.forms.past_part, v .. "en")
			insert(data.forms.past_part, v .. "e")
			insert(data.forms.imp_p, v .. "eth")
			insert(data.forms.imp_p, v .. "e")
		end
	end
	
	if conj_type ~= "wk" then
		local classnames = weak_forms(args, data, args.w_class, args[1], args.s, args.w_irr, conj_type)
		if args.w_class[1] ~= "none" and not data.wk_set then
			data.conj_type = data.conj_type .. " or [[Appendix:Middle English verbs#Weak verbs|weak " .. build_wk_classnames(classnames) .. "]]"
			data.wk_set = true
		end	
	end

	custom_form(args.inf, data.forms.inf)
	custom_form(args["1s"], data.forms.pres_ind_1s)
	custom_form(args["2s"], data.forms.pres_ind_2s)
	custom_form(args["3s"], data.forms.pres_ind_3s)
	custom_form(args.p, data.forms.pres_ind_p)
	custom_form(args["sub"], data.forms.pres_sub_s)
	custom_form(args.imp_p, data.forms.imp_p)
	custom_form(args.part, data.forms.pres_part)
	custom_form(args.p_1s, data.forms.past_ind_1s)
	custom_form(args.p_2s, data.forms.past_ind_2s)
	custom_form(args.p_p, data.forms.past_ind_p)
	custom_form(args.p_sub, data.forms.past_sub_s)
	custom_form(args.p_part, data.forms.past_part)
	
	if args["nopres"] == true then
		data.forms.pres_ind_1s = {"—"}
		data.forms.pres_ind_2s = {"—"}
		data.forms.pres_ind_3s = {"—"}
		data.forms.pres_ind_p = {"—"}
		data.forms.pres_sub_s = {"—"}
		data.forms.pres_part = {"—"}
		data.forms.imp_p = {"—"}
		data.forms.pres_part = {"—"}
	end

	if args["i"] == "0" then
		data.forms.inf = {"—"}
		data.forms.imp_p = {"—"}
		data.forms.pres_part = {"—"}
		data.forms.past_part = {"—"}
	end
	
	if args["w_part"] == true then
		insert(data.forms.past_part, args[2])
		for _, v in ipairs(args["2a"]) do
			insert(data.forms.past_part, v)
		end
	end
	
	for k, v in pairs(data.forms.past_part) do
		data.forms.past_part[k] = v:gsub("dd$", "d"):gsub("tt$", "t")
	end

	for _, v in pairs(data.forms) do
		if table_find (v, "—") == true then
			insert(data.categories, "Middle English defective verbs")
			if not data.def_set then
				data.conj_type = data.conj_type .. ", [[Appendix:Glossary#defective|defective]]"
				data.def_set = true
			end	
		end
	end
	
	local y_forms, y_abbrev
	if args.pf ~= "0" then
		for _, form in pairs(data.forms) do
			for k, v in ipairs(form) do
				if v ~= "0" then 
					form[k] = args.pf .. v
				end
			end
		end	
	elseif args.y == "0" or table_find (data.forms.past_part, "—") then
	elseif args.y == "2" then
		y_forms = {}
		for k, v in ipairs(data.forms.past_part) do
			y_forms[k] = "y" .. v
		end
		if data.forms.past_part[4] then
			y_abbrev = true
		else for _, item in pairs(y_forms) do
				insert(data.forms.past_part, item)
			end	
		end
	elseif args.y == "p1" then
		data.forms.past_part[#data.forms.past_part + 1] = "y" .. data.forms.past_part[1]
	elseif args.y == "p2" then
		if not data.forms.past_part[2] then
			error("Parameter 'y' is set to 'p2', but only one past participle was supplied")
		else
			data.forms.past_part[#data.forms.past_part + 1] = "y" .. data.forms.past_part[2]
		end
	elseif args.y == "p3" then
		if not data.forms.past_part[3] then
			error("Parameter 'y' is set to 'p3', but less than three past participles were supplied")
		else
			data.forms.past_part[#data.forms.past_part + 1] = "y" .. data.forms.past_part[3]
		end
	else
		if data.forms.past_part[2] then
			data.forms.past_part[#data.forms.past_part + 1] = "y" .. data.forms.past_part[1]
			data.forms.past_part[#data.forms.past_part + 1] = "y" .. data.forms.past_part[2]
		else
			data.forms.past_part[#data.forms.past_part + 1] = "y" .. data.forms.past_part[1]
		end
	end
	if args.nocat == false then
		if conj_type == "st" then
			for _, v in ipairs(args.class) do
			insert(data.categories, "Middle English class " .. v .. " strong verbs")
			end	
		end	
		if args.s_class[1] ~= "none" then
			for _, v in ipairs(args.s_class) do
			insert(data.categories, "Middle English class " .. v .. " strong verbs")
			end	
		end
		if conj_type == "wk" or args.w_class[1] ~= "none" then
			insert(data.categories, "Middle English weak verbs")
		end	
	end
	return y_forms, y_abbrev
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
	local conj_type = (frame.args["conj"] or parent_args["conj"]) or "st"

	local boolean_default_false = {type = "boolean", default = false}
	local list_allow_holes = {list = true, allow_holes = true}
	local list_allow_holes_default_none = {list = true, allow_holes = true, default = "none"}
	local args = require("Module:parameters").process(parent_args, {
		-- Basic parameters
		[1] = true,
--		[1] = {default = string.sub(mw.title.getCurrentTitle().text, 1, -3)},
		[2] = true,
		[3] = true,
		[4] = true,
		[5] = true,
		["class"] = {list = true, default = "ed", allow_holes = true},
		["type"] = true,
		["head"] = true,
		-- Form replacement parameters
		["inf"] = list_allow_holes,	
		["1s"] = list_allow_holes,	
		["2s"] = list_allow_holes,	
		["3s"] = list_allow_holes,	
		["p"] = list_allow_holes,	
		["sub"] = list_allow_holes,	
		["imp_p"] = list_allow_holes,	
		["part"] = list_allow_holes,
		["p_1s"] = list_allow_holes,	
		["p_2s"] = list_allow_holes,	
		["p_p"] = list_allow_holes,
		["p_sub"] = list_allow_holes,	
		["p_part"] = list_allow_holes,
		-- Principal part replacement parameters
		["1a"] = list_allow_holes,
		["2a"] = list_allow_holes,
		["3a"] = list_allow_holes,
		["4a"] = list_allow_holes,
		["5a"] = list_allow_holes,
		["obl"] = list_allow_holes,
		-- Weak form parameters
		["w_class"] = list_allow_holes_default_none,
		["w_irr"] = true,
		["w_p"] = list_allow_holes,
		["w_part"] = boolean_default_false,
		-- Strong form parameters
		["s_class"] = list_allow_holes_default_none,
		["s2"] = {list = "s2_", allow_holes = true},
		["s3"] = {list = "s3_", allow_holes = true},
		["s4"] = {list = "s4_", allow_holes = true},
		-- Miscellaneous parameters
		["s"] = true,
		["i"] = {default = "1"},
		["nopres"] = boolean_default_false,
		["y"] = true,
		["pf"] = {default = "0"},
		["irr"] = {type = "boolean"},
		["nocat"] = boolean_default_false,
		-- Aliases
		["c"] = {alias_of = "class", list = true},
		["past"] = {alias_of = "w_p", list = true},
		["t"] = {alias_of = "type"},
		["w"] = {alias_of = "w_class", list = true},
		["sc"] = {alias_of = "s_class", list = true},
		["w_s"] = {alias_of = "s"},
	})
	
	-- Override for templates
	if not args[1] then
		setmetatable(args, {__index = function(self, key)
			return "{{{" .. key .. "}}}"
		end})
	end
	
	local data = {
		head = args.head,
		forms = {},
		categories = {}
	}
	
	-- Generate the forms
	local y_forms, y_abbrev = generate_conj(args, data, conj_type)
	
	data.forms["title"] = {}
--	insert(data.forms.title, mw.title.getCurrentTitle().text) 

	-- Make the table
	local function show_form(form)
		if not form then
			return "—"
		end
		
		local ret = {}
		
		for key, subform in ipairs(form) do
			if mw.title.getCurrentTitle().nsText == "Reconstruction" and subform ~= "—" then
				subform = "*" .. subform
			end
			if subform == "0" then
			elseif subform == "y0" then
			elseif subform == "—" then
				insert(ret, "—")
			elseif form == data.forms["past_sub_s"]	then
				insert(ret, m_links.full_link({lang = lang, term = subform}) .. [=[<sup>1</sup>]=])
			elseif form == data.forms["past_part"] and y_abbrev then
				insert(ret, "(" .. m_links.full_link({lang = lang, alt = "y", term = y_forms[key]}) .. ")" .. m_links.full_link({lang = lang, term = subform}))
			else
				insert(ret, m_links.full_link({lang = lang, term = subform}))
			end	
		end
		
		return concat(ret, ", ")
	end

	local function repl(param)
		if param == "title" and mw.title.getCurrentTitle().nsText == "Reconstruction" then
			return "*" .. mw.title.getCurrentTitle().subpageText
		elseif param == "title" then
			return mw.title.getCurrentTitle().subpageText
		elseif param == "conj_type" then
			return data.conj_type
		elseif param == "inf" and not table_find(data.forms.inf , "—" ) then
			return "(to) " .. show_form(data.forms[param])
	--		elseif param == "past_part" and y_abbrev then
	--			return "(to) " .. show_form(data.forms["past_part"])
		else
			return show_form(data.forms[param])
		end
	end

	if conj_type == "irr" and parent_args.type == "been" then
		local wikicode = mw.getCurrentFrame():expandTemplate{ 
			title = 'inflection-table-top', 
			args = {
				title = "Conjugation of ''{{{title}}}'' ({{{conj_type}}})",
				palette = 'grey',
				tall = 'yes',
			}
		} .. [=[
|-
! [[infinitive]]
| colspan="3" | {{{inf}}}
|-
| class="separator" colspan="999" |
|-
! 
! [[present tense]]
! [[past tense]]
|-
! [[first_person#English:_grammar|1st-person]] [[singular]]
| style="max-width: 15em" | {{{pres_ind_1s}}}
| style="max-width: 15em" | {{{past_ind_1s}}}
|-
! [[second_person#English:_grammar|2nd-person]] [[singular]]
| style="max-width: 15em" | {{{pres_ind_2s}}}
| style="max-width: 15em" | {{{past_ind_2s}}}
|-
! [[third_person#English:_grammar|3rd-person]] [[singular]]
| style="max-width: 15em" | {{{pres_ind_3s}}}
| style="max-width: 15em" | {{{past_ind_1s}}}
|-
! [[subjunctive]] [[singular]]
| rowspan="2" style="max-width: 15em" | {{{pres_sub_s}}}
| style="max-width: 15em" | {{{past_ind_2s}}}
|-
! [[imperative]] [[singular]]
| —
|-
| class="separator" colspan="999" |
|-
! [[plural]]<sup>1</sup>
| style="max-width: 15em" | {{{pres_ind_p}}}
| rowspan="2" style="max-width: 15em" |  {{{past_ind_p}}}
|-
! [[subjunctive]] [[plural]]<sup>1</sup>
| style="max-width: 15em" | {{{pres_sub_p}}}
|-
! [[imperative]] [[plural]]
| style="max-width: 15em" | {{{imp_p}}}
| —
|-
| class="separator" colspan="999" |
|-
! [[participle]]s
| style="max-width: 15em" | {{{pres_part}}}
| style="max-width: 15em" | {{{past_part}}}
]=] .. mw.getCurrentFrame():expandTemplate{
		title = 'inflection-table-bottom',
		args = {
			notes = "<sup>1</sup> Sometimes used as a formal 2nd-person singular."
		}
	}
	return (mw.ustring.gsub(wikicode, "{{{([a-z0-9_]+)}}}", repl)) .. m_utils.format_categories(data.categories, lang)
elseif table_find(data.forms.imp_p, "—") then
	local wikicode = mw.getCurrentFrame():expandTemplate{ 
		title = 'inflection-table-top', 
		args = {
			title = "Conjugation of ''{{{title}}}'' ({{{conj_type}}})",
			palette = 'grey',
			tall = 'yes',
		}
	} .. [=[
! [[infinitive]]
| colspan="3" | {{{inf}}}
|-
!
! [[present tense]]
! [[past tense]]
|-
! [[first_person#English:_grammar|1st-person]] [[singular]]
| style="max-width: 15em" | {{{pres_ind_1s}}}
| style="max-width: 15em" | {{{past_ind_1s}}}
|-
! [[second_person#English:_grammar|2nd-person]] [[singular]]
| style="max-width: 15em" | {{{pres_ind_2s}}}
| style="max-width: 15em" | {{{past_ind_2s}}}
|-
! [[third_person#English:_grammar|3rd-person]] [[singular]]
| style="max-width: 15em" | {{{pres_ind_3s}}}
| rowspan="2" style="max-width: 15em" | {{{past_ind_1s}}}
|-
! [[subjunctive]] [[singular]]
| style="max-width: 15em" | {{{pres_sub_s}}}
|-
! [[imperative]] [[singular]]
| —
| —
|-
! class="separator" colspan="999" |
|-
! [[plural]]<sup>1</sup>
| style="max-width: 15em" | {{{pres_ind_p}}}
| style="max-width: 15em" | {{{past_ind_p}}}
|-
! [[imperative]] [[plural]]
| style="max-width: 15em" | {{{imp_p}}}
| —
|-
! class="separator" colspan="999" |
|-
! [[participle]]s
| style="max-width: 15em" | {{{pres_part}}}
| style="max-width: 15em" | {{{past_part}}}
]=] .. mw.getCurrentFrame():expandTemplate{
		title = 'inflection-table-bottom',
		args = {
			notes = "<sup>1</sup> Sometimes used as a formal 2nd-person singular."
		}
	}
	return (mw.ustring.gsub(wikicode, "{{{([a-z0-9_]+)}}}", repl)) .. m_utils.format_categories(data.categories, lang)
elseif conj_type == "st" or (parent_args.sc or parent_args.s_class) ~= nil then
	local wikicode = mw.getCurrentFrame():expandTemplate{ 
		title = 'inflection-table-top', 
		args = {
			title = "Conjugation of ''{{{title}}}'' ({{{conj_type}}})",
			palette = 'grey',
			tall = 'yes',
		}
	} .. [=[
! [[infinitive]]
| colspan="3" | {{{inf}}}
|-
| class="separator" colspan="999" |
|-
! 
! [[present tense]]
! [[past tense]]
|-
! [[first_person#English:_grammar|1st-person]] [[singular]]
| style="max-width: 15em" | {{{pres_ind_1s}}}
| style="max-width: 15em" | {{{past_ind_1s}}}
|-
! [[second_person#English:_grammar|2nd-person]] [[singular]]
| style="max-width: 15em" | {{{pres_ind_2s}}}
| style="max-width: 15em" | {{{past_ind_2s}}}
|-
! [[third_person#English:_grammar|3rd-person]] [[singular]]
| style="max-width: 15em" | {{{pres_ind_3s}}}
| style="max-width: 15em" | {{{past_ind_1s}}}
|-
! [[subjunctive]] [[singular]]
| rowspan="2" style="max-width: 15em" |  {{{pres_sub_s}}}
| style="max-width: 15em" | {{{past_sub_s}}}
|-
! [[imperative]] [[singular]]
| —
|-
| class="separator" colspan="999" |
|-
! [[plural]]<sup>2</sup>
| style="max-width: 15em" | {{{pres_ind_p}}}
| style="max-width: 15em" | {{{past_ind_p}}}
|-
! [[imperative]] [[plural]]
| style="max-width: 15em" | {{{imp_p}}}
| —
|-
| class="separator" colspan="999" |
|-
! [[participle]]s
| style="max-width: 15em" | {{{pres_part}}}
| style="max-width: 15em" | {{{past_part}}}
]=] .. mw.getCurrentFrame():expandTemplate{
		title = 'inflection-table-bottom',
		args = {
			notes = "<sup>1</sup> Replaced by the indicative in later Middle English.<br/>" ..
				"<sup>2</sup> Sometimes used as a formal 2nd-person singular."
		}
	}
	return (mw.ustring.gsub(wikicode, "{{{([a-z0-9_]+)}}}", repl)) .. m_utils.format_categories(data.categories, lang)
else
	local wikicode = mw.getCurrentFrame():expandTemplate{ 
		title = 'inflection-table-top', 
		args = {
			title = "Conjugation of ''{{{title}}}'' ({{{conj_type}}})",
			palette = 'grey',
			tall = 'yes',
		}
	} .. [=[
|-
! [[infinitive]]
| colspan="3" | {{{inf}}}
|-
| class="separator" colspan="999" |
|-
! 
! [[present tense]]
! [[past tense]]
|-
! [[first_person#English:_grammar|1st-person]] [[singular]]
| style="max-width: 15em" | {{{pres_ind_1s}}}
| style="max-width: 15em" | {{{past_ind_1s}}}
|-
! [[second_person#English:_grammar|2nd-person]] [[singular]]
| style="max-width: 15em" | {{{pres_ind_2s}}}
| style="max-width: 15em" | {{{past_ind_2s}}}
|-
! [[third_person#English:_grammar|3rd-person]] [[singular]]
| style="max-width: 15em" | {{{pres_ind_3s}}}
| style="max-width: 15em" rowspan="2" | {{{past_ind_1s}}}
|-
! [[subjunctive]] [[singular]]
| style="max-width: 15em" rowspan="2" | {{{pres_sub_s}}}
|-
! [[imperative]] [[singular]]
| —
|-
| class="separator" colspan="999" |
|-
! [[plural]]<sup>1</sup>
| style="max-width: 15em" | {{{pres_ind_p}}}
| style="max-width: 15em" | {{{past_ind_p}}}
|-
! [[imperative]] [[plural]]
| style="max-width: 15em" | {{{imp_p}}}
| —
|-
| class="separator" colspan="999" |
|-
! [[participle]]s
| style="max-width: 15em" | {{{pres_part}}}
| style="max-width: 15em" | {{{past_part}}}
]=] .. mw.getCurrentFrame():expandTemplate{
		title = 'inflection-table-bottom',
		args = {
			notes = "<sup>1</sup> Sometimes used as a formal 2nd-person singular."
		}
	}
	return (mw.ustring.gsub(wikicode, "{{{([a-z0-9_]+)}}}", repl)) .. m_utils.format_categories(data.categories, lang)
end
end

return export