Module:izh-decl-S

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 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 frontalize(w, vh) if vh == "ä" then w = mw.ustring.gsub(w, "[aou]", { a = "ä", o = "ö", u = "y" }) end return w 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({...}) 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 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 get_geminated(data, w, fallback) if data.geminate == false then return fallback end if data.headword then local gemprefix = mw.ustring.len(data.title) - mw.ustring.len(data.headword) if gemprefix > 0 then local wp = mw.ustring.sub(w, 1, gemprefix) local wg = m_izh.guess_gemination(mw.ustring.sub(w, gemprefix + 1)) if not wg then return fallback end return wp .. wg		end end return m_izh.guess_gemination(w) or fallback end

local function get_elongation(data, w)	if data.elongate == false then return false end if data.headword then local gemprefix = mw.ustring.len(data.title) - mw.ustring.len(data.headword) if gemprefix > 0 then return m_izh.guess_elongation(mw.ustring.sub(w, gemprefix + 1)) end end return m_izh.guess_elongation(w) end

local function process(data, result, vh) local vh = data.vh	-- genitive singular/plural stem local gs = result.stem_gs local gp = result.stem_gp -- nominative plural stem local np = result.stem_np or gs	-- partitive singular/plural stem local ps = result.stem_ps local pp = result.stem_pp -- illative singular/plural stem local is = result.stem_is local ip = result.stem_ip -- allative singular/plural stem local as = result.stem_as or gs	local ap = result.stem_ap or pp	-- adessive singular/plural stem local es = result.stem_es or as	local ep = result.stem_ep or ap	-- essive singular/plural stem local xs = result.stem_xs or is	local xp = result.stem_xp or ip

if not data.no_singular then result["nom_sg"] = { data.title } result["gen_sg"] = append(gs, "n") result["par_sg"] = append(ps, vh) if result.par_short_ok then result["par_sg"] = join(result["par_sg"], ps) end if result.ill_short or result.ill_short_sg then result["ill_sg"] = append(is, result.ill_ending or result.ill_ending_sg or nil) else result["ill_sg"] = append(elongate_all(is), result.ill_ending or result.ill_ending_sg or nil) end result["ine_sg"] = append(es, "s") result["ela_sg"] = append(es, "st") result["all_sg"] = append(as, "lle") result["ade_sg"] = append(es, "l") result["abl_sg"] = append(es, "lt") result["tra_sg"] = append(es, "ks") result["ess_sg"] = append(xs, "n") result["exe_sg"] = append(xs, "nt") end

if not data.no_plural then result["nom_pl"] = append(np, "t") result["gen_pl"] = append(gp, "n") result["par_pl"] = append(pp, vh) if result.ill_short then result["ill_pl"] = append(ip, result.ill_ending or result.ill_ending_pl or nil) else result["ill_pl"] = append(elongate_all(ip), result.ill_ending or result.ill_ending_pl or nil) end result["ine_pl"] = append(ep, "s") result["ela_pl"] = append(ep, "st") result["all_pl"] = append(ap, "lle") result["ade_pl"] = append(ep, "l") result["abl_pl"] = append(ep, "lt") result["tra_pl"] = append(ep, "ks") result["ess_pl"] = append(xp, "n") result["exe_pl"] = append(xp, "nt") end

return result end

local function guess_illative_weight(stem) local syllables = m_izh.split_syllables(stem) return #syllables % 2 == 1 and mw.ustring.find(stem, m_izh.vowel .. m_izh.vowel .. "$") and mw.ustring.sub(stem, -2, -2) ~= mw.ustring.sub(stem, -1, -1) end

local function generate_hv_illative_forms(result, data, stems, weights, ending, short) local outputs = {}

for i, stem in ipairs(stems) do		local weight = weights[i]

if not short then stem = elongate(stem) end

if weight == nil then local guess = stem if data.headword then guess = mw.ustring.sub(guess, 1 + mw.ustring.len(data.title) - mw.ustring.len(data.headword)) end weight = guess_illative_weight(guess) end

if weight then table.insert(outputs, stem .. ending) else table.insert(outputs, stem) end end

return outputs end

-- -hV illative ending is only sometimes evident local function generate_hv_illative(result, data, stem_s, weight_s, stem_p, weight_p) if not data.no_singular and stem_s then result["ill_sg"] = generate_hv_illative_forms(result, data, stem_s, weight_s, result.ill_ending_sg or result.ill_ending or "", result.ill_short_sg or result.ill_short) end

if not data.no_plural and stem_p then result["ill_pl"] = generate_hv_illative_forms(result, data, stem_p, weight_p, result.ill_ending_pl or result.ill_ending or "", result.ill_short) end

return result end

-- inflection classes begin local inflections = {}

inflections["kärpäin"] = 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") if data.no_singular then word = get_stem(word, "iset") .. "in" end local final = mw.ustring.sub(word, -3, -3) local stem if mw.ustring.sub(word, -5, -5) == strong then stem = get_stem(word, strong .. strong .. final .. "in") else stem = get_stem(word, strong .. final .. "in") end local gem = get_stem(word, final .. "in")

result.stem_gs = gem .. final .. "ise" result.stem_ps = stem .. weak .. final .. "ist" result.stem_is = stem .. strong .. final .. "ise" result.stem_es = stem .. strong .. final .. "isee" result.stem_xs = stem .. strong .. final .. "isee" result.stem_np = { gem .. final .. "ise", gem .. final .. "is" } result.stem_gp = stem .. strong .. final .. "isii" result.stem_pp = stem .. strong .. final .. "isi" result.stem_ip = stem .. strong .. final .. "isi" result.stem_ep = stem .. strong .. final .. "isii" result.stem_xp = stem .. strong .. final .. "isii" result.par_short_ok = true result.grade = make_gradation(strong, weak) result.geminate = gem ~= stem .. strong

return process(data, result) end

inflections["kolmas"] = function (data) local result = { typeno = "2" } local word = data.title if data.no_singular then -- plural title -> singular word = get_stem(word, "nnet") .. "s" end local stem = get_stem(word, "s")

result.stem_gs = stem .. "nne" result.stem_ps = stem .. "tt" result.stem_is = stem .. "nte" result.stem_es = stem .. "nnee" result.stem_xs = stem .. "ntee"

result.stem_np = stem .. "nne" result.stem_gp = stem .. "nsii" result.stem_pp = stem .. "nsi" result.stem_ip = stem .. "nsi" result.stem_ep = stem .. "nsii" result.stem_xp = stem .. "nsii" return process(data, result) 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="width:35.5em; background:rgb(80%,80%,100%);text-align:left;"|Soikkola 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 ! style="background:rgb(80%,80%,100%);" | essive ! style="background:rgb(80%,80%,100%);" | exessive1)
 * - class="vsHide" style="background:rgb(80%,80%,100%);vertical-align:top;"
 * - class="vsHide" style="background:rgb(95%,95%,100%);vertical-align:top;" |
 * style="width:12em" |
 * style="width:12em" |
 * - 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;" |
 * - 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" | 1) obsolete
 * ) the accusative corresponds with either the genitive ( sg ) or nominative ( pl )
 * }]=]
 * ) the accusative corresponds with either the genitive ( sg ) or nominative ( pl )
 * }]=]

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

local function mention(text) return require("Module:links").full_link({ term = text, lang = m_izh.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 geminate, elongate, vh, headword if args["g"] == "1" then geminate = true elseif args["g"] == "0" or args["g"] == "-" then geminate = false else headword = args["g"] vh = m_izh.guess_vowel_harmony(headword or title) end if args["e"] == "1" then elongate = true elseif args["e"] == "0" or args["e"] == "-" then elongate = false else elongate = nil 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_izh.guess_vowel_harmony(title) end

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

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 "'''" .. 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		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(f)) end return table.concat(result, ", ") else return link(value) end end end

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

return export