Module:vot-decl

local export = {} local m_vot = require("Module:vot")

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

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

local function get_e(vh) return (vh == "ä") and "e" or "õ" end

local function get_or(value, fallback) return (value and #value > 0) and value or fallback end

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

local function gsub_all(t, s, d)	if type(t) == "string" then return mw.ustring.gsub(t, s, d)	end local r = {} for _, v in ipairs(t) do		table.insert(r, mw.ustring.gsub(v, s, d)) 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 unreduce_full(t) local final = mw.ustring.sub(t, -1, -1) if final == "a" then return t .. "a" elseif final == "ä" then return t .. "ä" elseif final == "õ" then return mw.ustring.sub(t, 1, -2) .. "a" elseif final == "e" then return mw.ustring.sub(t, 1, -2) .. "ä" else return t	end end

local function unreduce(t) local final = mw.ustring.sub(t, -1, -1) if final == "õ" then return mw.ustring.sub(t, 1, -2) .. "a" elseif final == "e" then return mw.ustring.sub(t, 1, -2) .. "ä" else return t	end end

local function lengthen(t) if mw.ustring.find(t, m_vot.vowel .. "$") and not mw.ustring.find(t, m_vot.vowel .. m_vot.vowel .. "$") then return t .. mw.ustring.sub(t, -1) else return t	end end

local function make_gen_sg(data, x)	return (m_vot.guess_reduction(x, data.first_stressed) and lengthen(x) or x)	--return lengthen(x) end

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

local function unwind(data, word, grade, final, ending, may_have_gemination) local stem = (ending and #ending > 0) and get_stem(word, ending) or word local ci, stem = m_vot.extract_ci(stem) data.ci = ci

final = select(3, mw.ustring.find(stem, "(" .. final .. ")$")) if not final then final = "õ" end stem = get_stem(stem, grade .. final) if data.geminate ~= false and may_have_gemination then local repl stem, repl = mw.ustring.gsub(stem, grade .. "$", "") data.geminate = repl > 0 end return stem, final end

local function geminate(stem) local gem = m_vot.guess_gemination(stem) return gem and (gem .. mw.ustring.sub(stem, -1)) or stem end

local function geminate_surface(stem, final) local gem = m_vot.guess_gemination(stem) return gem and (gem .. final) or stem end

local function rewind(data, stem, grade, final, ending) local result if mw.ustring.find(grade, "k+$") then result = m_vot.apply_ci(data.ci, stem, grade, final) elseif grade == "vv" and (mw.ustring.find(stem, "[iaäeõoö][uü]$") or mw.ustring.find(stem, "[oö][oö]$")) then result = mw.ustring.sub(stem, 1, -2) .. grade .. (type(final) == "string" and final or "") else result = stem .. grade .. (type(final) == "string" and final or "") end return result .. (ending or "") end

local function rewind_long(data, stem, grade, final, ending) return geminate_surface(m_vot.apply_ci(data.ci, stem, grade, final), final) .. (ending or "") end

local function get_tuli_short_nom_sg(x) if not mw.ustring.find(x, "i$") then return nil end

local syl = m_vot.split_syllables(x) if #syl % 2 == 0 and not mw.ustring.find(syl[#syl - 1], m_vot.vowel .. ".") then return nil end

local form = mw.ustring.sub(x, 1, -2) if not mw.ustring.find(form, "[nrsz]$") then return nil end return form end

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

if data.geminate == false then return t end

if not mw.ustring.find(t, "(" .. m_vot.vowel .. ")%1$") then return t	end

local g = m_vot.guess_gemination(mw.ustring.sub(t, 1, -2)) if not g then return t end return g .. mw.ustring.sub(t, -2) end

local function cleanup_form(data, form) local form = mw.ustring.gsub(form, m_vot.virtual_syllable_break, "") form = m_vot.apply_reduction(form, data.infl_root_split, nil, data.first_stressed) return mw.ustring.gsub(form, m_vot.ungeminate, "") end

local function process(data) local vh = data.vh

-- nominative singular stem local ns = data.stem_ns -- genitive singular stem local gs = data.stem_gs -- partitive singular stem local ps = data.stem_ps -- illative singular stem local is = data.stem_is or ps	-- oblique singular stem local os = data.stem_os or gs	-- oblique plural stem local op = data.stem_op -- genitive plural stem local gp = data.stem_gp or op	-- partitive plural stem local pp = data.stem_pp or gp	local is_short = data.stem_is_short or is

local ill_sg = data.illative_sg or "long_short"

local result = { } data.infl_root_split = m_vot.split_syllables(data.infl_root)

if not data.no_singular then result["nom_sg"] = ns		result["gen_sg"] = gs		result["par_sg"] = append(ps, vh)

local short_ill = lengthen(do_geminate(data, is_short)) local long_ill = append(data.no_illative_sg_lengthen and is or lengthen(do_geminate(data, is)), frontalize("sõ", vh))

if ill_sg == "short" then result["ill_sg"] = short_ill elseif ill_sg == "long" then result["ill_sg"] = long_ill elseif ill_sg == "short_long" then result["ill_sg"] = join(short_ill, long_ill) elseif ill_sg == "long_short" then result["ill_sg"] = join(long_ill, short_ill) else error("unsupported ill_sg") end

result["ine_sg"] = append(os, "z") result["ela_sg"] = append(os, frontalize("ssa", vh)) result["all_sg"] = append(os, frontalize("lõõ", vh)) result["ade_sg"] = append(os, frontalize("lla", vh)) result["abl_sg"] = append(os, frontalize("lta", vh)) result["tra_sg"] = append(os, "ssi") end

if not data.no_plural then result["nom_pl"] = append(os, "d") result["gen_pl"] = join(append(gp, frontalize("õ", vh)), not data.no_short_pl and op or nil) result["par_pl"] = join(append(pp, vh), not data.no_short_pl and op or nil) result["ill_pl"] = append(op, frontalize("sõ", vh)) result["ine_pl"] = append(op, "z") result["ela_pl"] = append(op, frontalize("ssa", vh)) result["all_pl"] = append(op, frontalize("lõõ", vh)) result["ade_pl"] = append(op, frontalize("lla", vh)) result["abl_pl"] = append(op, frontalize("lta", vh)) result["tra_pl"] = append(op, "ssi") end

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

-- inflection classes begin local inflections = {}

inflections["maa"] = function (data) data.typeno = "I" local word = data.title if data.no_singular then -- plural title -> singular word = get_stem(word, "d") end local stem = word local final = mw.ustring.sub(word, -1, -1) local stem_pl = (mw.ustring.find(word, m_vot.vowel .. m_vot.vowel .. "$") and mw.ustring.gsub(word, m_vot.vowel .. "$", "") or word) .. "i"

data.stem_ns = stem data.stem_gs = stem data.stem_ps = stem .. "t" if mw.ustring.find(stem, final .. final .. "$") then local stem_ill = mw.ustring.sub(stem, 1, -2) data.stem_is = stem_ill .. "h" .. final data.stem_is_short = stem_ill .. "hh" .. final data.no_illative_sg_lengthen = true else data.stem_is = stem .. "h" .. final end

data.stem_op = stem_pl data.stem_gp = stem_pl .. "j" data.stem_pp = stem_pl .. "t"

data.illative_sg = "short_long"

data.infl_root = stem data.no_short_pl = true return process(data) end

inflections["võrkko"] = function (data) data.typeno = "II" 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, final if data.no_singular then -- plural title -> singular stem, final = unwind(data, word, weak, m_vot.vowel, "d") else stem, final = unwind(data, word, strong, m_vot.vowel) end

data.stem_ns = rewind(data, stem, strong, final) if mw.ustring.find(stem, final .. final .. "$") and weak == "" and strong ~= "" then data.stem_gs = stem else data.stem_gs = rewind(data, stem, weak, final) end data.stem_ps = rewind_long(data, stem, strong, final) data.stem_is = rewind_long(data, stem, strong, final) data.stem_os = data.stem_gs

local pl = m_vot.apply_ci(data.ci, stem, strong, final) data.stem_op = pl .. m_vot.ungeminate .. "i" data.stem_gp = pl .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "long_short"

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

inflections["jalkõ"] = function (data) data.typeno = "III" 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, final if data.no_singular then -- plural title -> singular stem, final = unwind(data, word, weak, m_vot.vowel, "d") else stem, final = unwind(data, word, strong, m_vot.vowel) end final = unreduce(final)

data.stem_ns = word data.stem_gs = make_gen_sg(data, rewind(data, stem, weak, final)) data.stem_ps = rewind_long(data, stem, strong, final) data.stem_is = rewind_long(data, stem, strong, final) data.stem_os = rewind(data, stem, weak, final)

local pl = rewind(data, stem, strong, frontalize("o", vh_plural)) data.stem_op = pl .. "i" data.stem_gp = pl .. "j" data.stem_pp = pl .. "it"

data.illative_sg = "long_short"

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

inflections["poikõ"] = function (data) data.typeno = "V" 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, final if data.no_singular then -- plural title -> singular stem, final = unwind(data, word, weak, m_vot.vowel, "d") else stem, final = unwind(data, word, strong, m_vot.vowel) end final = unreduce(final) local pl = rewind(data, stem, strong, vh == "ä") .. "i"

data.stem_ns = word data.stem_gs = make_gen_sg(data, rewind(data, stem, weak, final)) data.stem_ps = rewind_long(data, stem, strong, final) data.stem_is = rewind_long(data, stem, strong, final) data.stem_os = rewind(data, stem, weak, final)

data.stem_op = pl .. m_vot.ungeminate .. "i" data.stem_gp = pl .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "long_short"

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

inflections["valka"] = function (data) data.typeno = "VI" local word = data.title local vh = data.vh	if data.no_singular then -- plural title -> singular stem = get_stem(word, "d") end local stem = lengthen(word) local pl_stem = word local pl_stem_g = pl_stem if mw.ustring.find(word, "i[äa]$") then pl_stem = mw.ustring.gsub(word, "iä$", get_e(vh)) pl_stem_g = pl_stem .. "i" elseif mw.ustring.find(word, "õa$") then pl_stem = mw.ustring.gsub(word, "õa$", get_e(vh)) pl_stem_g = pl_stem .. "i" end

data.stem_ns = stem data.stem_gs = stem data.stem_ps = stem .. "t" data.stem_is = stem data.stem_os = stem

data.stem_op = pl_stem .. "i" data.stem_gp = unreduce_full(pl_stem_g) .. "j" data.stem_pp = pl_stem .. "it"

data.illative_sg = "long_short"

data.grade = make_gradation(strong, weak) data.infl_root = mw.ustring.gsub(word, m_vot.vowel .. "+$", "") return process(data) end

inflections["nimi"] = function (data) data.typeno = "VII" 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, final if data.no_singular then -- plural title -> singular stem, final = unwind(data, word, weak, m_vot.vowel, "d") else stem, final = unwind(data, word, strong, m_vot.vowel) end local e = get_e(vh) local pl = rewind(data, stem, strong, "i")

data.stem_ns = word data.stem_gs = rewind(data, stem, weak, e)	data.stem_ps = rewind_long(data, stem, strong, "i") data.stem_is = rewind_long(data, stem, strong, e)	data.stem_os = rewind(data, stem, weak, e)

data.stem_op = pl .. m_vot.ungeminate .. "i" data.stem_gp = pl .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "long_short"

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

inflections["uhsi"] = function (data) data.typeno = "VII" local word = data.title local strong = "s" local weak = "z" local vh = data.vh	local stem, final if data.no_singular then -- plural title -> singular stem, final = unwind(data, word, "h" .. weak, m_vot.vowel, "d") else stem, final = unwind(data, word, "h" .. strong, m_vot.vowel) end local e = get_e(vh) local pl = rewind(data, stem .. "h", strong, "i")

data.stem_ns = word data.stem_gs = rewind(data, stem .. "h", weak, e) data.stem_ps = stem .. strong .. strong data.stem_is = rewind_long(data, stem .. "h", strong, e) data.stem_os = rewind(data, stem .. "h", weak, e)

data.stem_op = pl .. m_vot.ungeminate .. "i" data.stem_gp = pl .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "long_short"

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

inflections["päive"] = function (data) data.typeno = "VIII" 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, final if data.no_singular then -- plural title -> singular stem, final = unwind(data, word, weak, m_vot.vowel, "d") else stem, final = unwind(data, word, strong, m_vot.vowel) end final = get_or(data.args[3], unreduce(final) or final) local pl = rewind(data, stem, strong, vh == "ä") .. "i"

data.stem_ns = word data.stem_gs = make_gen_sg(data, rewind(data, stem, weak, final)) data.stem_ps = rewind_long(data, stem, strong, final) data.stem_is = rewind_long(data, stem, strong, final) data.stem_os = rewind(data, stem, weak, final)

data.stem_op = pl .. m_vot.ungeminate .. "i" data.stem_gp = pl .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "long_short"

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

inflections["parõpi"] = function (data) data.typeno = "VIII" local word = data.title local vh = data.vh	local stem if data.no_singular then -- plural title -> singular stem = get_stem(word, "[" .. vh .. get_e(vh) .. "]d") else stem = get_stem(word, "i") end local pl = stem .. "i"

data.stem_ns = word data.stem_gs = stem .. vh .. vh data.stem_ps = stem .. vh data.stem_is = stem .. vh data.stem_os = stem .. vh

data.stem_op = pl .. m_vot.ungeminate .. "i" data.stem_gp = pl .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "long_short"

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

local LENGTHEN = mw.ustring.char(0xEEF0)

local tuli_weak = { ["lt"] = "ll", ["rt"] = "rr", ["nt"] = "nn", ["l"] = "l", ["m"] = "m", ["n"] = "n", ["r"] = "r", ["s"] = "z", ["hs"] = "hz", ["ht"] = "h", ["t"] = "d", ["h"] = "h" }

local tuli_partitive = { ["lt"] = "ltt", ["rt"] = "rtt", ["m"] = "nt", ["s"] = "ss", ["hs"] = "ss", ["nt"] = "ntt" }

local tuli_plural = { ["lt"] = "ls", ["rt"] = "rs", ["t"] = "s", ["ht"] = "hz", ["nt"] = LENGTHEN .. "s" }

local function clean_lengthen(x) return mw.ustring.gsub(x, "(" .. m_vot.vowel .. "?)" .. LENGTHEN, "%1%1") end

inflections["tuli"] = function (data) data.typeno = "X" local word = data.title local vh = data.vh	local strong = data.args[1] or error("must specify final consonant") local weak = tuli_weak[strong] or error("unrecognized final consonant") local partitive = tuli_partitive[strong] or (strong .. "t") local plural = tuli_plural[strong] or strong local e = get_e(vh) local stem local has_i = true if data.no_singular then -- plural title -> singular stem = unwind(data, word, weak, e, "d") elseif not mw.ustring.find(word, "i$") then has_i = false stem = get_stem(word, mw.ustring.gsub(plural, LENGTHEN, "[" .. m_vot.vowels .. "n]")) else stem = unwind(data, word, mw.ustring.gsub(plural, LENGTHEN, "[" .. m_vot.vowels .. "n]"), "i") end local stemw = nil if weak == "d" then if mw.ustring.find(stem, m_vot.vowel .. "i$") then weak = "jj" elseif mw.ustring.find(stem, m_vot.vowel .. "[oöuü]$") then weak = "vv" else weak = "" end end

if has_i then local short = get_tuli_short_nom_sg(word) data.stem_ns = (short and { word, short } or word) else data.stem_ns = { word, word .. "i" } end

local pl = clean_lengthen(stem .. plural .. "i") data.stem_gs = join(stemw and rewind(data, stemw, weak, e) or {}, rewind(data, stem, weak, e)) data.stem_ps = stem .. partitive data.stem_is = rewind_long(data, stem, strong, e)	data.stem_os = join(stemw and rewind(data, stemw, weak, e) or {}, rewind(data, stem, weak, e))

data.stem_op = pl .. m_vot.ungeminate .. "i" data.stem_gp = pl .. "j" data.stem_pp = data.stem_op .. "t"

if mw.ustring.match(partitive, "^t+$") then data.stem_ps = mw.ustring.gsub(data.stem_ps, "(" .. m_vot.consonant .. "t)t$", "%1") end

data.illative_sg = "short_long"

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

inflections["jänez"] = function (data) data.typeno = "XI" local word = data.title local vh = data.vh	local e = get_e(vh) local stem if data.no_singular then -- plural title -> singular stem = get_stem(word, "s" .. e .. "d") else stem = get_stem(word, "z") end local pl = stem .. "ssi"

data.stem_ns = word data.stem_gs = stem .. "s" .. e	data.stem_ps = stem .. "ss" data.stem_is = stem .. "ss" .. e	data.stem_os = data.stem_gs

data.stem_op = pl .. m_vot.ungeminate .. "i" data.stem_gp = pl .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "long"

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

inflections["sinin"] = function (data) data.typeno = "XII" local word = data.title local strong = data.args[1] or "" local weak = data.args[2] or "" local vh = data.vh	local e = get_e(vh) local stem, final if data.no_singular then -- plural title -> singular stem, final = unwind(data, word, strong, m_vot.vowel, "z" .. e .. "d") else stem, final = unwind(data, word, strong, m_vot.vowel, "n") end local pl = m_vot.apply_ci(data.ci, stem, strong, final) .. "si" .. m_vot.ungeminate .. "i"

data.stem_ns = word data.stem_gs = m_vot.apply_ci(data.ci, stem, strong, final) .. "z" .. e	data.stem_ps = m_vot.apply_ci(data.ci, stem, weak, final) .. "ss" data.stem_is = geminate(m_vot.apply_ci(data.ci, stem, strong, final) .. "s" .. e)	data.stem_os = data.stem_gs

data.stem_op = pl data.stem_gp = pl .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "short_long"

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

inflections["seeme"] = function (data) data.typeno = "XIII" local word = data.title local weak = data.args[1] or error("must specify weak grade") local strong = data.args[2] or error("must specify strong grade") local vh = data.vh	local e = get_e(vh) local v1, c1, v2	if data.no_singular then -- plural title -> singular word = get_stem(word, "d") v2 = data.args[5] or mw.ustring.sub(word, -1, -1) c1 = data.args[4] or mw.ustring.sub(word, -2, -2) v1 = data.args[3] or mw.ustring.sub(word, -3, -3) if not mw.ustring.match(v1, m_vot.vowel) then error("unexpected sound for type 11") end if not mw.ustring.match(c1, m_vot.consonant) then error("unexpected sound for type 11") end if not mw.ustring.match(v2, m_vot.vowel) then error("unexpected sound for type 11") end word = get_stem(mw.ustring.sub(word, 1, -4), strong) .. weak .. v1	else v1 = data.args[3] or error("must specify penultimate stem vowel") c1 = data.args[4] or error("must specify final stem consonant") v2 = data.args[5] or error("must specify final stem vowel") end local stem if mw.ustring.find(word, c1 .. "$") then stem = mw.ustring.sub(word, 1, -2) elseif mw.ustring.find(word, "[" .. v1 .. e .. "][" .. v1 .. "]$") then stem = mw.ustring.sub(word, 1, -2) else stem = word end local stem = unwind(data, stem, weak, "[" .. v1 .. "eõ]", nil, true) local pl = rewind(data, stem, strong, v1) .. c1 .. "i" data.ci = true

data.stem_ns = word data.stem_gs = rewind(data, stem, strong, v1) .. c1 .. v2 data.stem_ps = rewind(data, stem, weak, v1) .. (mw.ustring.match(c1, "[mn]") and "tt" or c1 .. "t") data.stem_is = geminate(rewind(data, stem, strong, v1).. c1 .. v2) data.stem_os = data.stem_gs

data.stem_op = pl .. m_vot.ungeminate .. "i" data.stem_gp = pl .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "short_long"

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

inflections["tšümme"] = function (data) data.typeno = "XIII" local word = data.title local weak = data.args[1] or error("must specify weak grade") local strong = data.args[2] or error("must specify strong grade") local vh = data.vh	local v1, c1, v2	if data.no_singular then -- plural title -> singular word = get_stem(word, "d") v2 = data.args[5] or mw.ustring.sub(word, -1, -1) c1 = data.args[4] or mw.ustring.sub(word, -2, -2) v1 = data.args[3] or mw.ustring.sub(word, -3, -3) if not mw.ustring.match(v1, m_vot.vowel) then error("unexpected sound for type 11") end if not mw.ustring.match(c1, m_vot.consonant) then error("unexpected sound for type 11") end if not mw.ustring.match(v2, m_vot.vowel) then error("unexpected sound for type 11") end word = get_stem(mw.ustring.sub(word, 1, -4), strong) .. weak .. v1	else v1 = data.args[3] or error("must specify penultimate stem vowel") c1 = data.args[4] or error("must specify final stem consonant") v2 = data.args[5] or error("must specify final stem vowel") end local stem = get_stem(word, weak .. "[" .. v1 .. "eõ][" .. v1 .. c1 .. "]?") local pl = stem .. strong .. v1 .. c1 .. "i" data.ci = true

data.stem_ns = word data.stem_gs = stem .. strong .. v1 .. c1 .. v2 data.stem_ps = rewind(data, stem, weak, v1) .. c1 .. vh data.stem_is = geminate(stem .. strong .. v1 .. c1 .. v2) data.stem_os = data.stem_gs

data.stem_op = pl .. m_vot.ungeminate .. "i" data.stem_gp = pl .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "short_long"

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

inflections["seittse"] = function (data) data.typeno = "XIII" local word = data.title local weak = data.args[1] or error("must specify weak grade") local strong = data.args[2] or error("must specify strong grade") local vh = data.vh	local v1, c1, v2	if data.no_singular then -- plural title -> singular word = get_stem(word, "d") v2 = data.args[5] or mw.ustring.sub(word, -1, -1) c1 = data.args[4] or mw.ustring.sub(word, -2, -2) v1 = data.args[3] or mw.ustring.sub(word, -3, -3) if not mw.ustring.match(v1, m_vot.vowel) then error("unexpected sound for type 11") end if not mw.ustring.match(c1, m_vot.consonant) then error("unexpected sound for type 11") end if not mw.ustring.match(v2, m_vot.vowel) then error("unexpected sound for type 11") end word = get_stem(mw.ustring.sub(word, 1, -4), strong) .. weak .. v1	else v1 = data.args[3] or error("must specify penultimate stem vowel") c1 = data.args[4] or error("must specify final stem vowel") v2 = data.args[5] or error("must specify final stem consonant") end local stem = get_stem(word, weak .. m_vot.vowel) local pl = stem .. strong .. v1 .. c1 .. "i" data.ci = true

data.stem_ns = lengthen(word) data.stem_gs = stem .. strong .. v1 .. c1 .. v2 data.stem_ps = geminate(rewind(data, stem, strong, v1) .. c1 .. vh) data.stem_is = geminate(stem .. strong .. v1 .. c1 .. v2) data.stem_os = data.stem_gs

data.stem_op = stem .. strong .. v1 .. c1 .. "i" data.stem_gp = pl .. "j" data.stem_pp = pl .. "t"

data.illative_sg = "short_long"

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

inflections["kõlmõz"] = function (data) data.typeno = "XIII" local word = data.title local vh = data.vh	if data.no_singular then -- plural title -> singular error("Plural-only not supported for type kolmaz") end local stem = get_stem(word, "z") local v1 = mw.ustring.sub(stem, -1) local c1 = "m" local v2 = data.args[1] or error("must specify final stem vowel") local pl = stem .. "tt" .. v1 .. c1 .. "i"

data.stem_ns = word data.stem_gs = stem .. "tt" .. v1 .. c1 .. v2 data.stem_ps = stem .. "tt" data.stem_is = geminate(stem .. "tt" .. v1 .. c1 .. v2) data.stem_os = stem .. "tt" .. v1 .. c1 .. v2

data.stem_op = pl .. m_vot.ungeminate .. "i" data.stem_gp = pl .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "short_long"

data.infl_root = stem return process(data) end

inflections["ammõz"] = function (data) data.typeno = "XIV" local word = data.title local weak = data.args[1] or error("must specify weak grade") local strong = data.args[2] or error("must specify strong grade") local vh = data.vh	local final if data.no_singular then -- plural title -> singular word = get_stem(word, "d") final = mw.ustring.sub(word, -1, -1) word = get_stem(mw.ustring.sub(word, 1, -2), strong) .. weak .. final .. "z" else final = mw.ustring.sub(word, -2, -2) end local stem = get_stem(word, weak .. final .. "z") final = get_or(data.args[3], unreduce(final)) local h = false if final == "e" and mw.ustring.find(stem, "e$") then stem = stem .. "h" h = true end local pl = h and stem .. strong .. "i" or geminate(stem .. strong .. final)

local stem_nom if mw.ustring.match(mw.ustring.sub(word, 1, -3), "[uü]$") and mw.ustring.match(final, "[eõ]") then stem_nom = mw.ustring.sub(word, 1, -3) .. "i" else stem_nom = mw.ustring.sub(word, 1, -3) .. final end

data.stem_ns = stem_nom .. "z" data.stem_gs = h and stem .. strong .. final or geminate(stem .. strong .. final) .. final data.stem_ps = stem_nom .. "ss" data.stem_is = geminate(stem .. strong .. final) data.stem_os = h and stem .. strong .. final or lengthen(data.stem_is)

data.stem_op = pl .. (not h and final == "i" and m_vot.ungeminate or "") .. "i" data.stem_gp = unreduce_full(pl) .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "long_short"

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

inflections["terve"] = function (data) data.typeno = "XIV" local word = data.title local weak = data.args[1] or error("must specify weak grade") local strong = data.args[2] or error("must specify strong grade") local vh = data.vh	local e = get_e(vh) local v1, c1, v2	local stem if data.no_singular then -- plural title -> singular stem = get_stem(word, strong .. e .. "d") else stem = get_stem(word, weak .. e)	end

data.stem_ns = word data.stem_gs = geminate(stem .. strong .. e) .. e	data.stem_ps = stem .. weak .. e .. "tt" data.stem_is = geminate(stem .. strong .. e)	data.stem_os = data.stem_gs

data.stem_op = geminate(stem .. strong .. e) .. "i" data.stem_gp = geminate(stem .. strong .. e) .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "long_short"

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

inflections["lühüd"] = function (data) data.typeno = "XV" local word = data.title local vh = data.vh	local stem if data.no_singular then -- plural title -> singular stem = get_stem(word, "d") elseif mw.ustring.find(word, "[dz]$") then stem = mw.ustring.sub(word, 1, -2) else stem = word end local e = get_e(vh) local final = mw.ustring.sub(stem, -1, -1) stem = get_stem(stem, m_vot.vowel) local final2 = data.args[1] or error("Must specify final stem vowel")

data.stem_ns = word data.stem_gs = make_gen_sg(data, geminate(stem .. final2)) data.stem_ps = stem .. final .. "tt" data.stem_is = geminate(stem .. final2) data.stem_os = data.stem_gs

data.stem_op = geminate(stem .. final) .. "i" data.stem_gp = data.stem_op .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "long"

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

inflections["kõrkuz"] = function (data) data.typeno = "XV" local word = data.title local vh = data.vh	local stem if data.no_singular then -- plural title -> singular stem = get_stem(word, "d") elseif mw.ustring.find(word, "[dz]$") then stem = mw.ustring.sub(word, 1, -2) else stem = word end local e = get_e(vh) local final = mw.ustring.sub(stem, -1, -1) stem = get_stem(stem, "[uü]")

data.stem_ns = word data.stem_gs = geminate(stem .. final) data.stem_ps = stem .. final .. "tt" data.stem_is = geminate(stem .. final) data.stem_os = data.stem_gs

data.stem_op = geminate(stem .. final) .. "i" data.stem_gp = data.stem_op .. "j" data.stem_pp = data.stem_op .. "t"

data.illative_sg = "long"

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

-- inflection classes end

local infl_table = [=[{| class="inflection-table vsSwitcher" data-toggle-category="declension" style="border:1px solid #CCCCFF" !colspan=3 class="vsToggleElement" style="background:rgb(80%,80%,100%);text-align:left;"|Declension of ! style="width:11em;" | ! style="width:12em;" | singular ! style="width:12em;" | plural ! style="background:rgb(80%,80%,100%);width:11em" | nominative ! style="background:rgb(80%,80%,100%);" | genitive ! style="background:rgb(80%,80%,100%);" | partitive ! style="background:rgb(80%,80%,100%);" | illative ! style="background:rgb(80%,80%,100%);" | inessive ! style="background:rgb(80%,80%,100%);" | elative ! style="background:rgb(80%,80%,100%);" | allative ! style="background:rgb(80%,80%,100%);" | adessive ! style="background:rgb(80%,80%,100%);" | ablative ! style="background:rgb(80%,80%,100%);" | translative
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - style="background:rgb(95%,95%,100%);vertical-align:top;" |
 * style="width:12em" |
 * style="width:12em" |
 * - style="background:rgb(95%,95%,100%);vertical-align:top;" |
 * - style="background:rgb(95%,95%,100%);vertical-align:top;" |
 * - style="background:rgb(95%,95%,100%);vertical-align:top;" |
 * - style="background:rgb(95%,95%,100%);vertical-align:top;" |
 * - style="background:rgb(95%,95%,100%);vertical-align:top;" |
 * - style="background:rgb(95%,95%,100%);vertical-align:top;" |
 * - 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;" |
 * - 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;" |
 * colspan="3" style="background:rgb(80%,80%,100%);font-size:smaller" | *) the accusative corresponds with either the genitive ( sg ) or nominative ( pl )
 * ) the terminative is formed by adding the suffix to the genitive.
 * ) the comitative is formed by adding the suffix to the genitive.
 * }]=]
 * ) the comitative is formed by adding the suffix to the genitive.
 * }]=]

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

local function mention(text) return require("Module:links").full_link({ term = text, lang = m_vot.lang }, "term") 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 categories = {}

local geminate, vh, headword if args["g"] == "1" then geminate = true elseif args["g"] == "0" or args["g"] == "-" then geminate = false else headword = args["g"] end

local prefix = args["prefix"]

local original_title = title if prefix then local prefix_len = mw.ustring.len(prefix) local split split, title = mw.ustring.sub(title, 1, prefix_len), mw.ustring.sub(title, prefix_len + 1) if #title == 0 or prefix ~= split then error("Prefix is too long or does not match title") end end if args["v"] then vh = args["v"] if vh ~= "a" and vh ~= "ä" then error("Invalid vowel harmony specification") end elseif not vh then vh = m_vot.guess_vowel_harmony(headword or title) end

local first_stressed = args["s"] and tonumber(args["s"]) or 1 local data = { title = title, headword = headword, geminate = geminate, prefix = prefix, vh = vh, args = args, first_stressed = first_stressed } local word_prefix = prefix or ""

if args["n"] then if args["n"] == "s" or args["n"] == "sg" then data.no_plural = true elseif args["n"] == "p" or args["n"] == "pl" then data.no_singular = true end end

local forms = infl(data)

local function repl(form) if form == "title" then return "'''" .. original_title .. "'''"		elseif form == "type" then if data.irregular then return "irregular" end local s = "type " .. data.typeno .. "/" .. mention(infl_type) if data.grade then s = s .. ", " .. data.grade else s = s .. ", " .. make_gradation(nil, nil) end if data.geminate then s = s .. ", gemination" end return s		elseif form == "has_short_ill" then if data.illative_sg == "long" or data.no_singular then return "" elseif data.illative_sg == "short" then return "the illative (sg ) or " else return "the short illative (sg ) or " end else local value = forms[form] if not value then return "&mdash;" elseif type(value) == "table" then local result = {} for _, f in ipairs(value) do table.insert(result, link(word_prefix .. f)) end return table.concat(result, ", ") else return link(word_prefix .. value) end end end

if mw.title.getCurrentTitle.namespace == 0 then table.insert(categories, "Votic " .. infl_type .. "-type nominals") end

local result = mw.ustring.gsub(infl_table, "", repl) result = mw.ustring.gsub(result, "{{m|vot|([^}]-)}}", mention) return result .. require("Module:utilities").format_categories(categories, m_vot.lang) end

return export