Hello, you have come here looking for the meaning of the word . In DICTIOUS you will not only get to know all the dictionary meanings for the word , but we will also tell you about its etymology, its characteristics and you will know how to say in singular and plural. Everything you need to know about the word you have here. The definition of the word will help you to be more precise and correct when speaking or writing your texts. Knowing the definition of, as well as those of other words, enriches your vocabulary and provides you with more and better linguistic resources.


local export = {}

--[=[

Authorship: Ben Wing <benwing2>

]=]

--[=[

TERMINOLOGY:

-- "slot" = A particular combination of case/number.
	 Example slot names for verbs are "aor_1s" (non-past aorist first-person singular) and
	 "neg_dist_gen_past_2p_formal" (negative distant general past second-person plural formal).
	 Each slot is filled with zero or more forms.

-- "form" = The conjugated Kyrgyz form representing the value of a given slot.

-- "lemma" = The dictionary form of a given Kyrgyz verb, i.e. the infinitive.
]=]

local lang = require("Module:languages").getByCode("ky")
local m_table = require("Module:table")
local m_string_utilities = require("Module:string utilities")
local m_script_utilities = require("Module:script utilities")
local iut = require("Module:inflection utilities")
local parse_utilities_module = "Module:parse utilities"
local m_para = require("Module:parameters")

local current_title = mw.title.getCurrentTitle()

local u = require("Module:string/char")
local rsplit = m_string_utilities.split
local rfind = m_string_utilities.find
local rmatch = m_string_utilities.match
local rgmatch = m_string_utilities.gmatch
local rsubn = m_string_utilities.gsub
local ulen = m_string_utilities.len
local usub = m_string_utilities.sub
local uupper = m_string_utilities.upper
local ulower = m_string_utilities.lower
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local insert = table.insert
local dump = mw.dumpObject

-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
	local retval = rsubn(term, foo, bar)
	return retval
end

local lower_vowel = "аоөүуыэяёюие"
local upper_vowel = uupper(lower_vowel)
local vowel = lower_vowel .. upper_vowel
local V = ""
local C = ""

local lower_jr = "йр"
local upper_jr = uupper(lower_jr)
local jr = lower_jr .. upper_jr
local lower_voiced_cons_not_jr = "дмлнңбвгжз"
local upper_voiced_cons_not_jr = uupper(lower_voiced_cons_not_jr)
local voiced_cons_not_jr = lower_voiced_cons_not_jr .. upper_voiced_cons_not_jr
local lower_unvoiced_cons = "кпстфхчцшщ"
local upper_unvoiced_cons = uupper(lower_unvoiced_cons)
local unvoiced_cons = lower_unvoiced_cons .. upper_unvoiced_cons

local function construct_vowel_harmony_table(spec)
	local tab = {}
	for _, triggers_result in ipairs(spec) do
		local triggers, result = unpack(triggers_result)
		for trigger in rgmatch(triggers, ".") do
			tab = result
		end
	end
	return tab
end

local high_harmony_table = construct_vowel_harmony_table {
	{ "эие", "и" }, -- front unrounded
	{ "аыя", "ы" }, -- back unrounded
	{ "өү", "ү" }, -- front rounded
	{ "оёюу", "у" }, -- back rounded
}
local low_harmony_table = construct_vowel_harmony_table {
	{ "эие", "е" }, -- front unrounded
	{ "аыяюу", "а" }, -- back unrounded
	{ "өү", "ө" }, -- front rounded
	{ "оё", "о" }, -- back rounded
}
--[==[ not currently used
local round_harmony_table = construct_vowel_harmony_table {
	{ "эеө", "ө" }, -- low front
	{ "аяоё", "о" }, -- low back
	{ "иү", "ү" }, -- high front
	{ "ыую", "у" }, -- high back
}
]==]
local u_harmony_table = construct_vowel_harmony_table {
	{ "эеөиү", "ү" }, -- front
	{ "аяоёыую", "у" }, -- back
}
local o_harmony_table = construct_vowel_harmony_table {
	{ "эеөиү", "ө" }, -- front
	{ "аяоёыую", "о" }, -- back
}
local tenses = {
	{ "rec_past", "recent|past" },
	{ "gen_past", "general|past" },
	{ "dist_gen_past", "distant|general|past" },
	{ "indir_past", "indir|past" },
	{ "hab_past", "hab|past" },
	{ "hab_rem_past", "hab|remote|past" },
	{ "unaccomp_past", "unaccomplished|past" },
	{ "aor", "aor|non-past" }, -- non-past/aorist
	{ "uncert_fut", "uncertain|fut" },
	{ "would_cond_1", "''would''|cond|type1" },
	{ "would_cond_2", "''would''|cond|type2" },
	{ "cfact_cond", "counterfactual|cond" },
	{ "imp", "imp" },
--	{ "opt", "opt" },
	{ "if_cond", "''if''|cond" },
}

local person_numbers = { "1s", "2s_inform", "2s_formal", "3s", "1p", "2p_inform", "2p_formal", "3p" }

-- P1: past/conditional
local default_person_number_suffixes_type_1 = {
	 = "им",
	 = "иң",
	 = "иңиз",
	 = "",
	 = "ик",
	 = "иңар",
	 = "иңиздар",
	 = "",
}

-- P2: copula
local default_person_number_suffixes_type_2 = {
	 = "мин",
	 = "сиң",
	 = "сиз",
	 = "",
	 = "биз",
	 = "сиңар",
	 = "сиздар",
	 = "",
}

-- P3: present
local default_person_number_suffixes_type_3 = {
	 = {"мин", {form = "м", footnotes = {""}}},
	 = "сиң",
	 = "сиз",
	 = "т",
	 = "биз",
	 = "сиңар",
	 = "сиздар",
	 = "т",
}

local verb_slots_list = {}
local participles = {
	{ "past_part", "past|part" },
	{ "neg_past_part", "neg|past|part" },
	{ "fut_part", "fut|part" },
	{ "neg_fut_part", "neg|fut|part" },
	{ "pres_pfv_part", "pres|pfv|part" },
	{ "pres_impfv_part", "pres|impfv|part" },
	{ "neg_pres_part", "neg|pres|part" },
}

local function make_verb_slots()
	insert(verb_slots_list, { "inf", "inf" })
	insert(verb_slots_list, { "neg_inf", "neg|inf" })
	for _, part_accel in ipairs(participles) do
		local part, accel = unpack(part_accel)
		insert(verb_slots_list, { part, accel })
	end
	for _, tense_accel in ipairs(tenses) do
		for _, pos_neg in ipairs { "", "neg_" } do
			local tense, accel_tense = unpack(tense_accel)
			local pos_neg_accel = pos_neg == "" and "" or "neg|"
			if tense ~= "unaccomp_past" or pos_neg ~= "neg_" then
				for _, person_number in ipairs(person_numbers) do
					local accel_person_number = person_number:gsub("_", "|")
					local slot = pos_neg .. tense .. "_" .. person_number
					local accel = accel_person_number .. "|" .. pos_neg_accel .. accel_tense
					insert(verb_slots_list, { slot, accel })
				end
			end
		end
	end
end

make_verb_slots()


local function skip_slot(conj_spec, slot)
	return conj_spec.args
end


local function fetch_footnotes(separated_group)
	local footnotes
	for j = 2, #separated_group - 1, 2 do
		if separated_group ~= "" then
			error("Extraneous text after bracketed footnotes: '" .. table.concat(separated_group) .. "'")
		end
		if not footnotes then
			footnotes = {}
		end
		table.insert(footnotes, separated_group)
	end
	return footnotes
end


-- Process override for the participle arguments in `args`, storing the results into `forms`.
local function process_overrides(forms, args)
	for _, part_accel in ipairs(participles) do
		local part, accel = unpack(part_accel)
		if args then
			forms = nil
			if args ~= "-" then
				local put = require(parse_utilities_module)
				local segments = put.parse_balanced_segment_run(args, "")
				local comma_separated_groups = put.split_alternating_runs_on_comma(segments)
				for i, comma_separated_group in ipairs(comma_separated_groups) do
					local formobj = {
						form = comma_separated_group,
						footnotes = fetch_footnotes(comma_separated_group),
					}
					iut.insert_form(forms, part, formobj)
				end
			end
		end
	end
end


local function combine_stem_ending(stem, ending)
	if ending == "" then
		return stem
	end

	local split_suffix = rsplit(ending, "()")
	local suffix_syls = {}
	for i, sufpart in ipairs(split_suffix) do
		-- Break into CV sequences but add a final consonant onto the preceding syllable, unless the
		-- final "consonant" is "*" to repeat the vowel (as in the negative infinitive), in which case
		-- it needs to be in the onset of the next "syllable".
		if i == #split_suffix and suffix_syls and sufpart ~= "*" or i % 2 == 0 then
			suffix_syls = suffix_syls .. sufpart
		else
			insert(suffix_syls, sufpart)
		end
	end

	for _, endsyl in ipairs(suffix_syls) do
		local stem_init, stem_last_vowel, stem_final_cons_cluster = rmatch(stem, "^(.*)(" .. V .. ")(.-)$")
		if not stem_last_vowel then
			error(("Lemma or stem '%s' has no vowel, not sure how to implement vowel harmony"):format(stem))
		end
		local endsyl_init, endsyl_vowel, endsyl_final = rmatch(endsyl, "^(.-)()(.*)$")
		if not endsyl_init then
			endsyl_init = endsyl
			endsyl_vowel = ""
			endsyl_final = ""
		end
		local endsyl_init_first, endsyl_init_butfirst = "", ""
		if endsyl_init ~= "" then
			endsyl_init_first, endsyl_init_butfirst = rmatch(endsyl_init, "^(.)(.*)$")
			if endsyl_init_first == "Л" then
				if stem_final_cons_cluster == "" or rfind(stem_final_cons_cluster, "$") then
					endsyl_init_first = "л"
				else
					endsyl_init_first = "д"
				end
			elseif endsyl_init_first == "Н" then
				if stem_final_cons_cluster == "" then
					endsyl_init_first = "н"
				else
					endsyl_init_first = "д"
				end
			elseif endsyl_init_first == "С" then
				if stem_final_cons_cluster == "" then
					endsyl_init_first = "с"
				else
					endsyl_init_first = ""
				end
			elseif endsyl_init_first == "*" then
				if stem_final_cons_cluster == "" then
					endsyl_init_first = ulower(stem_last_vowel)
					if endsyl_init_first == "е" then
						endsyl_init_first = "э"
						stem_last_vowel = stem_last_vowel == "Е" and "Э" or "э"
					elseif endsyl_init_first == "я" then
						endsyl_init_first = "а"
					elseif endsyl_init_first == "ё" then
						endsyl_init_first = "о"
					end
				else
					error(("Internal error: * in ending %s cannot follow a consonant-final stem %s"):format(
						ending, stem))
				end
			elseif endsyl_init_first == "#" then
				endsyl_init_first = ""
				-- delete preceding final consonant cluster
				stem_final_cons_cluster = ""
			end
		end
		if endsyl_vowel == "Й" then
			if stem_final_cons_cluster == "" then
				endsyl_init_first = "й"
				endsyl_vowel = ""
			else
				endsyl_init_first = ""
				endsyl_vowel = "а"
			end
		end
		if rfind(endsyl_vowel, "^$") then
			local harmony_table
			if endsyl_vowel == "и" then
				harmony_table = high_harmony_table
			elseif endsyl_vowel == "у" then
				harmony_table = u_harmony_table
			elseif endsyl_vowel == "О" then
				harmony_table = o_harmony_table
			else
				harmony_table = low_harmony_table
			end
			if endsyl_init == "" and stem_final_cons_cluster == "" then
				endsyl_vowel = ""
			else
				endsyl_vowel = harmony_table
			end
		end
		if rfind(stem_final_cons_cluster, "$") then
			if endsyl_init_first == "д" then
				endsyl_init_first = "т"
			elseif endsyl_init_first == "г" then
				endsyl_init_first = "к"
			elseif endsyl_init_first == "б" then
				endsyl_init_first = "п"
			end
		end
		endsyl_init = endsyl_init_first .. endsyl_init_butfirst
		if endsyl_init == "" then
			stem_final_cons_cluster = rsub(stem_final_cons_cluster, "$", {
				 = "б",
				 = "Б",
				 = "г",
				 = "Г",
			})
		end
		stem = stem_init .. stem_last_vowel .. stem_final_cons_cluster .. endsyl_init .. endsyl_vowel .. endsyl_final
	end

	stem = rsub(stem, "", {
		 = "я",
		 = "Я",
		 = "Я",
		 = "ё",
		 = "Ё",
		 = "Ё",
		 = "ю",
		 = "Ю",
		 = "Ю",
	})

	return stem
end


local function conjugate_verb(conj_spec, lemma)
	local function insert_form(slot, form)
		if skip_slot(conj_spec, slot) then
			return
		end
		iut.insert_form(conj_spec.forms, slot, {form = form})
	end

	local function resolve_ending(stem, ending)
		if type(ending) == "function" then
			return ending(stem)
		else
			return ending
		end
	end

	local function add_stem_ending(stem, ending)
		ending = resolve_ending(stem, ending)
		local full_ending = ending:match("^!(.*)$")
		if full_ending then
			return full_ending
		end
		return combine_stem_ending(stem, ending)
	end

	local function add_stem_final_ending(spec, stem, ending)
		local form = add_stem_ending(stem, ending)
		if spec.postprocess then
			form = spec.postprocess(form)
		end
		return form
	end

	local function add_single(slot, ending)
		insert_form(slot, add_stem_ending(conj_spec.stem, ending))
	end

	local function add_part(slot, ending)
		add_single(slot, ending)
		insert_form(slot .. "_3p", add_stem_ending(add_stem_ending(conj_spec.stem, "иш"), ending))
	end

	local function make_future_part_ending(stem)
		if rfind(stem, "$") then
			return "р"
		elseif rfind(stem, V .. "$") then
			return "*р"
		else
			return "ар"
		end
	end

	add_single("inf", function(stem)
		return "!" .. conj_spec.lemma
	end)
	add_single("neg_inf", "бО*")

	add_part("past_part", "ган")
	add_part("neg_past_part", "баган")
	add_part("fut_part", make_future_part_ending)
	add_part("neg_fut_part", "бас")
	add_part("pres_pfv_part", "ип")
	add_part("pres_impfv_part", "Й")
	add_part("neg_pres_part", "бай")

	local function do_tense_person_number(spec, person_number_form, person_number_dest_slot, extra_footnotes)
		local components = {}
		if spec.part_base then
			insert(components, conj_spec.forms)
		else
			insert(components, person_number_form == "3p" and not spec.ending_3p and add_stem_ending(conj_spec.stem, "иш") or
				conj_spec.stem)
		end
		insert(components, spec.tense_ending)
		local ending = (person_number_form == "3s" or person_number_form == "3p") and spec.ending_3sp or
			spec
		if not ending then
			local default_endings =
				spec.ending_type == "1" and default_person_number_suffixes_type_1 or
				spec.ending_type == "2" and default_person_number_suffixes_type_2 or
				default_person_number_suffixes_type_3
			ending = default_endings
		end
		insert(components, ending)
		local slot = spec.tense .. "_" .. person_number_dest_slot
		iut.add_multiple_forms(conj_spec.forms, slot, components, combine_stem_ending, nil, nil,
			iut.combine_footnotes(spec.footnotes, extra_footnotes))
	end

	local function make_tense(spec)
		for _, person_number in ipairs(person_numbers) do
			do_tense_person_number(spec, person_number, person_number)
		end
		-- The third-singular is an alternative for the third-plural.
		do_tense_person_number(spec, "3s", "3p", {""})
	end

	make_tense { -- non-past/aorist
		tense = "aor",
		part_base = "pres_impfv_part",
		tense_ending = "",
		ending_type = "3",
	}
	make_tense { -- negative non-past/aorist
		tense = "neg_aor",
		part_base = "neg_pres_part",
		tense_ending = "",
		ending_type = "3",
	}
	make_tense { -- recent past
		tense = "rec_past",
		tense_ending = "ди",
		ending_type = "1",
	}
	make_tense { -- negative recent past, variant #1
		tense = "neg_rec_past",
		part_base = "past_part",
		tense_ending = " жок",
		ending_type = "2",
	}
	make_tense { -- negative recent past, variant #2
		tense = "neg_rec_past",
		tense_ending = "бади",
		ending_type = "1",
		footnotes = {""},
	}
	make_tense { -- remote/general past
		tense = "gen_past",
		part_base = "past_part",
		tense_ending = "",
		ending_type = "2",
		ending_1s = {"мин", {form = "#м", footnotes = {""}}},
	}
	make_tense { -- negative remote/general past
		tense = "neg_gen_past",
		part_base = "past_part",
		tense_ending = " эмес",
		ending_type = "2",
	}
	make_tense { -- distant remote/general past
		tense = "dist_gen_past",
		part_base = "past_part",
		tense_ending = " эле",
		ending_type = "1",
	}
	make_tense { -- negative distant remote/general past
		tense = "neg_dist_gen_past",
		part_base = "past_part",
		tense_ending = " эмес эле",
		ending_type = "1",
	}
	make_tense { -- indirect/unwitnessed recent past, variant #1
		tense = "indir_past",
		part_base = "pres_pfv_part",
		tense_ending = "тир",
		ending_type = "2",
	}
	make_tense { -- indirect/unwitnessed recent past, variant #2
		tense = "indir_past",
		part_base = "pres_pfv_part",
		tense_ending = "",
		ending_type = "2",
		ending_3sp = {}, -- -тир required, so only one form
		footnotes = {""},
	}
	make_tense { -- negative indirect/unwitnessed recent past, variant #1
		tense = "neg_indir_past",
		tense_ending = "баптир",
		ending_type = "2",
	}
	make_tense { -- negative indirect/unwitnessed recent past, variant #2
		tense = "neg_indir_past",
		tense_ending = "бап",
		ending_type = "2",
		ending_3sp = {}, -- -тир required, so only one form
	}
	make_tense { -- past habitual
		tense = "hab_past",
		tense_ending = "чу",
		ending_type = "2",
	}
	make_tense { -- negative past habitual
		tense = "neg_hab_past",
		tense_ending = "чу эмес",
		ending_type = "2",
	}
	make_tense { -- remote past habitual
		tense = "hab_rem_past",
		tense_ending = "чу эле",
		ending_type = "1",
	}
	make_tense { -- negative remote past habitual
		tense = "neg_hab_rem_past",
		tense_ending = "чу эле эмес",
		ending_type = "2",
	}
	make_tense { -- past unaccomplished
		tense = "unaccomp_past",
		part_base = "pres_impfv_part",
		tense_ending = " элек",
		ending_type = "2",
	}
	make_tense { -- uncertain future
		tense = "uncert_fut",
		part_base = "fut_part",
		tense_ending = "",
		ending_type = "2",
	}
	make_tense { -- negative uncertain future
		tense = "neg_uncert_fut",
		part_base = "neg_fut_part",
		tense_ending = "",
		ending_type = "2",
	}
	make_tense { -- "would" conditional 1
		tense = "would_cond_1",
		part_base = "fut_part",
		tense_ending = " эле",
		ending_type = "1",
	}
	make_tense { -- negative "would" conditional 1
		tense = "neg_would_cond_1",
		part_base = "neg_fut_part",
		tense_ending = " эле",
		ending_type = "1",
	}
	make_tense { -- "would" conditional 2
		tense = "would_cond_2",
		tense_ending = "Йт эле",
		ending_type = "1",
	}
	make_tense { -- negative "would" conditional 2
		tense = "neg_would_cond_2",
		tense_ending = "байт эле",
		ending_type = "1",
	}
	make_tense { -- counterfactual conditional
		tense = "cfact_cond",
		tense_ending = "мак",
		ending_type = "2",
	}
	make_tense { -- negative counterfactual conditional
		tense = "neg_cfact_cond",
		tense_ending = "мак эмес",
		ending_type = "2",
	}
	make_tense { -- imperative/hortative
		tense = "imp",
		tense_ending = "",
		ending_type = "1",
		ending_1s = "айин",
		ending_2s_inform = {"", {form = "гин", footnotes = {""}}},
		ending_2s_formal = "аңиз",
		ending_3sp = "син",
		ending_1p = {"Йли", "Йлик"},
		ending_2p_inform = "гила",
		ending_2p_formal = "аңиздар",
	}
	make_tense { -- negative imperative/hortative
		tense = "neg_imp",
		tense_ending = "",
		ending_type = "1",
		ending_1s = "байин",
		ending_2s_inform = {"ба", {form = "багин", footnotes = {""}}},
		ending_2s_formal = "баңиз",
		ending_3sp = "басин",
		ending_1p = {"байли", "байлик"},
		ending_2p_inform = "багила",
		ending_2p_formal = "баңиздар",
	}
	--[==[
	make_tense {
		tense = "opt",
		tense_ending = "ги",
		ending_type = "1",
		ending_3s = "си",
		ending_2p_inform = "лариң",
		ending_2p_formal = "лариңиз",
		ending_3p = "лари",
		postprocess = function(form)
			return form .. " келет"
		end,
	}]==]
	make_tense { -- "if" conditional
		tense = "if_cond",
		tense_ending = "са",
		ending_type = "1",
	}
	make_tense { -- negative "if" conditional
		tense = "neg_if_cond",
		tense_ending = "баса",
		ending_type = "1",
	}
end


-- Compute the categories to add the verb to, as well as the annotation to display in the
-- conjugation title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(conj_spec)
	local cats = {}
	local function inscat(cattype)
		m_table.insertIfNot(cats, "Kyrgyz " .. cattype)
	end
	local vowel_final_stem = rfind(conj_spec.stem, V .. "$")
	conj_spec.annotation = vowel_final_stem and "vowel-final" or "consonant-final"
	if vowel_final_stem then
		inscat("verbs with vowel-final stem")
	else
		inscat("verbs with consonant-final stem")
	end
	conj_spec.categories = cats
end


local function show_forms(conj_spec)
	local lemmas = {}
	if conj_spec.forms.inf then
		for _, inf in ipairs(conj_spec.forms.inf) do
			table.insert(lemmas, inf.form)
		end
	end
	local props = {
		lemmas = lemmas,
		slot_list = verb_slots_list,
		lang = lang,
		include_translit = true,
	}
	iut.show_forms(conj_spec.forms, props)
end


local function make_table(conj_spec)
	local forms = conj_spec.forms

	local header = mw.getCurrentFrame():expandTemplate{
		title = "inflection-table-top",
		args = {
			title = "{title}{annotation}",
			palette = "blue",
			tall = "yes",
			class = "wide tr-alongside", -- hack to suppress excess space below each term
			category = "conjugation",
		}
	}

	local table_spec = [=[
! colspan="3" | infinitive
| colspan="2" | {inf}
| colspan="999" rowspan="8" class="blank-end-row" |
|-
! colspan="3" style="background-color: var(--wikt-palette-blue-3);" | negative infinitive
| colspan="2" style="background-color: var(--wikt-palette-blue-3);" | {neg_inf}
|-
! rowspan="7" style="min-width:0" | participle
! colspan="2" | past
| colspan="2" | {past_part}
|-
! colspan="2" style="background-color: var(--wikt-palette-blue-3);" | negative past
| colspan="2" style="background-color: var(--wikt-palette-blue-3);" | {neg_past_part}
|-
! colspan="2" | future
| colspan="2" | {fut_part}
|-
! colspan="2" style="background-color: var(--wikt-palette-blue-3);" | negative future
| colspan="2" style="background-color: var(--wikt-palette-blue-3);" | {neg_fut_part}
|-
! colspan="2" | present perfective
| colspan="2" | {pres_pfv_part}
|-
! colspan="2" | present imperfective
| colspan="2" | {pres_impfv_part}
|-
! colspan="2" style="background-color: var(--wikt-palette-blue-3);" | negative present
| colspan="2" style="background-color: var(--wikt-palette-blue-3);" | {neg_pres_part}
|-
| class="separator" colspan="999" |
|-
! colspan="3" class="outer" |
! colspan="4" class="outer" | singular
! colspan="4" class="outer" | plural
|-
! colspan="3" rowspan="2" |
! rowspan="2" | 1<sup>st</sup> person
! colspan="2" | 2<sup>nd</sup> person
! rowspan="2" | 3<sup>rd</sup> person
! rowspan="2" | 1<sup>st</sup> person
! colspan="2" | 2<sup>nd</sup> person
! rowspan="2" | 3<sup>rd</sup> person
|-
! informal
! formal
! informal
! formal
|-
! colspan="3" |
! {men}
! {sen}
! {siz}
! {al}
! {biz}
! {siler}
! {sizder}
! {alar}
|- style="border-top: 2px solid black;"
! rowspan="13" style="min-width:0" | past
! rowspan="2" class="secondary" | recent
! class="secondary" | positive
| {rec_past_1s}
| {rec_past_2s_inform}
| {rec_past_2s_formal}
| {rec_past_3s}
| {rec_past_1p}
| {rec_past_2p_inform}
| {rec_past_2p_formal}
| {rec_past_3p}
|-
! style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_rec_past_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_rec_past_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_rec_past_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_rec_past_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_rec_past_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_rec_past_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_rec_past_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_rec_past_3p}
|-
! rowspan="2" class="secondary" | remote/general
! class="secondary" | positive
| {gen_past_1s}
| {gen_past_2s_inform}
| {gen_past_2s_formal}
| {gen_past_3s}
| {gen_past_1p}
| {gen_past_2p_inform}
| {gen_past_2p_formal}
| {gen_past_3p}
|-
! style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_gen_past_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_gen_past_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_gen_past_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_gen_past_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_gen_past_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_gen_past_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_gen_past_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_gen_past_3p}
|-
! rowspan="2" class="secondary" | distant remote/general
! class="secondary" | positive
| {dist_gen_past_1s}
| {dist_gen_past_2s_inform}
| {dist_gen_past_2s_formal}
| {dist_gen_past_3s}
| {dist_gen_past_1p}
| {dist_gen_past_2p_inform}
| {dist_gen_past_2p_formal}
| {dist_gen_past_3p}
|-
! class="secondary" style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_dist_gen_past_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_dist_gen_past_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_dist_gen_past_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_dist_gen_past_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_dist_gen_past_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_dist_gen_past_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_dist_gen_past_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_dist_gen_past_3p}
|-
! rowspan="2" class="secondary" | indirect/unwitnessed recent
! class="secondary" | positive
| {indir_past_1s}
| {indir_past_2s_inform}
| {indir_past_2s_formal}
| {indir_past_3s}
| {indir_past_1p}
| {indir_past_2p_inform}
| {indir_past_2p_formal}
| {indir_past_3p}
|-
! class="secondary" style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_indir_past_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_indir_past_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_indir_past_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_indir_past_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_indir_past_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_indir_past_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_indir_past_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_indir_past_3p}
|-
! rowspan="2" class="secondary" | habitual
! class="secondary" | positive
| {hab_past_1s}
| {hab_past_2s_inform}
| {hab_past_2s_formal}
| {hab_past_3s}
| {hab_past_1p}
| {hab_past_2p_inform}
| {hab_past_2p_formal}
| {hab_past_3p}
|-
! class="secondary" style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_past_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_past_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_past_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_past_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_past_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_past_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_past_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_past_3p}
|-
! rowspan="2" class="secondary" | remote habitual
! class="secondary" | positive
| {hab_rem_past_1s}
| {hab_rem_past_2s_inform}
| {hab_rem_past_2s_formal}
| {hab_rem_past_3s}
| {hab_rem_past_1p}
| {hab_rem_past_2p_inform}
| {hab_rem_past_2p_formal}
| {hab_rem_past_3p}
|-
! class="secondary" style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_rem_past_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_rem_past_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_rem_past_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_rem_past_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_rem_past_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_rem_past_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_rem_past_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_hab_rem_past_3p}
|-
! class="secondary" | past unaccomplished
! class="secondary" |
| {unaccomp_past_1s}
| {unaccomp_past_2s_inform}
| {unaccomp_past_2s_formal}
| {unaccomp_past_3s}
| {unaccomp_past_1p}
| {unaccomp_past_2p_inform}
| {unaccomp_past_2p_formal}
| {unaccomp_past_3p}
|- style="border-top: 2px solid black;"
! rowspan="4" style="min-width:0" | non-past
! rowspan="2" class="secondary" | aorist
! class="secondary" | positive
| {aor_1s}
| {aor_2s_inform}
| {aor_2s_formal}
| {aor_3s}
| {aor_1p}
| {aor_2p_inform}
| {aor_2p_formal}
| {aor_3p}
|-
! class="secondary" style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_aor_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_aor_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_aor_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_aor_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_aor_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_aor_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_aor_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_aor_3p}
|-
! rowspan="2" class="secondary" | future uncertain
! class="secondary" | positive
| {uncert_fut_1s}
| {uncert_fut_2s_inform}
| {uncert_fut_2s_formal}
| {uncert_fut_3s}
| {uncert_fut_1p}
| {uncert_fut_2p_inform}
| {uncert_fut_2p_formal}
| {uncert_fut_3p}
|-
! class="secondary" style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_uncert_fut_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_uncert_fut_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_uncert_fut_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_uncert_fut_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_uncert_fut_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_uncert_fut_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_uncert_fut_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_uncert_fut_3p}
|- style="border-top: 2px solid black;"
! rowspan="2" style="min-width:0" | imperative/hortative
! rowspan="2" class="secondary" |
! class="secondary" | positive
| {imp_1s}
| {imp_2s_inform}
| {imp_2s_formal}
| {imp_3s}
| {imp_1p}
| {imp_2p_inform}
| {imp_2p_formal}
| {imp_3p}
|-
! class="secondary" style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_imp_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_imp_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_imp_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_imp_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_imp_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_imp_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_imp_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_imp_3p}
|- style="border-top: 2px solid black;"
! rowspan="8" style="min-width:0" | conditional
! rowspan="2" class="secondary" | ''would'' type 1
! class="secondary" | positive
| {would_cond_1_1s}
| {would_cond_1_2s_inform}
| {would_cond_1_2s_formal}
| {would_cond_1_3s}
| {would_cond_1_1p}
| {would_cond_1_2p_inform}
| {would_cond_1_2p_formal}
| {would_cond_1_3p}
|-
! class="secondary" style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_1_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_1_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_1_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_1_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_1_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_1_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_1_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_1_3p}
|-
! rowspan="2" class="secondary" | ''would'' type 2
! class="secondary" | positive
| {would_cond_2_1s}
| {would_cond_2_2s_inform}
| {would_cond_2_2s_formal}
| {would_cond_2_3s}
| {would_cond_2_1p}
| {would_cond_2_2p_inform}
| {would_cond_2_2p_formal}
| {would_cond_2_3p}
|-
! class="secondary" style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_2_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_2_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_2_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_2_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_2_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_2_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_2_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_would_cond_2_3p}
|-
! rowspan="2" class="secondary" | counterfactual
! class="secondary" | positive
| {cfact_cond_1s}
| {cfact_cond_2s_inform}
| {cfact_cond_2s_formal}
| {cfact_cond_3s}
| {cfact_cond_1p}
| {cfact_cond_2p_inform}
| {cfact_cond_2p_formal}
| {cfact_cond_3p}
|-
! class="secondary" style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_cfact_cond_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_cfact_cond_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_cfact_cond_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_cfact_cond_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_cfact_cond_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_cfact_cond_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_cfact_cond_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_cfact_cond_3p}
|-
! rowspan="2" class="secondary" | ''if''
! class="secondary" | positive
| {if_cond_1s}
| {if_cond_2s_inform}
| {if_cond_2s_formal}
| {if_cond_3s}
| {if_cond_1p}
| {if_cond_2p_inform}
| {if_cond_2p_formal}
| {if_cond_3p}
|-
! class="secondary" style="background-color: var(--wikt-palette-blue-3);" | negative
| style="background-color: var(--wikt-palette-blue-3);" | {neg_if_cond_1s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_if_cond_2s_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_if_cond_2s_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_if_cond_3s}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_if_cond_1p}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_if_cond_2p_inform}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_if_cond_2p_formal}
| style="background-color: var(--wikt-palette-blue-3);" | {neg_if_cond_3p}
]=]

	local footer = mw.getCurrentFrame():expandTemplate{ title = "inflection-table-bottom",
		args = {notes = "{footnote}"}
	}

	if conj_spec.title then
		forms.title = conj_spec.title
	else
		forms.title = 'Conjugation of <i lang="ky" class="Cyrl">' .. forms.lemma .. '</i>'
	end

	local function make_text_smaller(text)
		return "(<span style=\"font-size: smaller;\">" .. text .. "</span>)"
	end

	local annotation = conj_spec.annotation
	if annotation == "" then
		forms.annotation = ""
	else
		forms.annotation = " " .. make_text_smaller(annotation)
	end

	local function tag_text(text)
		return make_text_smaller(m_script_utilities.tag_text(text, lang))
	end

	-- grammatical terms used in the table
	forms.men = tag_text("мен")
	forms.sen = tag_text("сен")
	forms.siz = tag_text("сиз")
	forms.al = tag_text("ал")
	forms.biz = tag_text("биз")
	forms.siler = tag_text("силер")
	forms.sizder = tag_text("сиздер")
	forms.alar = tag_text("алар")

	return m_string_utilities.format(header .. table_spec .. footer, forms)
end


local function infinitive_to_stem(inf)
	local stem = rsub(inf, "()%1$", "")
	if stem == inf then
		stem = inf:gsub("ёо$", "й")
	end
	if stem == inf then
		stem = inf:gsub("юу$", "й")
	end
	if stem == inf then
		error(("Unable to compute stem from infinitive %s, doesn't end in long rounded vowel"):format(inf))
	end
	if stem:find("б$") then
		stem = stem:gsub("б$", "п")
	elseif stem:find("г$") then
		stem = stem:gsub("г$", "к")
	end
	return stem
end


-- Externally callable function to parse and conjine a verb where all forms
-- are given manually. Return value is WORD_SPEC, an object where the conjugated
-- forms are in `WORD_SPEC.forms` for each slot. If there are no values for a
-- slot, the slot key will be missing. The value for a given slot is a list of
-- objects {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(parent_args)
	local params = {
		stem = {template_default = "иште"}, -- specify the stem if it ends in a vowel, п or к
		title = true,
		pagename = {template_default = "иштөө"},
	}
	for _, part_accel in ipairs(participles) do
		local part, accel = unpack(part_accel)
		params = true
		params = true
	end

	local args = m_para.process(parent_args, params)
	local pagename = args.pagename or mw.loadData("Module:headword/data").pagename
	local lemma = pagename
	local conj_spec = {
		args = args,
		lemma = lemma,
		stem = args.stem or infinitive_to_stem(lemma),
		title = args.title,
		forms = {},
	}
	process_overrides(conj_spec.forms, args)
	conjugate_verb(conj_spec, lemma)
	compute_categories_and_annotation(conj_spec)
	return conj_spec
end


-- Entry point for {{ky-conj}}.
function export.show(frame)
	local parent_args = frame:getParent().args
	local conj_spec = export.do_generate_forms(parent_args)
	show_forms(conj_spec)
	return make_table(conj_spec) .. require("Module:utilities").format_categories(conj_spec.categories, lang)
end

return export