Module:fi-verbs

local export = {}

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

-- Functions that do the actual inflecting by creating the forms of a basic term. local inflections = {}

local kotus_grad_type = { ["kk-k"] = "A", ["pp-p"] = "B", ["tt-t"] = "C", ["k-"] = "D", ["p-v"] = "E", ["t-d"] = "F", ["nk-ng"] = "G", ["mp-mm"] = "H", ["lt-ll"] = "I", ["nt-nn"] = "J", ["rt-rr"] = "K", ["k-j"] = "L", ["k-v"] = "M" }

local function tag_term(term) -- return require("Module:script utilities").tag_text(term, lang, nil, "term") return '' .. term .. '' end

local function normalize_apostrophes(term, link_target) if link_target then if term and mw.ustring.find(term, "’") then term = mw.ustring.gsub(term, "’", "'") end else if term and mw.ustring.find(term, "'") then term = mw.ustring.gsub(term, "'", "’") end end return term end

-- Creates a link to a form. local function make_link(term, accel_form) -- do not link inflected forms of suffixes if term:match("^-") or term:find("%[%[%-") then term = mw.ustring.gsub(term, "[%[%]]", "")

if target == mw.title.getCurrentTitle.fullText then return ' ' .. term .. ' '		end

return ' ' .. term .. ' '	end -- if there is something difficult, use full module. if term:find(":") or term:find("<") or (accel_form and term:find("%[")) then if term:find(":") then term = mw.ustring.gsub(term, ":", "\\:") end return require("Module:links").full_link({			lang = lang,			term = term,			accel = accel_form and ({ form = accel_form }) or nil		}) end -- otherwise, we can save a ton of memory by doing this manually. local target = normalize_apostrophes(term, true) if target == mw.title.getCurrentTitle.fullText then return ' ' .. term .. ' '	end if term:find("%[") then return ' ' .. term .. ' '	end if not accel_form then return ' ' .. term .. ' ' end return '' .. term .. ' ' end

-- The main entry point. -- This is the only function that can be invoked from a template. function export.show(frame) local infl_type = frame.args[1] or error("Inflection type has not been specified. Please pass parameter 1 to the module invocation") local args = frame:getParent.args if not inflections[infl_type] then error("Unknown inflection type '" .. infl_type .. "'") end local data = { forms = {}, title = nil, categories = {}, vh = nil, pagename = mw.title.getCurrentTitle.text }

if args["title"] and mw.title.getCurrentTitle.namespace > 0 then data.pagename = args.title end data.pagename = normalize_apostrophes(data.pagename) -- Generate the forms inflections[infl_type](args, data) -- Postprocess postprocess(args, data) if args["appendix"] then table.insert(data.categories, "fi-conj with appendix") end if args["noagent"] then table.insert(data.categories, "fi-conj with noagent") end if args["qual"] or		args["q1sg"] or args["q2sg"] or args["q1pl"] or args["q2pl"] or args["q3p"] or args["qpass"] or		args["q1sgp"] or args["q2sgp"] or args["q1plp"] or args["q2plp"] or args["q3pp"] or args["qpassp"] or args["q4i"] then table.insert(data.categories, "fi-conj with qual") end

local categories if args["appendix"] then categories = "" else categories = require("Module:utilities").format_categories(data.categories, lang) end return make_table(data) .. categories end

local function args_get_required(args, i, purpose) local v = args[i] if not v then error(purpose .. " (parameter " .. i .. ") may not be omitted.") end return v end

local function args_get_vowel_harmony(args, i)	local v = args[i] if not v or not mw.ustring.match(v, "^[aä]$") then error("Vowel harmony (parameter " .. i .. ") must be \"a\" or \"ä\".") end return v end

-- Get parameters from the template, in standard order and numbering local function get_params(args, num, invert_grades) local params = {}

params.base = normalize_apostrophes(args[1]) if num >= 2 then if num >= 4 then params.strong = normalize_apostrophes(args_get_required(args, 2, "Infinitive grade")) params.weak = normalize_apostrophes(args_get_required(args, 3, "Other grade")) -- Swap the grades if invert_grades then params.strong, params.weak = params.weak, params.strong end end

if num >= 5 then params.final = args_get_required(args, 4, "Final letter(s)") end

params.a = args_get_vowel_harmony(args, num) end if params.a then params.o = params.a == "ä" and "ö" or "o" params.u = params.a == "ä" and "y" or "u" end return params end

--[=[	Inflection functions ]=]--

local stem_endings = {}

stem_endings["inf1"] = { ["inf1"] = "a", ["inf1_long"] = "akse¤", }

stem_endings["inf2"] = { ["inf2_ine"] = "essa¤", ["inf2_ins"] = "en", }

stem_endings["pres"] = { ["pres_3sg"] = "V", ["pres_3pl"] = "vat", ["inf3_ine"] = "massa", ["inf3_ela"] = "masta", ["inf3_ill"] = "maan", ["inf3_ade"] = "malla", ["inf3_abe"] = "matta", ["inf3_ins"] = "man", ["inf4"] = "minen", ["inf5"] = "maisilla¤", ["pres_part"] = "va", ["agnt_part"] = "ma", ["nega_part"] = "maton", }

stem_endings["pres_weak"] = { ["pres_1sg"] = "n", ["pres_2sg"] = "t", ["pres_1pl"] = "mme", ["pres_2pl"] = "tte", ["pres_conn"] = "", ["impr_2sg"] = "", }

stem_endings["past"] = { ["past_3sg"] = "", ["past_3pl"] = "vat", }

stem_endings["past_weak"] = { ["past_1sg"] = "n", ["past_2sg"] = "t", ["past_1pl"] = "mme", ["past_2pl"] = "tte", }

stem_endings["cond"] = { ["cond_1sg"] = "sin", ["cond_2sg"] = "sit", ["cond_3sg"] = "si", ["cond_1pl"] = "simme", ["cond_2pl"] = "sitte", ["cond_3pl"] = "sivat", ["cond_conn"] = "si", }

stem_endings["impr"] = { ["impr_3sg"] = "oon", ["impr_1pl"] = "aamme", ["impr_2pl"] = "aa", ["impr_3pl"] = "oot", ["impr_conn"] = "o", }

stem_endings["potn"] = { ["potn_1sg"] = "en", ["potn_2sg"] = "et", ["potn_3sg"] = "ee", ["potn_1pl"] = "emme", ["potn_2pl"] = "ette", ["potn_3pl"] = "evat", ["potn_conn"] = "e", ["past_part"] = "ut", ["past_part_pl"] = "eet", }

stem_endings["pres_pasv"] = { ["pres_pasv"] = "aan", ["pres_pasv_conn"] = "a", }

stem_endings["past_pasv"] = { ["past_pasv"] = "iin", ["cond_pasv"] = "aisiin", ["cond_pasv_conn"] = "aisi", ["impr_pasv"] = "akoon", ["impr_pasv_conn"] = "ako", ["potn_pasv"] = "aneen", ["potn_pasv_conn"] = "ane", ["inf2_pasv_ine"] = "aessa", ["inf3_pasv_ins"] = "aman", ["pres_pasv_part"] = "ava", ["past_pasv_part"] = "u", }

-- Make a copy of the endings, with front vowels stem_endings = {["a"] = stem_endings, ["ä"] = mw.clone(stem_endings)}

for stem_key, endings in pairs(stem_endings["ä"]) do	for key, ending in pairs(endings) do		endings[key] = mw.ustring.gsub(endings[key], "([aou])", {["a"] = "ä", ["o"] = "ö", ["u"] = "y"}) end end

local function process_stems(data, stems, vh, no_make_stems) -- Create any stems that were not given if not no_make_stems then stems["inf1"] = stems["inf1"] or mw.clone(stems["pres"]) if not stems["cond"] and stems["pres"] then stems["cond"] = {} for _, stem in ipairs(stems["pres"]) do table.insert(stems["cond"], mw.ustring.gsub(stem, "[ei]$", "") .. "i") end end if not stems["impr"] and stems["pres"] then stems["impr"] = {} for _, stem in ipairs(stems["pres"]) do table.insert(stems["impr"], stem .. "k") end end if not stems["potn"] and stems["pres"] then stems["potn"] = {} for _, stem in ipairs(stems["pres"]) do table.insert(stems["potn"], stem .. "n") end end end

-- Create forms based on each stem, by adding endings to it	if not stems["inf2"] and stems["inf1"] then stems["inf2"] = {} for _, stem in ipairs(stems["inf1"]) do			table.insert(stems["inf2"], (mw.ustring.gsub(stem, "e$", "i"))) end end stems["pres_weak"] = stems["pres_weak"] or mw.clone(stems["pres"]) stems["past_weak"] = stems["past_weak"] or mw.clone(stems["past"]) -- Go through each of the stems given for stem_key, substems in pairs(stems) do		for _, stem in ipairs(substems) do			-- Attach the endings to the stem for form_key, ending in pairs(stem_endings[vh][stem_key]) do				if not data.forms[form_key] then data.forms[form_key] = {} end -- If the ending is "V" then it is a copy of the preceding vowel... if ending == "V" then -- ...but not if the stem ends in a long vowel or diphthong. if mw.ustring.find(stem, "([aeiouyäö])%1$") or mw.ustring.find(stem, "([aeiouyäö])[iuy]$") or mw.ustring.find(stem, "ie$") or mw.ustring.find(stem, "uo$") or mw.ustring.find(stem, "yö$") then ending = "" else ending = mw.ustring.match(stem, "([aeiouyäö])$") or "" end end table.insert(data.forms[form_key], stem .. ending) end end end

data["vh"] = vh end

local KOTUS_TYPE = "Kotus type "

local function make_kotus_title_number(type_number) return KOTUS_TYPE .. type_number end

local function make_kotus_title_word(reference_word) return '/ ' .. reference_word .. ' ' end

local function make_kotus_title(number, reference_word) return make_kotus_title_number(number) .. make_kotus_title_word(reference_word) end

local function inflection_type_is(data, number, reference_word, strong, weak) local title = make_kotus_title_number(number) local has_gradation = strong and strong ~= weak

if has_gradation then local letter = kotus_grad_type[strong .. "-" .. weak] if letter then title = title .. "*" .. letter else title = title .. "*"		end end

title = title .. make_kotus_title_word(reference_word)

if has_gradation then local EMPTY = " ∅ " local function format(grade) if grade == "" then return EMPTY else return "''" .. grade .. "''"			end end title = title .. ", " .. format(strong) .. "-" .. format(weak) .. " gradation" else title = title .. ", no gradation" end

data.title = title

table.insert(data.categories, "Finnish " .. reference_word .. "-type verbs") end

local function inflection_type_is_t_d(data, number, reference_word, weak) if weak == "d" then inflection_type_is(data, number, reference_word, "t", "d") else inflection_type_is(data, number, reference_word, weak .. "t", weak .. weak) end end

local function inflection_type_is_combo(data, number_a, reference_word_a, number_b, reference_word_b, strong, weak) local title = KOTUS_TYPE local has_gradation = strong and strong ~= weak local gradation_suffix = ""

if has_gradation then local letter = kotus_grad_type[strong .. "-" .. weak] if letter then gradation_suffix = "*" .. letter else gradation_suffix = "*" end end

title = title .. number_a .. gradation_suffix .. make_kotus_title_word(reference_word_a) title = title .. " and " .. number_b .. gradation_suffix .. make_kotus_title_word(reference_word_b)

if has_gradation then local EMPTY = " ∅ " local function format(grade) if grade == "" then return EMPTY else return "''" .. grade .. "''"			end end title = title .. ", " .. format(strong) .. "-" .. format(weak) .. " gradation" else title = title .. ", no gradation" end

data.title = title

table.insert(data.categories, "Finnish " .. reference_word_a .. "-type verbs") table.insert(data.categories, "Finnish " .. reference_word_b .. "-type verbs") end

--[=[	Inflection types ]=]--

inflections["sanoa"] = function(args, data) local params = get_params(args, 5) local apo = (params.weak == "" and mw.ustring.sub(params.base, -1) == params.final) and "'" or "" local stems = {} stems["pres"]     = {params.base .. params.strong .. params.final} stems["pres_weak"] = {params.base .. params.weak .. apo .. params.final} stems["past"]     = {params.base .. params.strong .. params.final .. "i"} stems["past_weak"] = {params.base .. params.weak .. apo .. params.final .. "i"} stems["pres_pasv"] = {params.base .. params.weak .. apo .. params.final .. "t"} stems["past_pasv"] = {params.base .. params.weak .. apo .. params.final .. "tt"} inflection_type_is(data, 52, "sanoa", params.strong, params.weak) process_stems(data, stems, params.a) end

inflections["muistaa"] = function(args, data) local params = get_params(args, 4) local stems = {} stems["pres"]     = {params.base .. params.strong .. params.a} stems["pres_weak"] = {params.base .. params.weak .. params.a} stems["past"]     = {params.base .. params.strong .. "i"} stems["past_weak"] = {params.base .. params.weak .. "i"} stems["pres_pasv"] = {params.base .. params.weak .. "et"} stems["past_pasv"] = {params.base .. params.weak .. "ett"} inflection_type_is(data, 53, "muistaa", params.strong, params.weak) process_stems(data, stems, params.a) end

inflections["huutaa"] = function(args, data) local params = get_params(args, 2) local weak = mw.ustring.match(params.base, "([lnr])$") or "d" local stems = {} stems["pres"]     = {params.base .. "t" .. params.a} stems["pres_weak"] = {params.base .. weak .. params.a} stems["past"]     = {params.base .. "si"} stems["pres_pasv"] = {params.base .. weak .. "et"} stems["past_pasv"] = {params.base .. weak .. "ett"} inflection_type_is_t_d(data, 54, "huutaa", weak) process_stems(data, stems, params.a) end

inflections["soutaa"] = function(args, data) local params = get_params(args, 2) local weak = mw.ustring.match(params.base, "([lnr])$") or "d" local stems = {} stems["pres"]     = {params.base .. "t" .. params.a} stems["pres_weak"] = {params.base .. weak .. params.a} stems["past"]     = {params.base .. "ti", params.base .. "si"} stems["past_weak"] = {params.base .. weak .. "i", params.base .. "si"} stems["pres_pasv"] = {params.base .. weak .. "et"} stems["past_pasv"] = {params.base .. weak .. "ett"} inflection_type_is_t_d(data, 55, "soutaa", weak) process_stems(data, stems, params.a) end

inflections["kaivaa"] = function(args, data) local params = get_params(args, 4) local stems = {} stems["pres"]     = {params.base .. params.strong .. params.a} stems["pres_weak"] = {params.base .. params.weak .. params.a} stems["past"]     = {params.base .. params.strong .. params.o .. "i"} stems["past_weak"] = {params.base .. params.weak .. params.o .. "i"} stems["pres_pasv"] = {params.base .. params.weak .. "et"} stems["past_pasv"] = {params.base .. params.weak .. "ett"} inflection_type_is(data, 56, "kaivaa", params.strong, params.weak) process_stems(data, stems, params.a) end

inflections["saartaa"] = function(args, data) local params = get_params(args, 2) local weak = mw.ustring.match(params.base, "([lnr])$") or "d" local stems = {} stems["pres"]     = {params.base .. "t" .. params.a} stems["pres_weak"] = {params.base .. weak .. params.a} stems["past"]     = {params.base .. "si", params.base .. "t" .. params.o .. "i"} stems["past_weak"] = {params.base .. "si", params.base .. weak .. params.o .. "i"} stems["pres_pasv"] = {params.base .. weak .. "et"} stems["past_pasv"] = {params.base .. weak .. "ett"} inflection_type_is_t_d(data, 57, "saartaa", weak) process_stems(data, stems, params.a) end

inflections["laskea"] = function(args, data) local params = get_params(args, 4) local stems = {} stems["pres"]     = {params.base .. params.strong .. "e"} stems["pres_weak"] = {params.base .. params.weak .. "e"} stems["past"]     = {params.base .. params.strong .. "i"} stems["past_weak"] = {params.base .. params.weak .. "i"} stems["pres_pasv"] = {params.base .. params.weak .. "et"} stems["past_pasv"] = {params.base .. params.weak .. "ett"} inflection_type_is(data, 58, "laskea", params.strong, params.weak) process_stems(data, stems, params.a) end

inflections["tuntea"] = function(args, data) local params = get_params(args, 2) local weak = mw.ustring.match(params.base, "([lnr])$") or "d" local stems = {} stems["pres"]     = {params.base .. "te"} stems["pres_weak"] = {params.base .. weak .. "e"} stems["past"]     = {params.base .. "si"} stems["pres_pasv"] = {params.base .. weak .. "et"} stems["past_pasv"] = {params.base .. weak .. "ett"} inflection_type_is_t_d(data, 59, "tuntea", weak) process_stems(data, stems, params.a) end

inflections["lähteä"] = function(args, data) local params = get_params(args, 2) local stems = {} stems["pres"]     = {params.base .. "hte"} stems["pres_weak"] = {params.base .. "hde"} stems["past"]     = {params.base .. "hti", params.base .. "ksi"} stems["past_weak"] = {params.base .. "hdi", params.base .. "ksi"} stems["pres_pasv"] = {params.base .. "hdet"} stems["past_pasv"] = {params.base .. "hdett"} inflection_type_is(data, 60, "lähteä", "t", "d") process_stems(data, stems, params.a) end

inflections["sallia"] = function(args, data) local params = get_params(args, 4) local apo = (params.weak == "" and mw.ustring.sub(params.base, -1) == "i") and "'" or "" local stems = {} stems["pres"]     = {params.base .. params.strong .. "i"} stems["pres_weak"] = {params.base .. params.weak .. apo .. "i"} stems["past"]     = {params.base .. params.strong .. "i"} stems["past_weak"] = {params.base .. params.weak .. apo .. "i"} stems["pres_pasv"] = {params.base .. params.weak .. apo .. "it"} stems["past_pasv"] = {params.base .. params.weak .. apo .. "itt"} inflection_type_is(data, 61, "sallia", params.strong, params.weak) process_stems(data, stems, params.a) end

inflections["voida"] = function(args, data) local params = get_params(args, 2) local stems = {} stems["inf1"]     = {params.base .. "d"} stems["pres"]     = {params.base} stems["past"]     = {params.base} stems["pres_pasv"] = {params.base .. "d"} stems["past_pasv"] = {params.base .. "t"} inflection_type_is(data, 62, "voida") process_stems(data, stems, params.a) end

inflections["saada"] = function(args, data) local params = get_params(args, 2) local vowel = mw.ustring.sub(params.base, -1) local stems = {} stems["inf1"]     = {params.base .. vowel .. "d"} stems["pres"]     = {params.base .. vowel} stems["past"]     = {params.base .. "i"} stems["cond"]     = {params.base .. "i"} stems["pres_pasv"] = {params.base .. vowel .. "d"} stems["past_pasv"] = {params.base .. vowel .. "t"} inflection_type_is(data, 63, "saada") process_stems(data, stems, params.a) end

inflections["juoda"] = function(args, data) local params = get_params(args, 2) local past_cond_stem = mw.ustring.sub(params.base, 1, -3) .. mw.ustring.sub(params.base, -1) local stems = {} stems["inf1"]     = {params.base .. "d"} stems["pres"]     = {params.base} stems["past"]     = {past_cond_stem .. "i"} stems["cond"]     = {past_cond_stem .. "i"} stems["pres_pasv"] = {params.base .. "d"} stems["past_pasv"] = {params.base .. "t"} inflection_type_is(data, 64, "juoda") process_stems(data, stems, params.a) end

inflections["käydä"] = function(args, data) local params = get_params(args, 2) local stems = {} stems["inf1"]     = {params.base .. params.u .. "d"} stems["pres"]     = {params.base .. params.u} stems["past"]     = {params.base .. "vi"} stems["cond"]     = {params.base .. "vi"} stems["pres_pasv"] = {params.base .. params.u .. "d"} stems["past_pasv"] = {params.base .. params.u .. "t"} inflection_type_is(data, 65, "käydä") process_stems(data, stems, params.a) end

inflections["rohkaista"] = function(args, data) local params = get_params(args, 5, true) local stems = {} stems["inf1"]     = {params.base .. params.weak .. params.final .. "st"} stems["pres"]     = {params.base .. params.strong .. params.final .. "se"} stems["past"]     = {params.base .. params.strong .. params.final .. "si"} stems["impr"]     = {params.base .. params.weak .. params.final .. "sk"} stems["potn"]     = {params.base .. params.weak .. params.final .. "ss"} stems["pres_pasv"] = {params.base .. params.weak .. params.final .. "st"} stems["past_pasv"] = {params.base .. params.weak .. params.final .. "st"} inflection_type_is(data, 66, "rohkaista", params.strong, params.weak) process_stems(data, stems, params.a) end

inflections["tulla"] = function(args, data) local params = get_params(args, 5, true) local cons = mw.ustring.sub(params.final, -1) local stems = {} stems["inf1"]     = {params.base .. params.weak .. params.final .. cons} stems["pres"]     = {params.base .. params.strong .. params.final .. "e"} stems["past"]     = {params.base .. params.strong .. params.final .. "i"} stems["impr"]     = {params.base .. params.weak .. params.final .. "k"} stems["potn"]     = {params.base .. params.weak .. params.final .. cons} stems["pres_pasv"] = {params.base .. params.weak .. params.final .. cons} stems["past_pasv"] = {params.base .. params.weak .. params.final .. "t"} inflection_type_is(data, 67, "tulla", params.strong, params.weak) process_stems(data, stems, params.a) end

inflections["tupakoida"] = function(args, data) local params = get_params(args, 2) local stems = {} stems["inf1"]     = {params.base .. "d"} stems["pres"]     = {params.base, params.base .. "tse"} stems["past"]     = {params.base, params.base .. "tsi"} stems["impr"]     = {params.base .. "k"} stems["potn"]     = {params.base .. "n"} stems["pres_pasv"] = {params.base .. "d"} stems["past_pasv"] = {params.base .. "t"} inflection_type_is(data, 68, "tupakoida") process_stems(data, stems, params.a) end

inflections["valita"] = function(args, data) local params = get_params(args, 2) local stems = {} stems["inf1"]     = {params.base .. "t"} stems["pres"]     = {params.base .. "tse"} stems["past"]     = {params.base .. "tsi"} stems["impr"]     = {params.base .. "tk"} stems["potn"]     = {params.base .. "nn"} stems["pres_pasv"] = {params.base .. "t"} stems["past_pasv"] = {params.base .. "tt"} inflection_type_is(data, 69, "valita") process_stems(data, stems, params.a) end

inflections["juosta"] = function(args, data) local params = get_params(args, 2) local stems = {} stems["inf1"]     = {params.base .. "st"} stems["pres"]     = {params.base .. "kse"} stems["past"]     = {params.base .. "ksi"} stems["impr"]     = {params.base .. "sk"} stems["potn"]     = {params.base .. "ss"} stems["pres_pasv"] = {params.base .. "st"} stems["past_pasv"] = {params.base .. "st"} inflection_type_is(data, 70, "juosta") process_stems(data, stems, params.a) end

inflections["nähdä"] = function(args, data) local params = get_params(args, 2) local stems = {} stems["inf1"]     = {params.base .. "hd"} stems["pres"]     = {params.base .. "ke"} stems["pres_weak"] = {params.base .. "e"} stems["past"]     = {params.base .. "ki"} stems["past_weak"] = {params.base .. "i"} stems["impr"]     = {params.base .. "hk"} stems["potn"]     = {params.base .. "hn"} stems["pres_pasv"] = {params.base .. "hd"} stems["past_pasv"] = {params.base .. "ht"} inflection_type_is(data, 71, "nähdä", "k", "") process_stems(data, stems, params.a) end

inflections["vanheta"] = function(args, data) local params = get_params(args, 5, true) local stems = {} stems["inf1"]     = {params.base .. params.weak .. params.final .. "t"} stems["pres"]     = {params.base .. params.strong .. params.final .. "ne"} stems["past"]     = {params.base .. params.strong .. params.final .. "ni"} stems["impr"]     = {params.base .. params.weak .. params.final .. "tk"} stems["potn"]     = {params.base .. params.weak .. params.final .. "nn"} stems["pres_pasv"] = {params.base .. params.weak .. params.final .. "t"} stems["past_pasv"] = {params.base .. params.weak .. params.final .. "tt"} inflection_type_is(data, 72, "vanheta", params.strong, params.weak) process_stems(data, stems, params.a) end

inflections["salata"] = function(args, data) local params = get_params(args, 4, true) local stems = {} stems["inf1"]     = {params.base .. params.weak .. params.a .. "t"} stems["pres"]     = {params.base .. params.strong .. params.a .. params.a} stems["past"]     = {params.base .. params.strong .. params.a .. "si"} stems["cond"]     = {params.base .. params.strong .. params.a .. "i"} stems["impr"]     = {params.base .. params.weak .. params.a .. "tk"} stems["potn"]     = {params.base .. params.weak .. params.a .. "nn"} stems["pres_pasv"] = {params.base .. params.weak .. params.a .. "t"} stems["past_pasv"] = {params.base .. params.weak .. params.a .. "tt"} inflection_type_is(data, 73, "salata", params.strong, params.weak) process_stems(data, stems, params.a) end

inflections["katketa"] = function(args, data) local params = get_params(args, 5, true) local stems = {} stems["inf1"]     = {params.base .. params.weak .. params.final .. "t"} stems["pres"]     = {params.base .. params.strong .. params.final .. params.a} stems["past"]     = {params.base .. params.strong .. params.final .. "si"} stems["cond"]     = {params.base .. params.strong .. params.final .. params.a .. "i", params.base .. params.strong .. params.final .. "i"} stems["impr"]     = {params.base .. params.weak .. params.final .. "tk"} stems["potn"]     = {params.base .. params.weak .. params.final .. "nn"} stems["pres_pasv"] = {params.base .. params.weak .. params.final .. "t"} stems["past_pasv"] = {params.base .. params.weak .. params.final .. "tt"} inflection_type_is(data, 74, "katketa", params.strong, params.weak) process_stems(data, stems, params.a) end

inflections["selvitä"] = function(args, data) local params = get_params(args, 5, true) local stems = {} stems["inf1"]     = {params.base .. params.weak .. params.final .. "t"} stems["pres"]     = {params.base .. params.strong .. params.final .. params.a} stems["past"]     = {params.base .. params.strong .. params.final .. "si"} stems["impr"]     = {params.base .. params.weak .. params.final .. "tk"} stems["potn"]     = {params.base .. params.weak .. params.final .. "nn"} stems["pres_pasv"] = {params.base .. params.weak .. params.final .. "t"} stems["past_pasv"] = {params.base .. params.weak .. params.final .. "tt"} inflection_type_is(data, 75, "selvitä", params.strong, params.weak) process_stems(data, stems, params.a) end

inflections["taitaa"] = function(args, data) local params = get_params(args, 2) local stems = {} stems["pres"]     = {params.base .. "t" .. params.a} stems["pres_weak"] = {params.base .. "d" .. params.a} stems["past"]     = {params.base .. "si"} stems["potn"]     = {params.base .. "t" .. params.a .. "n", params.base .. "nn"} stems["pres_pasv"] = {params.base .. "det"} stems["past_pasv"] = {params.base .. "dett"} inflection_type_is(data, 76, "taitaa", "t", "d") process_stems(data, stems, params.a) end

inflections["virkkaa"] = function(args, data) local stems = {} stems["inf1"]     = {"virkka"} stems["pres"]     = {"virkka"} stems["pres_weak"] = {"virka"} stems["past"]     = {"virkkoi"} stems["past_weak"] = {"virkoi"} stems["cond"]     = {"virkkai"} stems["impr"]     = {"virkkak"} stems["potn"]     = {"virkkan"} process_stems(data, stems, "a", true) local stems = {} stems["pres_pasv"] = {"virket"} stems["past_pasv"] = {"virkett"} process_stems(data, stems, "ä", true)

inflection_type_is_combo(data, 56, "kaivaa", 53, "muistaa", "kk", "k") data.title = data.title .. ", irregular vowel harmony" end

inflections["seistä"] = function(args, data) local stems = {} stems["inf1"]     = {"seist"} stems["impr"]     = {"seisk"} stems["potn"]     = {"seiss"} stems["pres_pasv"] = {"seist"} stems["past_pasv"] = {"seist"} process_stems(data, stems, "ä", true) local stems = {} stems["pres"]     = {"seiso"} stems["past"]     = {"seisoi"} stems["cond"]     = {"seisoi"} process_stems(data, stems, "a", true)

inflection_type_is_combo(data, 52, "sanoa", 66, "rohkaista") end

inflections["olla"] = function(args, data) local stems = {} stems["inf1"]     = {"oll"} stems["pres"]     = {"ole"} stems["past"]     = {"oli"} stems["impr"]     = {"olk"} stems["potn"]     = {"oll"} stems["pres_pasv"] = {"oll"} stems["past_pasv"] = {"olt"} process_stems(data, stems, "a") data.forms["pres_3sg"] = {"on"} data.forms["pres_3pl"] = {"ovat"} data.forms["potn_1sg"] = {"lienen"} data.forms["potn_2sg"] = {"lienet"} data.forms["potn_3sg"] = {"lienee"} data.forms["potn_1pl"] = {"lienemme"} data.forms["potn_2pl"] = {"lienette"} data.forms["potn_3pl"] = {"lienevät"} data.forms["potn_conn"] = {"liene"}

inflection_type_is_combo(data, 67, "tulla", 64, "juoda") end

-- Helper functions

local complex_forms = { -- Present ["pres_1sg_neg"] = { "en", "pres_conn" }, ["pres_2sg_neg"] = { "et", "pres_conn" }, ["pres_3sg_neg"] = { "ei", "pres_conn" }, ["pres_1pl_neg"] = { "emme", "pres_conn" }, ["pres_2pl_neg"] = { "ette", "pres_conn" }, ["pres_3pl_neg"] = { "eivät", "pres_conn" }, ["pres_pasv_neg"] = { "ei", "pres_pasv_conn" }, ["pres_perf_1sg"] = { "olen", "past_part" }, ["pres_perf_2sg"] = { "olet", "past_part" }, ["pres_perf_3sg"] = { "on", "past_part" }, ["pres_perf_1pl"] = { "olemme", "past_part_pl" }, ["pres_perf_2pl"] = { "olette", "past_part_pl" }, ["pres_perf_3pl"] = { "ovat", "past_part_pl" }, ["pres_perf_pasv"] = { "on", "past_pasv_part" }, ["pres_perf_1sg_neg"] = { "en ole", "past_part" }, ["pres_perf_2sg_neg"] = { "et ole", "past_part" }, ["pres_perf_3sg_neg"] = { "ei ole", "past_part" }, ["pres_perf_1pl_neg"] = { "emme ole", "past_part_pl" }, ["pres_perf_2pl_neg"] = { "ette ole", "past_part_pl" }, ["pres_perf_3pl_neg"] = { "eivät ole", "past_part_pl" }, ["pres_perf_pasv_neg"] = { "ei ole", "past_pasv_part" }, -- Past ["past_1sg_neg"] = { "en", "past_part" }, ["past_2sg_neg"] = { "et", "past_part" }, ["past_3sg_neg"] = { "ei", "past_part" }, ["past_1pl_neg"] = { "emme", "past_part_pl" }, ["past_2pl_neg"] = { "ette", "past_part_pl" }, ["past_3pl_neg"] = { "eivät", "past_part_pl" }, ["past_pasv_neg"] = { "ei", "past_pasv_part" }, ["past_perf_1sg"] = { "olin", "past_part" }, ["past_perf_2sg"] = { "olit", "past_part" }, ["past_perf_3sg"] = { "oli", "past_part" }, ["past_perf_1pl"] = { "olimme", "past_part_pl" }, ["past_perf_2pl"] = { "olitte", "past_part_pl" }, ["past_perf_3pl"] = { "olivat", "past_part_pl" }, ["past_perf_pasv"] = { "oli", "past_pasv_part" }, ["past_perf_1sg_neg"] = { "en ollut", "past_part" }, ["past_perf_2sg_neg"] = { "et ollut", "past_part" }, ["past_perf_3sg_neg"] = { "ei ollut", "past_part" }, ["past_perf_1pl_neg"] = { "emme olleet", "past_part_pl" }, ["past_perf_2pl_neg"] = { "ette olleet", "past_part_pl" }, ["past_perf_3pl_neg"] = { "eivät olleet", "past_part_pl" }, ["past_perf_pasv_neg"] = { "ei ollut", "past_pasv_part" }, -- Conditional ["cond_1sg_neg"] = { "en", "cond_conn" }, ["cond_2sg_neg"] = { "et", "cond_conn" }, ["cond_3sg_neg"] = { "ei", "cond_conn" }, ["cond_1pl_neg"] = { "emme", "cond_conn" }, ["cond_2pl_neg"] = { "ette", "cond_conn" }, ["cond_3pl_neg"] = { "eivät", "cond_conn" }, ["cond_pasv_neg"] = { "ei", "cond_pasv_conn" }, ["cond_perf_1sg"] = { "olisin", "past_part" }, ["cond_perf_2sg"] = { "olisit", "past_part" }, ["cond_perf_3sg"] = { "olisi", "past_part" }, ["cond_perf_1pl"] = { "olisimme", "past_part_pl" }, ["cond_perf_2pl"] = { "olisitte", "past_part_pl" }, ["cond_perf_3pl"] = { "olisivat", "past_part_pl" }, ["cond_perf_pasv"] = { "olisi", "past_pasv_part" }, ["cond_perf_1sg_neg"] = { "en olisi", "past_part" }, ["cond_perf_2sg_neg"] = { "et olisi", "past_part" }, ["cond_perf_3sg_neg"] = { "ei olisi", "past_part" }, ["cond_perf_1pl_neg"] = { "emme olisi", "past_part_pl" }, ["cond_perf_2pl_neg"] = { "ette olisi", "past_part_pl" }, ["cond_perf_3pl_neg"] = { "eivät olisi", "past_part_pl" }, ["cond_perf_pasv_neg"] = { "ei olisi", "past_pasv_part" }, -- Imperative ["impr_2sg_neg"] = { "älä", "impr_2sg" }, ["impr_3sg_neg"] = { "älköön", "impr_conn" }, ["impr_1pl_neg"] = { "älkäämme", "impr_conn" }, ["impr_2pl_neg"] = { "älkää", "impr_conn" }, ["impr_3pl_neg"] = { "älkööt", "impr_conn" }, ["impr_pasv_neg"] = { "älköön", "impr_pasv_conn" }, ["impr_perf_3sg"] = { "olkoon", "past_part" }, ["impr_perf_3pl"] = { "olkoot", "past_part_pl" }, ["impr_perf_pasv"] = { "olkoon", "past_pasv_part" }, ["impr_perf_3sg_neg"] = { "älköön olko", "past_part" }, ["impr_perf_3pl_neg"] = { "älkööt olko", "past_part_pl" }, ["impr_perf_pasv_neg"] = { "älköön olko", "past_pasv_part" }, -- Potential ["potn_1sg_neg"] = { "en", "potn_conn" }, ["potn_2sg_neg"] = { "et", "potn_conn" }, ["potn_3sg_neg"] = { "ei", "potn_conn" }, ["potn_1pl_neg"] = { "emme", "potn_conn" }, ["potn_2pl_neg"] = { "ette", "potn_conn" }, ["potn_3pl_neg"] = { "eivät", "potn_conn" }, ["potn_pasv_neg"] = { "ei", "potn_pasv_conn" }, ["potn_perf_1sg"] = { "lienen", "past_part" }, ["potn_perf_2sg"] = { "lienet", "past_part" }, ["potn_perf_3sg"] = { "lienee", "past_part" }, ["potn_perf_1pl"] = { "lienemme", "past_part_pl" }, ["potn_perf_2pl"] = { "lienette", "past_part_pl" }, ["potn_perf_3pl"] = { "lienevät", "past_part_pl" }, ["potn_perf_pasv"] = { "lienee", "past_pasv_part" }, ["potn_perf_1sg_neg"] = { "en liene", "past_part" }, ["potn_perf_2sg_neg"] = { "et liene", "past_part" }, ["potn_perf_3sg_neg"] = { "ei liene", "past_part" }, ["potn_perf_1pl_neg"] = { "emme liene", "past_part_pl" }, ["potn_perf_2pl_neg"] = { "ette liene", "past_part_pl" }, ["potn_perf_3pl_neg"] = { "eivät liene", "past_part_pl" }, ["potn_perf_pasv_neg"] = { "ei liene", "past_pasv_part" }, }

function postprocess(args, data) local appendix = args["appendix"]; if appendix == "" then appendix = nil end local qual = args["qual"]; if qual == "" then qual = nil end local q4i = args["q4i"]; if q4i == "" then q4i = nil end local extranotes = {} -- Create the periphrastic forms (negative and perfect) local function make_forms(aux, forms) if not forms then return nil end local ret = {} for _, form in ipairs(forms) do table.insert(ret, aux .. " " .. form .. "") end return ret end

if qual then data.no_accel = true end -- Present for key, value in pairs(complex_forms) do		data.forms[key] = make_forms(value[1], data.forms[value[2]]) end -- Add qualifier for key, form in pairs(data.forms) do		-- Add qual -- for participles, qual is before, while for others it is after if q4i and key == "inf4" then for i, subform in ipairs(form) do subform = (q4i and q4i .. " " or "") .. subform form[i] = subform end if form.rare then for i, subform in ipairs(form.rare) do subform = (q4i and q4i .. " " or "") .. subform form.rare[i] = subform end end elseif string.sub(key, -5) == "_part" then for i, subform in ipairs(form) do subform = (qual and qual .. " " or "") .. subform form[i] = subform end if form.rare then for i, subform in ipairs(form.rare) do subform = (qual and qual .. " " or "") .. subform form.rare[i] = subform end end else for i, subform in ipairs(form) do subform = subform .. (qual and " " .. qual or "") form[i] = subform end if form.rare then for i, subform in ipairs(form.rare) do subform = subform .. (qual and " " .. qual or "") form.rare[i] = subform end end end data.forms[key] = form end data.is_appendix = appendix if args.noagent then data.forms["agnt_part"] = nil end

if data.forms["inf1"][1] == data.forms["pres_3sg"][1] then table.insert(extranotes, "&#42; The third-person singular indicative form " .. tag_term(data.forms["inf1"][1]) .. " does not exhibit final gemination, unlike the first infinitive (the lemma form), even though they are spelled identically.") end

if extranotes then data.extranotes = extranotes end -- Check if the lemma form matches the page name if not appendix and not (args["q1sg"] or args["q2sg"] or args["q1pl"] or args["q2pl"] or args["q3p"] or args["qpass"]) and (lang:makeEntryName(data.forms["inf1"][1])) ~= normalize_apostrophes(data.pagename, true) then table.insert(data.categories, "Finnish entries with inflection not matching pagename") end end

local inf_to_accel = { ["1"] = nil, ["1_long"] = "long|first|inf", ["2_ine"] = "ine|of|second|actv|inf", ["2_pasv_ine"] = "ine|of|second|pasv|inf", ["2_ins"] = "ist|of|second|actv|inf", ["3_ine"] = "ine|of|third|actv|inf", ["3_ela"] = "ela|of|third|actv|inf", ["3_ill"] = "ill|of|third|actv|inf", ["3_ade"] = "ade|of|third|actv|inf", ["3_abe"] = "abe|of|third|actv|inf", ["3_ins"] = "ist|of|third|actv|inf", ["3_pasv_ins"] = "ist|of|third|pasv|inf", ["4"] = "vnoun", ["5"] = "fifth|inf" }

local part_to_accel = { ["pres_part"] = "pres|actv|part", ["pres_pasv_part"] = "pres|pasv|part", ["past_part"] = "past|actv|part", ["past_pasv_part"] = "past|pasv|part", ["agnt_part"] = "agentpart", ["nega_part"] = "neg|part" }

function convert_to_accel_inf(form) return inf_to_accel[form:sub(4)] end

function convert_to_accel_part(form) return "participle-" .. part_to_accel[form] end

function convert_to_accel(form, vh) if mw.ustring.match(form, "_perf") then -- all perf forms involve the past participle which we do not want -- to create manually return nil elseif form == "inf4" then return "vnoun-" .. vh	elseif mw.ustring.match(form, "^inf") then return convert_to_accel_inf(form) elseif mw.ustring.match(form, "_part$") then return convert_to_accel_part(form) end

-- imperative connegative is special if form == "impr_2sg_neg" then return "2|s|impr|conn" elseif mw.ustring.match(form, "impr_%d%a%a_neg") then return "3|or|p|impr|conn" end

-- split to tense/mood, person, extra local tmood, person, extra = unpack(mw.text.split(form, "_")) local tense, mood = "", tmood if tmood == "pres" or tmood == "past" then tense, mood = tmood .. "|", "indc" end

-- negative/connegative? if extra == "neg" then local result = tense if person == "pasv" then result = result .. "pasv" else -- not passive => active (no distinction between person here) result = result .. "actv" end result = result .. "|" .. mood .. "|conn" return result end

-- convert person if not passive person = person:gsub("(%d)(%a)%a", "%1|%2") return person .. "|" .. tense .. mood end

local poss_endings = { ["1s"] = "ni", ["2s"] = "si", ["1p"] = "mme", ["2p"] = "nne", ["3"] = "nsa" }

local accel_prefixes = { ["1s"] = "1|s", ["2s"] = "2|s", ["1p"] = "1|p", ["2p"] = "2|p", ["3"] = "3" }

-- Make the table function make_table(data) local vh = data.vh	local function show_form(form, accel_form) if not form then return "&mdash;" elseif type(form) ~= "table" then error("a non-table value was given in the list of inflected forms.") end local ret = {} for key, subform in ipairs(form) do			if mw.ustring.find(subform, "¤") then subform = mw.ustring.gsub(subform, "¤", "") end local accel = (accel_form and not data.no_accel) and accel_form or nil table.insert(ret, make_link(subform, accel)) end return table.concat(ret, " ") end local function make_and_show_poss_table(form, vh, accel_suffix) local short if mw.ustring.find(form, "([aäe])¤") then short = mw.ustring.gsub(form, "([aäe])¤", "%1%1n") end local function poss_repl(mode) local ending = poss_endings[mode] if ending:find("a") then ending = mw.ustring.gsub(ending, "a", vh) end local forms = {(mw.ustring.gsub(form, "¤", ending))} if mode == "3" and short then table.insert(forms, 1, short) end local ret = {} for key, subform in ipairs(forms) do local accel = (accel_suffix and not data.no_accel) and accel_prefixes[mode] .. "|form|of|" .. accel_suffix or nil table.insert(ret, make_link(subform, accel)) end return table.concat(ret, " ") end local poss_table_wikicode = [=[ return mw.ustring.gsub(poss_table_wikicode, "", poss_repl) end local function repl(param) if param == "lemma" then return (data.is_appendix and make_link(data.pagename) or tag_term(data.pagename)) elseif param == "info" then return data.title and " (" .. data.title .. ")" or "" elseif param == "extranotes" then if data.extranotes and #data.extranotes > 0 then return " \n" .. table.concat(data.extranotes, " \n") else return "" end elseif param:find("^m_") then return tag_term(param:sub(3)) elseif param:find("^poss_") then local result = "" local accel_suffix = convert_to_accel(param:sub(6), nil) for _, subform in ipairs(data.forms[param:sub(6)]) do result = result .. make_and_show_poss_table(subform, vh, accel_suffix) .. "\n" end return result else return show_form(data.forms[param], convert_to_accel(param, vh)) end end local wikicode = [=[ return mw.ustring.gsub(wikicode, "", repl) end

return export