Module:User:Surjection/izh-conj

local export = {} local m_izh = require("Module:izh")

local function get_stem(word, ending) if mw.ustring.match(word, ending .. "$") then return word:sub(1, #word - #ending) end error("Unexpected ending for this inflection type! Wrong type?") end

local function frontalize(w, vh) if vh == "ä" then w = mw.ustring.gsub(w, "[aou]", { a = "ä", o = "ö", u = "y" }) end return w end

local function elongate(stem, condition) if condition == nil or condition then -- already long? if mw.ustring.match(stem, m_izh.vowel .. m_izh.vowel .. "$") then for k, v in pairs(m_izh.vowel_sequences) do if mw.ustring.find(stem, v .. "$", pos) then return stem end end end return stem .. mw.ustring.sub(stem, -1) else return stem end end

local function geminate(c) if mw.ustring.match(c, m_izh.consonant .. m_izh.consonant .. "$") then return c	end return c .. mw.ustring.sub(c, -1) end

local function join(...) local t = {} for _, s in ipairs(arg) do		if type(s) == "table" then for _, v in ipairs(s) do				table.insert(t, v)			end elseif type(s) == "string" then table.insert(t, s)		end end return t end

local function gsub_all(t, p, q)	if type(t) == "string" then return mw.ustring.gsub(t, p, q)	end local r = {} for _, v in ipairs(t) do		table.insert(r, mw.ustring.gsub(v, p, q)) end return r end

local function append(t, x)	if not x then return t end if type(t) == "string" then return t .. x	end local r = {} for _, v in ipairs(t) do table.insert(r, v .. x)	end return r end

local function elongate_all(t) if type(t) == "string" then return elongate(t) end local r = {} for _, v in ipairs(t) do		table.insert(r, elongate(v)) end return r end

local function make_gradation(s, w)	if s == w then return "no gradation" else return s .. "-" .. w .. " gradation" end end

local function with_note(note, t)	if not note then return t end if type(t) == "string" then return { { form = t, note = note } } end local r = {} for _, v in ipairs(t) do		table.insert(r, { form = v, note = note }) end return r end

local function will_geminate(forms, finalc, finalv) if type(forms) == "string" then local stem = forms .. finalc .. finalv local gem = m_izh.guess_gemination(stem) if not gem then return stem end return gem .. finalv end local r = {} for _, form in ipairs(forms) do		table.insert(r, will_geminate(form, finalc, finalv)) end return r end

local function geminate_backwards(c) if mw.ustring.match(c, m_izh.vowel .. m_izh.consonant .. m_izh.vowel .. "$") then local stem = mw.ustring.sub(c, 1, -3) local finalc = mw.ustring.sub(c, -2, -2) local finalv = mw.ustring.sub(c, -1, -1) return will_geminate(stem, finalc, finalv) elseif mw.ustring.match(c, m_izh.vowel .. m_izh.consonant .. m_izh.vowel .. m_izh.vowel .. "$") then local stem = mw.ustring.sub(c, 1, -4) local finalc = mw.ustring.sub(c, -3, -3) local finalv = mw.ustring.sub(c, -2, -2) local finalv2 = mw.ustring.sub(c, -1, -1) return will_geminate(stem, finalc, finalv) .. finalv2 else return c	end end

local function will_geminate_backwards(forms, addv) if type(forms) == "string" then return geminate_backwards(forms) .. addv end local r = {} for _, form in ipairs(forms) do		table.insert(r, will_geminate_backwards(form, addv)) end return r end

local function elongate_and_geminate(c) return elongate(geminate_backwards(c)) end

local function elongate_and_geminate_all(t) if type(t) == "string" then return elongate_and_geminate(t) end local r = {} for _, v in ipairs(t) do		table.insert(r, elongate_and_geminate(v)) end return r end

local function can_geminate(data, forms, finalc, finalv) if data.geminate == false then return append(forms, finalc .. finalv) end return will_geminate(data, forms, finalc, finalv) end

local function chiefly_in_dialect(...) if #arg == 1 then return "Chiefly in the " .. arg[1] .. " dialect." elseif #arg > 1 then return "Chiefly in the " .. require("Module:table").serialCommaJoin(arg) .. " dialects." else return 1 end end

local function get_any(stems) if type(stems) == "string" then return stems elseif type(stems) == "table" then return stems[1] end end

local function process(data, result) local A = data.vh	-- present stem (strong, weak) local pres_s = result.stem_pres_s or result.stem_pres local pres_w = result.stem_pres_w or result.stem_pres -- past stem (strong, weak) local past_s = result.stem_past_s or result.stem_past local past_w = result.stem_past_w or result.stem_past -- present passive stem local pres_v = result.stem_pres_v -- past passive stem local past_v = result.stem_past_v -- 1st infinitive stem local inf1 = result.stem_inf1 or pres_s -- 2nd infinitive local inf2 = result.stem_inf2 or pres_s -- 3rd infinitive / 3rd person stem local inf3 = result.stem_inf3 or pres_s -- conditional stem local cond = result.stem_cond or append(gsub_all(pres_s, "[ei]$", ""), "i") -- imperative stem local impr = result.stem_impr or pres_s -- potential stem local potn = result.stem_potn or append(pres_s, "n") -- present participle stem local pres_p = result.stem_pres_p or pres_s -- past participle stem local past_p = result.stem_past_p or append(pres_s, "n") -- present third-person singular stem local pres_3sg = result.stem_pres_3sg or inf3 if pres_3sg ~= geminate_backwards(pres_3sg) then result.geminate = true end

result.pres_part = append(pres_p, "v" .. A) result.pres_pasv_part = append(past_v, A .. "v" .. A)	result.past_part = gsub_all(append(past_p, "t"), "([lnprs])[lnprs]t$", "%1t") result.past_part_pl = append(past_p, "eet") result.past_pasv_part = append(past_v, frontalize("u", A))

result.pres_pasv = append(pres_v, A .. A)	result.pres_1sg = append(pres_w, "n") result.pres_2sg = append(pres_w, "t") result.pres_3sg = append(elongate_and_geminate_all(pres_3sg), result.monosyllabic and "p" or nil) result.pres_1pl = append(pres_w, "mm" .. A) result.pres_2pl = append(pres_w, "tt" .. A)	result.pres_3pl = join(		not result.monosyllabic and with_note(chiefly_in_dialect("Soikkola"), append(result.pres_3sg, "t")),		with_note(not result.monosyllabic and chiefly_in_dialect("Ala-Laukaa"), append(pres_s, "v" .. A .. "t")),		result.pres_pasv) result.pres_conn = pres_w result.pres_pasv_conn = append(pres_v, A)

result.past_pasv = append(past_v, "ii") result.past_1sg = append(past_w, "n") result.past_2sg = append(past_w, "t") if result.has_short_past_2sg then result.past_2sg = join(result.past_2sg, with_note(chiefly_in_dialect("Soikkola"), append(elongate_and_geminate_all(get_stem(past_w, "si")), "st"))) end result.past_3sg = past_s result.past_1pl = append(past_w, "mm" .. A) result.past_2pl = append(past_w, "tt" .. A)	result.past_3pl = join(		not result.monosyllabic and with_note(chiefly_in_dialect("Soikkola"), append(elongate_and_geminate_all(result.past_3sg), "t")),		with_note(not result.monosyllabic and chiefly_in_dialect("Ala-Laukaa"), append(past_s, "v" .. A .. "t")),		result.past_pasv) result.past_conn = result.past_part result.past_conn_pl = result.past_part_pl result.past_pasv_conn = result.past_pasv_part

result.cond_pasv = append(past_v, A .. "is") result.cond_1sg = append(cond, "sin") result.cond_2sg = join(append(cond, "sit"), with_note(chiefly_in_dialect("Soikkola"), append(elongate_and_geminate_all(cond), "st"))) result.cond_3sg = append(cond, "s") result.cond_1pl = append(cond, "simm" .. A) result.cond_2pl = append(cond, "sitt" .. A)	result.cond_3pl = join(		with_note(chiefly_in_dialect("Soikkola"), append(cond, "siit")),		with_note(chiefly_in_dialect("Ala-Laukaa"), append(cond, "siv" .. A .. "t")),		result.cond_pasv) result.cond_conn = result.cond_3sg result.cond_pasv_conn = result.cond_pasv

result.impr_pasv = append(will_geminate(past_v .. A, "k", frontalize("o", A)), frontalize("o", A)) result.impr_2sg = pres_w result.impr_3sg = append(will_geminate(impr, "k", frontalize("o", A)), frontalize("o", A)) result.impr_2pl = append(will_geminate(impr, "k", A), A)	result.impr_3pl = append(result.impr_3sg, "t") result.impr_conn = append(impr, frontalize("ko", A)) result.impr_pasv_conn = append(past_v, frontalize("ako", A))

result.potn_pasv = will_geminate_backwards(append(past_v, frontalize("ano", A)), frontalize("o", A)) result.potn_1sg = append(potn, "en") result.potn_2sg = append(potn, "et") result.potn_3sg = will_geminate_backwards(append(potn, frontalize("o", A)), frontalize("o", A)) result.potn_1pl = append(potn, "emm" .. A) result.potn_2pl = append(potn, "ett" .. A)	result.potn_3pl = append(result.potn_3sg, "t") result.potn_conn = append(potn, "e") result.potn_pasv_conn = append(past_v, A .. "ne")

result.inf1 = { data.title } if m_izh.guess_elongation(get_any(inf2) .. "e") then inf2 = append(inf2, "e") if mw.ustring.match(inf2, m_izh.vowel .. m_izh.vowel .. "$") then inf2 = mw.ustring.sub(inf2, 1, -2) .. "jee" else inf2 = inf2 .. "e" end else -- potentially geminate inf2 = will_geminate_backwards(inf2, "e") end result.inf2_ine = append(inf2, "s") result.inf2_ins = append(inf2, "n") result.inf3_ill = append(will_geminate(inf3, "m", A), A) result.inf3_ine = append(inf3, "m" .. A .. (m_izh.guess_elongation(inf3 .. "m" .. A) and A or "") .. "s") result.inf3_ela = append(inf3, "m" .. A .. "st") result.inf3_abe = append(inf3, "m" .. A .. "t" .. A)	result.inf4_nom = append(will_geminate(inf3, "m", "i"), "in") result.inf4_par = join(append(inf3, "mist" .. A), append(inf3, "mist"))

if result.short_past_3sg then result.past_3sg = gsub_all(result.past_3sg, "i$", "") end

-- cleanup virtual syllable breaks for k, v in pairs(result) do		if type(v) == "string" then result[k] = mw.ustring.gsub(v, m_izh.virtual_syllable_break, "") elseif type(v) == "table" then for i, f in ipairs(v) do				if type(f) == "table" and f.form then f.form = mw.ustring.gsub(f.form, m_izh.virtual_syllable_break, "") elseif type(f) == "string" then v[i] = mw.ustring.gsub(f, m_izh.virtual_syllable_break, "") end end end end return result end

local function ungeminate(data, result, strong, weak, stem) if data.geminate ~= false and mw.ustring.len(strong) == 1 then -- gemination local final = strong if final == "j" then final = "i" end if mw.ustring.match(stem, final .. "$") then result.geminate = true return get_stem(stem, final) end end return stem end

-- inflection classes begin local inflections = {}

inflections["ampua"] = function (data) local result = { typeno = "1" } local word = data.title local strong = data.args[1] or error("must specify strong grade") local weak = data.args[2] or error("must specify weak grade") local vh = data.vh	local final = mw.ustring.sub(word, -2, -2) local stem = ungeminate(data, result, strong, weak, get_stem(word, strong .. final .. vh))

if strong ~= "" and weak == "" then weak = m_izh.virtual_syllable_break end result.stem_pres_s = stem .. strong .. final result.stem_pres_w = stem .. weak .. final result.stem_past_s = stem .. strong .. final .. "i" result.stem_past_w = stem .. weak .. final .. "i" result.stem_pres_v = stem .. weak .. final .. "t" result.stem_past_v = stem .. weak .. final .. "tt" result.grade = make_gradation(strong, weak) return process(data, result) end

inflections["kirjuttaa"] = function (data) local result = { typeno = "2" } local word = data.title local strong = data.args[1] or error("must specify strong grade") local weak = data.args[2] or error("must specify weak grade") local vh = data.vh local stem = ungeminate(data, result, strong, weak, get_stem(word, frontalize(strong .. "aa", vh)))

if strong ~= "" and weak == "" then weak = m_izh.virtual_syllable_break end result.stem_pres_s = stem .. strong .. vh result.stem_pres_w = stem .. weak .. vh result.stem_past_s = stem .. strong .. "i" result.stem_past_w = stem .. weak .. "i" result.stem_pres_v = stem .. weak .. "et" result.stem_past_v = stem .. weak .. "ett" result.grade = make_gradation(strong, weak) return process(data, result) end

inflections["kyntää"] = function (data) local result = { typeno = "3" } local word = data.title local strong = data.args[1] or error("must specify strong grade") local weak = data.args[2] or error("must specify weak grade") local vh = data.vh local stem = get_stem(word, frontalize(strong .. "aa", vh))

result.stem_pres_s = stem .. strong .. vh result.stem_pres_w = stem .. weak .. vh result.stem_past = stem .. "nsi" result.stem_pres_v = stem .. weak .. "et" result.stem_past_v = stem .. weak .. "ett" result.grade = make_gradation(strong, weak) return process(data, result) end

inflections["antaa"] = function (data) local result = { typeno = "4" } local word = data.title local strong = data.args[1] or error("must specify strong grade") local weak = data.args[2] or error("must specify weak grade") local vh = data.vh local stem = ungeminate(data, result, strong, weak, get_stem(word, frontalize(strong .. "aa", vh)))

result.stem_pres_s = stem .. strong .. vh result.stem_pres_w = stem .. weak .. vh result.stem_past_s = stem .. strong .. frontalize("oi", vh) result.stem_past_w = stem .. weak .. frontalize("oi", vh) result.stem_pres_v = stem .. weak .. "et" result.stem_past_v = stem .. weak .. "ett" result.grade = make_gradation(strong, weak) return process(data, result) end

inflections["laskia"] = function (data) local result = { typeno = "5" } local word = data.title local strong = data.args[1] or error("must specify strong grade") local weak = data.args[2] or error("must specify weak grade") local vh = data.vh local stem = ungeminate(data, result, strong, weak, get_stem(word, frontalize(strong .. "ia", vh)))

result.stem_pres_s = stem .. strong .. "e" result.stem_pres_w = stem .. weak .. "e" result.stem_past_s = stem .. strong .. "i" result.stem_past_w = stem .. weak .. "i" result.stem_pres_v = stem .. weak .. "et" result.stem_past_v = stem .. weak .. "ett" result.stem_inf2 = stem .. strong .. "i" result.stem_inf3 = stem .. strong .. frontalize("o", vh) result.grade = make_gradation(strong, weak) return process(data, result) end

inflections["tuntia"] = function (data) local result = { typeno = "6" } local word = data.title local strong = data.args[1] or error("must specify strong grade") local weak = data.args[2] or error("must specify weak grade") local vh = data.vh local stem = ungeminate(data, result, strong, weak, get_stem(word, frontalize(strong .. "ia", vh)))

local past_stem = { ["nt"] = "ns", ["ht"] = "ks" }

result.stem_pres_s = stem .. strong .. "e" result.stem_pres_w = stem .. weak .. "e" result.stem_past = stem .. (past_stem[strong] or error("The tuntia type is not supported for this verb")) .. "i" result.stem_pres_v = stem .. weak .. "et" result.stem_past_v = stem .. weak .. "ett" result.stem_inf2 = stem .. strong .. "i" result.stem_inf3 = stem .. strong .. frontalize("o", vh) result.grade = make_gradation(strong, weak) return process(data, result) end

inflections["oppia"] = function (data) local result = { typeno = "7" } local word = data.title local strong = data.args[1] or error("must specify strong grade") local weak = data.args[2] or error("must specify weak grade") local vh = data.vh local stem = ungeminate(data, result, strong, weak, get_stem(word, frontalize(strong .. "ia", vh)))

result.stem_pres_s = stem .. strong .. "i" result.stem_pres_w = stem .. weak .. "i" result.stem_past_s = stem .. strong .. "i" result.stem_past_w = stem .. weak .. "i" result.stem_pres_v = stem .. weak .. "it" result.stem_past_v = stem .. weak .. "itt" result.grade = make_gradation(strong, weak) return process(data, result) end

inflections["voija"] = function (data) local result = { typeno = "8" } local word = data.title local vh = data.vh	local stem = get_stem(word, frontalize("ja", vh)) if #m_izh.split_syllables(stem) > 1 then error("Verb stem must be monosyllabic for the voija type") end

result.stem_pres = stem result.stem_past = stem result.stem_pres_v = stem .. "j" result.stem_past_v = stem .. "t" result.stem_inf2 = stem .. "j" result.monosyllabic = true return process(data, result) end

inflections["jäävvä"] = function (data) local result = { typeno = "9" } local word = data.title local vh = data.vh	local stem = get_stem(word, frontalize("vva", vh)) if #m_izh.split_syllables(stem) > 1 then error("Verb stem must be monosyllabic for the jäävvä type") end

result.stem_pres = stem result.stem_past = mw.ustring.sub(stem, 1, -2) .. "i" result.stem_pres_v = stem .. "vv" result.stem_past_v = stem .. "t" result.stem_cond = result.stem_past result.stem_inf2 = stem .. "vv" result.monosyllabic = true return process(data, result) end

inflections["käyvvä"] = function (data) local result = { typeno = "10" } local word = data.title local vh = data.vh	local stem = get_stem(word, frontalize("vva", vh)) if #m_izh.split_syllables(stem) > 1 then error("Verb stem must be monosyllabic for the käyvvä type") end

result.stem_pres = stem result.stem_past = mw.ustring.sub(stem, 1, -2) .. "i" result.stem_pres_v = stem .. "vv" result.stem_past_v = stem .. "t" result.stem_cond = result.stem_past result.stem_inf2 = stem .. "vv" result.monosyllabic = true return process(data, result) end

inflections["pessä"] = function (data) local result = { typeno = "11" } local word = data.title local vh = data.vh	local stem = get_stem(word, frontalize("ssa", vh))

result.stem_pres = stem .. "se" result.stem_past = stem .. "si" result.stem_pres_v = stem .. "ss" result.stem_past_v = stem .. "st" result.stem_inf3 = stem .. frontalize("so", vh) result.stem_potn = stem .. "ss" result.stem_impr = stem .. "s" result.stem_past_p = stem .. "ss" return process(data, result) end

inflections["kuulla"] = function (data) local result = { typeno = "12" } local word = data.title local vh = data.vh	local stem = get_stem(word, vh) local finalgem = mw.ustring.sub(stem, -2, -1) local finals = { ["ll"] = "l", ["nn"] = "n", ["rr"] = "r" }	local final = finals[finalgem] or error("Unsupported stem for kuulla") stem = get_stem(stem, finalgem)

result.stem_pres = stem .. final .. "e" result.stem_past = stem .. final .. "i" result.stem_pres_v = stem .. finalgem result.stem_past_v = stem .. final .. "t" result.stem_inf2 = stem .. finalgem result.stem_inf3 = stem .. final .. frontalize("o", vh) result.stem_potn = stem .. finalgem result.stem_impr = stem .. final result.stem_past_p = stem .. finalgem return process(data, result) end

inflections["valita"] = function (data) local result = { typeno = "13" } local word = data.title local vh = data.vh	local stem = get_stem(word, frontalize("ta", vh))

result.stem_pres = stem .. "tse" result.stem_past = stem .. "tsi" result.stem_pres_v = stem .. "t" result.stem_past_v = stem .. "tt" result.stem_inf2 = stem .. "t" result.stem_inf3 = stem .. frontalize("tso", vh) result.stem_potn = stem .. "nn" result.stem_impr = stem .. "t" result.stem_past_p = stem .. "n" return process(data, result) end

inflections["joossa"] = function (data) local result = { typeno = "14" } local word = data.title local vh = data.vh	local stem = get_stem(word, frontalize("ssa", vh))

result.stem_pres = stem .. "kse" result.stem_past = stem .. "ksi" result.stem_pres_v = stem .. "ss" result.stem_past_v = stem .. "st" result.stem_inf2 = stem .. "ss" result.stem_inf3 = stem .. frontalize("kso", vh) result.stem_potn = stem .. "ss" result.stem_impr = stem .. "s" result.stem_past_p = stem .. "ss" return process(data, result) end

inflections["valeta"] = function (data) local result = { typeno = "15" } local word = data.title local vh = data.vh	local stem = get_stem(word, frontalize("ta", vh)) local weak = data.args[1] or error("must specify weak grade") local strong = data.args[2] or error("must specify strong grade") local final = mw.ustring.sub(stem, -1, -1) stem = get_stem(stem, weak .. final)

result.stem_pres = stem .. strong .. final .. "ne" result.stem_past = stem .. strong .. final .. "ni" result.stem_pres_v = stem .. weak .. final .. "t" result.stem_past_v = stem .. weak .. final .. "tt" result.stem_inf2 = stem .. weak .. final .. "t" result.stem_inf3 = stem .. strong .. final .. "n" .. frontalize("o", vh) result.stem_impr = stem .. weak .. final .. "t" result.stem_potn = stem .. weak .. final .. "n" result.stem_past_p = stem .. weak .. final .. "nn" result.grade = make_gradation(strong, weak) return process(data, result) end

inflections["maata"] = function (data) local result = { typeno = "16" } local word = data.title local vh = data.vh	local stem = get_stem(word, frontalize("ta", vh)) local weak = data.args[1] or error("must specify weak grade") local strong = data.args[2] or error("must specify strong grade") local final = mw.ustring.sub(stem, -1, -1) stem = get_stem(stem, weak .. final) local gem = will_geminate(stem, strong, final) if gem ~= stem .. strong .. final then result.geminate = true end

result.stem_pres = gem .. final result.stem_past = stem .. strong .. (final ~= "i" and final ~= "e" and final or "") .. "isi" result.stem_pres_v = stem .. weak .. final .. "t" result.stem_past_v = stem .. weak .. final .. "tt" result.stem_inf1 = stem .. strong .. final result.stem_inf2 = stem .. weak .. final .. "t" result.stem_inf3 = result.stem_pres_w result.stem_cond = stem .. strong .. final .. "j" .. vh .. "i" result.stem_impr = stem .. weak .. final .. "t" result.stem_potn = stem .. weak .. final .. "nn" result.stem_pres_p = result.stem_pres_w result.stem_past_p = stem .. weak .. final .. "nn" result.stem_pres_3sg = stem .. strong .. final .. "j" .. vh

result.short_past_3sg = true result.has_short_past_2sg = true

result.grade = make_gradation(strong, weak) return process(data, result) end

inflections["hävetä"] = function (data) local result = { typeno = "16" } local word = data.title local vh = data.vh	local stem = get_stem(word, frontalize("eta", vh)) local weak = data.args[1] or error("must specify weak grade") local strong = data.args[2] or error("must specify strong grade") local final = "i" stem = get_stem(stem, weak) local gem = will_geminate(stem, strong, final) if gem ~= stem .. strong .. final then result.geminate = true end

result.stem_pres = gem .. final result.stem_past = stem .. strong .. "isi" result.stem_pres_v = stem .. weak .. "et" result.stem_past_v = stem .. weak .. "ett" result.stem_inf1 = stem .. strong .. final result.stem_inf2 = stem .. weak .. "et" result.stem_inf3 = result.stem_pres_w result.stem_cond = stem .. strong .. final .. "j" .. vh .. "i" result.stem_impr = stem .. weak .. "et" result.stem_potn = stem .. weak .. "enn" result.stem_pres_p = result.stem_pres_w result.stem_past_p = stem .. weak .. "enn" result.stem_pres_3sg = stem .. strong .. final .. "j" .. vh

result.short_past_3sg = true result.has_short_past_2sg = true

result.grade = make_gradation(strong, weak) return process(data, result) end

inflections["laskiissa"] = function (data) local result = { typeno = "17" } local word = data.title local vh = data.vh	local stem = get_stem(word, frontalize("ssa", vh)) local truncate = mw.ustring.sub(stem, 1, -2)

result.stem_pres_s = stem result.stem_pres_w = stem result.stem_past = truncate .. "isi" result.stem_pres_v = stem .. "ss" result.stem_past_v = stem .. "st" result.stem_inf2 = stem .. "ss" result.stem_inf3 = stem result.stem_impr = stem .. "s" result.stem_potn = stem .. "ss" result.stem_cond = stem .. "ssi" result.stem_pres_p = stem result.stem_past_p = stem .. "ss" result.stem_pres_3sg = stem .. "j" .. vh	result.short_past_3sg = true result.has_short_past_2sg = true return process(data, result) end

inflections["praavihussa"] = function (data) local result = { typeno = "18" } local word = data.title local vh = data.vh	local stem = get_stem(word, frontalize("ssa", vh))

result.stem_pres = stem result.stem_past = stem .. "i" result.stem_pres_v = stem .. "ss" result.stem_past_v = stem .. "st" result.stem_inf2 = stem .. "ss" result.stem_impr = stem .. "s" result.stem_potn = stem .. "ss" result.stem_past_p = stem .. "ss"

return process(data, result) end

-- inflection classes end

local conj_table = [=[{| class="inflection-table vsSwitcher" data-toggle-category="conjugation" style="border:1px solid #CCCCFF;text-align:left;" ! colspan=6 class="vsToggleElement" style="background:rgb(80%,80%,100%);text-align:left;width:30em;"| Conjugation of ! colspan=6 style="width:10em;" | Indikativa ! colspan=3 style="width:10em;" | Preesens ! colspan=3 style="width:10em;" | Perfekta ! style="width:10em;" | ! style="width:13em; background:rgb(90%,90%,100%)" | positive ! style="width:13em; background:rgb(90%,90%,100%)" | negative ! style="width:10em;" | ! style="width:13em; background:rgb(90%,90%,100%)" | positive ! style="width:13em; background:rgb(90%,90%,100%)" | negative ! style="width:11em; background:rgb(80%,80%,100%)" | 1st singular ! style="width:11em; background:rgb(80%,80%,100%)" | 1st singular ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 1st plural ! style="width:11em; background:rgb(80%,80%,100%)" | 1st plural ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd plural ! style="width:11em; background:rgb(80%,80%,100%)" | impersonal ! style="width:11em; background:rgb(80%,80%,100%)" | impersonal ! colspan=3 style="width:11em;" | Imperfekta ! colspan=3 style="width:11em;" | Pluskvamperfekta ! style="width:11em;" | ! style="width:11em; background:rgb(90%,90%,100%)" | positive ! style="width:11em; background:rgb(90%,90%,100%)" | negative ! style="width:11em;" | ! style="width:11em; background:rgb(90%,90%,100%)" | positive ! style="width:11em; background:rgb(90%,90%,100%)" | negative ! style="width:11em; background:rgb(80%,80%,100%)" | 1st singular ! style="width:11em; background:rgb(80%,80%,100%)" | 1st singular ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 1st plural ! style="width:11em; background:rgb(80%,80%,100%)" | 1st plural ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd plural ! style="width:11em; background:rgb(80%,80%,100%)" | impersonal ! style="width:11em; background:rgb(80%,80%,100%)" | impersonal ! colspan=6 style="width:11em;" | Konditsionala ! colspan=3 style="width:11em;" | Preesens ! colspan=3 style="width:11em;" | Perfekta ! style="width:11em;" | ! style="width:11em; background:rgb(90%,90%,100%)" | positive ! style="width:11em; background:rgb(90%,90%,100%)" | negative ! style="width:11em;" | ! style="width:11em; background:rgb(90%,90%,100%)" | positive ! style="width:11em; background:rgb(90%,90%,100%)" | negative ! style="width:11em; background:rgb(80%,80%,100%)" | 1st singular ! style="width:11em; background:rgb(80%,80%,100%)" | 1st singular ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 1st plural ! style="width:11em; background:rgb(80%,80%,100%)" | 1st plural ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd plural ! style="width:11em; background:rgb(80%,80%,100%)" | impersonal ! style="width:11em; background:rgb(80%,80%,100%)" | impersonal ! colspan=6 style="width:11em;" | Imperativa ! colspan=3 style="width:11em;" | Preesens ! colspan=3 style="width:11em;" | Perfekta ! style="width:11em;" | ! style="width:11em; background:rgb(90%,90%,100%)" | positive ! style="width:11em; background:rgb(90%,90%,100%)" | negative ! style="width:11em;" | ! style="width:11em; background:rgb(90%,90%,100%)" | positive ! style="width:11em; background:rgb(90%,90%,100%)" | negative ! style="width:11em; background:rgb(80%,80%,100%)" | 1st singular ! style="width:11em; background:rgb(80%,80%,100%)" | 1st singular ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 1st plural ! style="width:11em; background:rgb(80%,80%,100%)" | 1st plural ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd plural ! style="width:11em; background:rgb(80%,80%,100%)" | impersonal ! style="width:11em; background:rgb(80%,80%,100%)" | impersonal ! colspan=6 style="width:11em;" | Potentsiala ! colspan=3 style="width:11em;" | Preesens ! colspan=3 style="width:11em;" | Perfekta ! style="width:11em;" | ! style="width:11em; background:rgb(90%,90%,100%)" | positive ! style="width:11em; background:rgb(90%,90%,100%)" | negative ! style="width:11em;" | ! style="width:11em; background:rgb(90%,90%,100%)" | positive ! style="width:11em; background:rgb(90%,90%,100%)" | negative ! style="width:11em; background:rgb(80%,80%,100%)" | 1st singular ! style="width:11em; background:rgb(80%,80%,100%)" | 1st singular ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd singular ! style="width:11em; background:rgb(80%,80%,100%)" | 1st plural ! style="width:11em; background:rgb(80%,80%,100%)" | 1st plural ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 2nd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd plural ! style="width:11em; background:rgb(80%,80%,100%)" | 3rd plural ! style="width:11em; background:rgb(80%,80%,100%)" | impersonal ! style="width:11em; background:rgb(80%,80%,100%)" | impersonal ! colspan=6 style="width:11em;" | Nominal forms ! colspan=3 style="width:11em;" | Infinitivat ! colspan=3 style="width:11em;" | Partisipat ! colspan=2 style="width:11em;" | ! style="width:11em; background:rgb(90%,90%,100%)" | ! style="width:11em;" | ! style="width:11em; background:rgb(90%,90%,100%)" | active ! style="width:11em; background:rgb(90%,90%,100%)" | passive ! colspan=2 style="width:11em; background:rgb(80%,80%,100%)" | 1st ! style="width:11em; background:rgb(80%,80%,100%)" | present ! rowspan=2 style="width:11em; background:rgb(80%,80%,100%)" | 2nd ! style="width:11em; background:rgb(90%,90%,100%)" | inessive ! style="width:11em; background:rgb(80%,80%,100%)" | past ! style="width:11em; background:rgb(90%,90%,100%)" | instructive ! rowspan=4 style="width:11em; background:rgb(80%,80%,100%)" | 3rd ! style="width:11em; background:rgb(90%,90%,100%)" | illative ! style="width:11em; background:rgb(90%,90%,100%)" | inessive ! style="width:11em; background:rgb(90%,90%,100%)" | elative ! style="width:11em; background:rgb(90%,90%,100%)" | abessive ! rowspan=4 style="width:11em; background:rgb(80%,80%,100%)" | 4th ! style="width:11em; background:rgb(90%,90%,100%)" | nominative ! style="width:11em; background:rgb(90%,90%,100%)" | partitive
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * en
 * en
 * oon
 * en oo
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * et
 * et
 * oot
 * et oo
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * ei
 * ei
 * ono
 * ei oo
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * emmä
 * emmä
 * oomma
 * emmä oo
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * että
 * että
 * ootta
 * että oo
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * evät
 * evät
 * ovat
 * evät oo
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * ei
 * ei
 * ono
 * ei oo
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * en
 * en
 * olin
 * en olt
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * et
 * et
 * olit
 * et olt
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * ei
 * ei
 * oli
 * ei olt
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * emmä
 * emmä
 * olimma
 * emmä olleet
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * että
 * että
 * olitta
 * että olleet
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * evät
 * evät
 * olivat
 * evät olleet
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * ei
 * ei
 * oli
 * ei olt
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * en
 * en
 * olisin
 * en olis
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * et
 * et
 * olisit
 * et olis
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * ei
 * ei
 * olis
 * ei olis
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * emmä
 * emmä
 * olisimma
 * emmä olis
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * että
 * että
 * olisitta
 * että olis
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * evät
 * evät
 * olisivat
 * evät olis
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * ei
 * ei
 * olis
 * ei olis
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * elä
 * elä
 * oo
 * elä oo
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * elköö
 * elköö
 * olkoo
 * elköö olko
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * elkää
 * elkää
 * olkaa
 * elkää olko
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * elkööt
 * elkööt
 * olkoot
 * elkööt olko
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * elköö
 * elköö
 * olkoo
 * elköö olko
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * en
 * en
 * leenen
 * en leene
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * et
 * et
 * leenet
 * et leene
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * ei
 * ei
 * leenöö
 * ei leene
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * emmä
 * emmä
 * leenemmä
 * emmä leene
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * että
 * että
 * leenettä
 * että leene
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * evät
 * evät
 * leenööt
 * evät leene
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * ei
 * ei
 * leenöö
 * ei leene
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * colspan=3 rowspan=7 style="font-size:smaller;" |
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;"
 * }]=]
 * }]=]

local function link(text) return require("Module:links").language_link{ term = text, lang = m_izh.lang } end

local function tag(text) return require("Module:script utilities").tag_text(text, m_izh.lang, nil, "term") end

local function mention(text) return require("Module:links").full_link({ term = text, lang = m_izh.lang }, "term") end

local function help_tooltip(text) return "" .. tostring(mw.html.create("span"):attr("style", "cursor:help"):attr("title", text):wikitext("?")) .. "" end

local function note_reference(note) if note then return "" .. note .. ")"	else		return ""	end end

local function link_and_note(form) if type(form) == "table" then return link(form.form) .. note_reference(form.note) else return link(form) end end

local function note_text(reference, text) return note_reference(reference) .. " " .. text end

-- extract notes from forms into a list and replace by their index local function format_notes_for_form(forms, form) local note = form.note if note then local index = forms.notes_reverse[note] if index then form.note = index else index = tostring(#forms.notes + 1) table.insert(forms.notes, note) forms.notes_reverse[note] = index form.note = index end end end

local function format_notes(forms) forms.notes = {} forms.notes_reverse = {} for k, v in pairs(forms) do		if type(v) == "table" then if v[1] then for _, form in ipairs(v) do					if type(form) == "table" then format_notes_for_form(forms, form) end end else format_notes_for_form(forms, v)			end end end forms.notes_reverse = nil end

function export.raw(word, infl_type, grad1, grad2, args) if not infl_type then error("inflection class not specified") end args = args or {}

local infl = inflections[infl_type] or error("unsupported inflection type") local geminate, vh	if args["g"] == "1" then geminate = true elseif args["g"] == "0" or args["g"] == "-" then geminate = false end if args["v"] then vh = args["v"] if vh ~= "a" and vh ~= "ä" then error("Invalid vowel harmony specification") end else vh = m_izh.guess_vowel_harmony(word) end

args[1] = args[1] or grad1 args[2] = args[2] or grad2 local data = { title = word, geminate = geminate, vh = vh, args = args } return infl(data) end

function export.show(frame) local infl_type = frame.args[1] or error("inflection class not specified") local infl = inflections[infl_type] or error("unsupported inflection type") local args = frame:getParent.args local title = args["title"] or mw.title.getCurrentTitle.text

local geminate, vh	if args["g"] == "1" then geminate = true elseif args["g"] == "0" or args["g"] == "-" then geminate = false end if args["v"] then vh = args["v"] if vh ~= "a" and vh ~= "ä" then error("Invalid vowel harmony specification") end else vh = m_izh.guess_vowel_harmony(title) end

local data = { title = title, geminate = geminate, vh = vh, args = args }

local forms = infl(data) format_notes(forms)

local function repl(form) if form == "title" then return "'''" .. title .. "'''"		elseif form == "type" then if forms.irregular then return "irregular" end local s = "type " .. forms.typeno .. "/" .. mention(infl_type) if forms.grade then s = s .. ", " .. forms.grade else s = s .. ", " .. make_gradation(nil, nil) end if forms.geminate then s = s .. ", gemination" end return s		elseif form == "notes" then local results = {} for index, note in ipairs(forms.notes) do				table.insert(results, note_text(tostring(index), note)) end table.insert(results, note_text("*", "For the imperative, the 2nd plural (" .. tag(forms.impr_2pl) .. ") may be used for the 3rd person as well.")) table.insert(results, note_text("**", "The interrogative is formed by adding the suffix (" .. help_tooltip("in back-vocalic stems, following the consonant -t") .. "/" .. help_tooltip("in front-vocalic stems, following the consonant -t") .. ") to the indicative, or  to the potential.")) return table.concat(results, " ") else local value = forms[form] if not value then return "&mdash;" elseif type(value) == "table" and value[1] then local result = {} for _, f in ipairs(value) do					table.insert(result, link_and_note(f)) end return table.concat(result, ", ") else return link_and_note(value) end end end

local result = mw.ustring.gsub(conj_table, "", repl) result = mw.ustring.gsub(result, "{{m|izh|([^}]-)}}", mention) return result end

return export