Mô đun:fi-nominals
Giao diện
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 m_bit32 -- loaded later if needed
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("^-") then
if term == mw.title.getCurrentTitle().fullText then
return '<span class="Latn" lang="fi"><strong class="selflink">' .. term .. '</strong></span>'
end
return '<span class="Latn" lang="fi">' .. term .. '</span>'
end
-- if there is something difficult, use full module.
if term:find(":") or 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 '<span class="Latn" lang="fi"><strong class="selflink">' .. term .. '</strong></span>'
end
if not accel_form then
return '<span class="Latn" lang="fi">[[' .. target .. '#Tiếng Phần Lan|' .. term .. ']]</span>'
end
return '<span class="Latn form-of lang-fi ' .. accel_form .. '-form-of" lang="fi">[[' .. target .. '#Tiếng Phần Lan|' .. term .. ']]</span>'
end
local function tag_term(term)
-- return require("Module:script utilities").tag_text(term, lang, nil, "term")
return '<i class="Latn mention" lang="fi">' .. term .. '</i>'
end
local function do_inflection_internal(data, argobj)
local args = argobj.args
argobj.pos = 1
data.words = {}
data.num = 1
data.forms = nil
data.categories = {}
for num, infl_type in ipairs(data.infl_types) do
-- initialize data for single word
local word_data = {forms = {}, title = nil, categories = {}}
-- word index
word_data.num = num
data.num = num
-- Generate the forms
inflections[infl_type](argobj, word_data)
postprocess_word(argobj, word_data, data, num == #data.infl_types)
word_data.class = infl_type
data.words[num] = word_data
end
if #data.words > 1 then
-- join the inflected word components
export.join_words(data, function (n) return args["space" .. tostring(n)] or args["space"] or " " end)
else
data.vh = data.words[1].vh
data.forms = data.words[1].forms
data.title = data.words[1].title
data.categories = data.words[1].categories
end
-- Postprocess
postprocess(args, data)
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
local infl_types = {infl_type}
infl_types = mw.text.split(infl_type, "%-")
for _, type in ipairs(infl_types) do
if not inflections[type] then
error("Unknown inflection type '" .. infl_type .. "'")
end
end
local pos = args["pos"]; if not pos or pos == "" then pos = "noun" end
local allow_possessive = (pos == "noun" or pos == "adj") and not args["poss"]
-- initialize data for full inflection process
local data = {
pagename = mw.title.getCurrentTitle().text,
infl_types = infl_types,
poss = args["poss"]
}
local argobj = {args = args}
if args["title"] and mw.title.getCurrentTitle().namespace > 0 then
data.pagename = args.title
elseif data.pagename:find("^Unsupported titles/") then
data.pagename = data.pagename:gsub("^Unsupported titles/", "")
end
data.pagename = normalize_apostrophes(data.pagename)
do_inflection_internal(data, argobj)
--if args["type"] then table.insert(data.categories, "fi-decl with type") end
--if args["nocheck"] then table.insert(data.categories, "fi-decl with nocheck") end
--if args["nosg"] then table.insert(data.categories, "fi-decl with nosg") end
--if args["nopl"] then table.insert(data.categories, "fi-decl with nopl") end
local function get_poss_forms(poss)
data.poss = poss
do_inflection_internal(data, argobj)
return data
end
local categories
if args["appendix"] then
categories = ""
else
categories = require("Module:utilities").format_categories(data.categories, lang)
end
return make_table(data, true)
.. (allow_possessive and make_possessive_table(data.pagename, args, pos, data.title, get_poss_forms) or "")
.. categories
.. require("Module:TemplateStyles")("Module:fi-nominals/style.css")
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
function get_params(argobj, num, invert_grades)
local params = {}
local args = argobj.args
local pos = argobj.pos
params.base = normalize_apostrophes(args[pos])
if num >= 2 then
if num >= 4 then
params.strong = normalize_apostrophes(args_get_required(args, pos + 1, "Nominative grade"))
params.weak = normalize_apostrophes(args_get_required(args, pos + 2, "Genitive 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, pos + 3, "Final letter(s)")
end
params.a = args_get_vowel_harmony(args, pos + num - 1)
else
params.base = params.base or ""
end
if params.a then
params.o = params.a == "ä" and "ö" or "o"
params.u = params.a == "ä" and "y" or "u"
end
argobj.pos = argobj.pos + num
return params
end
function get_extra_arg(argobj, wdata, name, fallback)
return argobj.args[name .. wdata.num] or argobj.args[name]
end
--[=[
Inflection functions
]=]--
local stem_endings = {}
stem_endings["nom_sg"] = {
["nom_sg"] = "",
}
stem_endings["sg"] = {
["ess_sg"] = "na",
}
stem_endings["sg_weak"] = {
["gen_sg"] = "n",
["ine_sg"] = "ssa",
["ela_sg"] = "sta",
["ade_sg"] = "lla",
["abl_sg"] = "lta",
["all_sg"] = "lle",
["tra_sg"] = "ksi",
["ins_sg"] = "n",
["abe_sg"] = "tta",
["nom_pl"] = "t",
}
stem_endings["par_sg"] = {
["par_sg"] = "a",
}
stem_endings["ill_sg"] = {
["ill_sg"] = "Vn",
}
stem_endings["pl"] = {
["ess_pl"] = "na",
["com_pl"] = "ne",
}
stem_endings["pl_weak"] = {
["ine_pl"] = "ssa",
["ela_pl"] = "sta",
["ade_pl"] = "lla",
["abl_pl"] = "lta",
["all_pl"] = "lle",
["tra_pl"] = "ksi",
["ins_pl"] = "n",
["abe_pl"] = "tta",
}
stem_endings["par_pl"] = {
["par_pl"] = "a",
}
stem_endings["gen_pl"] = {
["gen_pl"] = "en",
}
stem_endings["ill_pl"] = {
["ill_pl"] = "Vn",
}
-- 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
-- data for generating possessive forms
-- suffixes per person
local poss_forms = {["1s"] = "ni", ["2s"] = "si", ["3s"] = "nsa", ["1p"] = "mme", ["2p"] = "nne"}
local poss_alt = {--["00"] = false, ["1s"] = false, ["2s"] = false, ["1p"] = false, ["2p"] = false,
["3s"] = true, -- shorter form -Vn
}
-- which forms allow -nsa > -Vn?
local forms_alt_ok = {
["gen_sg"] = false, ["gen_pl"] = false,
["par_sg"] = false, ["par_pl"] = true,
["ine_sg"] = true, ["ine_pl"] = true,
["ela_sg"] = true, ["ela_pl"] = true,
["ill_sg"] = false, ["ill_pl"] = false,
["ade_sg"] = true, ["ade_pl"] = true,
["abl_sg"] = true, ["abl_pl"] = true,
["all_sg"] = true, ["all_pl"] = true,
["ess_sg"] = true, ["ess_pl"] = true,
["tra_sg"] = true, ["tra_pl"] = true,
["ins_sg"] = false, ["ins_pl"] = false,
["abe_sg"] = true, ["abe_pl"] = true,
["com_sg"] = true, ["com_pl"] = true,
}
-- which forms end in -n?
-- (in which case it is dropped before the possessive suffix)
local forms_gen_ok = {
["gen_sg"] = true, ["gen_pl"] = true,
["ill_sg"] = true, ["ill_pl"] = true,
["ins_sg"] = true, ["ins_pl"] = true,
}
local function feed_list(outputs, inputs)
for key, values in pairs(inputs) do
outputs[key] = outputs[key] or {}
for _, value in ipairs(values) do
table.insert(outputs[key], value)
end
end
end
local function process_stems(data, stems, vh)
-- Create any stems that were not given
stems["nom_sg"] = stems["nom_sg"] or mw.clone(stems["sg"])
stems["par_sg"] = stems["par_sg"] or mw.clone(stems["sg"])
stems["par_pl"] = stems["par_pl"] or mw.clone(stems["pl"])
stems["ill_pl"] = stems["ill_pl"] or mw.clone(stems["pl"])
if not stems["ill_sg"] and stems["sg"] then
stems["ill_sg"] = {}
for _, stem in ipairs(stems["sg"]) do
-- If the stem ends in a long vowel or diphthong, then add -h
if mw.ustring.find(stem, "([aeiouyäö])%1$") or mw.ustring.find(stem, "[aeiouyäö][iuyü]$") then
table.insert(stems["ill_sg"], stem .. "h")
else
table.insert(stems["ill_sg"], stem)
end
end
end
if not stems["gen_pl"] and stems["par_pl"] then
stems["gen_pl"] = {}
for _, stem in ipairs(stems["par_pl"]) do
-- If the partitive plural stem ends in -it, then replace the t with d or tt
if mw.ustring.find(stem, "it$") then
table.insert(stems["gen_pl"], (mw.ustring.gsub(stem, "t$", "d")))
table.insert(stems["gen_pl"], stem .. "t")
else
table.insert(stems["gen_pl"], stem)
end
end
end
-- Create forms based on each stem, by adding endings to it
stems["sg_weak"] = stems["sg_weak"] or mw.clone(stems["sg"])
stems["pl_weak"] = stems["pl_weak"] or mw.clone(stems["pl"])
-- 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
-- "V" is a copy of the last vowel in the stem
if mw.ustring.find(ending, "V") then
local vowel = mw.ustring.match(stem, "([aeiouyäö])[^aeiouyäö]*$")
ending = mw.ustring.gsub(ending, "V", vowel or "?")
end
table.insert(data.forms[form_key], stem .. ending)
end
end
end
data["stems"] = stems
data["vh"] = vh
end
local function make_kotus_title_number(type_number)
return "[[Kotus]] loại " .. type_number
end
local function make_kotus_title_word(reference_word)
return '/<span lang="fi" class="Latn">[[Phụ lục:Biến cách tiếng Phần Lan/' .. reference_word .. '|' .. reference_word .. ']]</span>'
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 = "<small>∅</small>"
local function format(grade)
if grade == "" then
return EMPTY
else
return "''" .. grade .. "''"
end
end
title = title .. ", cấp " .. format(strong) .. "-" .. format(weak) .. ""
else
title = title .. ", không thay đổi cấp"
end
data.title = title
table.insert(data.categories, "Từ tiếng Phần Lan thuộc loại " .. reference_word)
end
--[=[
Inflection types
]=]--
inflections["valo"] = function(args, data)
local params = get_params(args, 5)
local wk_sg = params.weak
local wk_pl = params.weak
if mw.ustring.sub(params.base, -1) == params.final then
if wk_sg == "" and (mw.ustring.find(params.base, "[aeiouyäö][iuy]$") or mw.ustring.find(params.base, "[iuy][eoö]$")) then
wk_sg = "’"
end
if wk_pl == "" then
wk_pl = "’"
end
end
local stems = {}
stems["sg"] = {params.base .. params.strong .. params.final}
stems["sg_weak"] = {params.base .. wk_sg .. params.final}
stems["pl"] = {params.base .. params.strong .. params.final .. "i"}
stems["pl_weak"] = {params.base .. wk_pl .. params.final .. "i"}
stems["par_pl"] = {params.base .. params.strong .. params.final .. "j"}
stems["ill_pl"] = {params.base .. params.strong .. params.final .. "ih"}
inflection_type_is(data, 1, "valo", params.strong, params.weak)
process_stems(data, stems, params.a)
end
inflections["palvelu"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["sg"] = {params.base}
stems["pl"] = {params.base .. "i"}
stems["par_pl"] = {params.base .. "j", params.base .. "it"}
stems["ill_pl"] = {params.base .. "ih"}
inflection_type_is(data, 2, "palvelu")
process_stems(data, stems, params.a)
end
inflections["valtio"] = function(args, data)
local params = get_params(args, 2)
local final = mw.ustring.sub(params.base, -1)
local stems = {}
stems["sg"] = {params.base}
stems["par_sg"] = {params.base .. "t"}
stems["pl"] = {params.base .. "i"}
stems["par_pl"] = {params.base .. "it"}
stems["ill_pl"] = {params.base .. "ih"}
inflection_type_is(data, 3, "valtio")
process_stems(data, stems, params.a)
end
inflections["laatikko"] = function(args, data)
local params = get_params(args, 5, false, "kk", "k", "o")
local stems = {}
stems["sg"] = {params.base .. params.strong .. params.final}
stems["sg_weak"] = {params.base .. params.weak .. params.final}
stems["pl"] = {params.base .. params.strong .. params.final .. "i"}
stems["pl_weak"] = {params.base .. params.weak .. params.final .. "i"}
stems["par_pl"] = {params.base .. params.strong .. params.final .. "j", params.base .. params.weak .. params.final .. "it"}
stems["ill_pl"] = {params.base .. params.strong .. params.final .. "ih", params.base .. params.weak .. params.final .. "ih"}
inflection_type_is(data, 4, "laatikko", params.strong, params.weak)
process_stems(data, stems, params.a)
end
inflections["risti"] = function(args, data)
local params = get_params(args, 4)
local i = get_extra_arg(args, data, "i"); if i == "0" then i = "" else i = "i" end
local stems = {}
stems["nom_sg"] = {params.base .. params.strong .. i}
stems["sg"] = {params.base .. params.strong .. "i"}
stems["sg_weak"] = {params.base .. params.weak .. "i"}
stems["pl"] = {params.base .. params.strong .. "ei"}
stems["pl_weak"] = {params.base .. params.weak .. "ei"}
stems["gen_pl"] = {params.base .. params.strong .. "i"}
stems["par_pl"] = {params.base .. params.strong .. "ej"}
stems["ill_pl"] = {params.base .. params.strong .. "eih"}
inflection_type_is(data, 5, "risti", params.strong, params.weak)
process_stems(data, stems, params.a)
end
inflections["paperi"] = function(args, data)
local params = get_params(args, 2)
local i = get_extra_arg(args, data, "i"); if i == "0" then i = "" else i = "i" end
local stems = {}
stems["nom_sg"] = {params.base .. i}
stems["sg"] = {params.base .. "i"}
stems["pl"] = {params.base .. "ei"}
stems["par_pl"] = {params.base .. "eit", params.base .. "ej"}
stems["gen_pl"] = {params.base .. "i", params.base .. "eid", params.base .. "eitt"}
stems["ill_pl"] = {params.base .. "eih"}
inflection_type_is(data, 6, "paperi")
process_stems(data, stems, params.a)
end
inflections["ovi"] = function(args, data)
local params = get_params(args, 4)
local nom_sg = get_extra_arg(args, data, "nom_sg"); if nom_sg == "" then nom_sg = nil end
local wk_pl = params.weak
if mw.ustring.sub(params.base, -1) == "i" and params.strong == "k" and params.weak == "" then
wk_pl = "’"
end
local stems = {}
stems["nom_sg"] = {nom_sg or params.base .. params.strong .. "i"}
stems["sg"] = {params.base .. params.strong .. "e"}
stems["sg_weak"] = {params.base .. params.weak .. "e"}
stems["pl"] = {params.base .. params.strong .. "i"}
stems["pl_weak"] = {params.base .. wk_pl .. "i"}
inflection_type_is(data, 7, "ovi", params.strong, params.weak)
process_stems(data, stems, params.a)
end
inflections["nalle"] = function(args, data)
local params = get_params(args, 4)
local stems = {}
stems["sg"] = {params.base .. params.strong .. "e"}
stems["sg_weak"] = {params.base .. params.weak .. "e"}
stems["pl"] = {params.base .. params.strong .. "ei"}
stems["pl_weak"] = {params.base .. params.weak .. "ei"}
stems["par_pl"] = {params.base .. params.strong .. "ej"}
stems["ill_pl"] = {params.base .. params.strong .. "eih"}
inflection_type_is(data, 8, "nalle", params.strong, params.weak)
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. params.strong .. "ein"}
end
inflections["kala"] = function(args, data)
local params = get_params(args, 4)
local ain = get_extra_arg(args, data, "ain"); if ain == "" then ain = nil end
local wk_sg = params.weak
if wk_sg == "" and mw.ustring.sub(params.base, -2) == params.a .. params.a then
wk_sg = "’"
end
local stems = {}
stems["sg"] = {params.base .. params.strong .. params.a}
stems["sg_weak"] = {params.base .. wk_sg .. params.a}
stems["pl"] = {params.base .. params.strong .. params.o .. "i"}
stems["pl_weak"] = {params.base .. params.weak .. params.o .. "i"}
stems["par_pl"] = {params.base .. params.strong .. params.o .. "j"}
stems["ill_pl"] = {params.base .. params.strong .. params.o .. "ih"}
inflection_type_is(data, 9, "kala", params.strong, params.weak)
process_stems(data, stems, params.a)
local ain_form = params.base .. params.strong .. params.a .. "in"
if ain == "2" then
table.insert(data.forms["gen_pl"], 1, ain_form)
elseif ain == "1" then
table.insert(data.forms["gen_pl"], ain_form)
else
data.forms["gen_pl"].rare = {ain_form}
end
end
inflections["koira"] = function(args, data)
local params = get_params(args, 4)
local nom_sg = get_extra_arg(args, data, "nom_sg"); if nom_sg == "" then nom_sg = nil end
local apo_pl = get_extra_arg(args, data, "apo_pl"); if apo_pl == "" then apo_pl = nil end
local wk_sg = params.weak
local wk_pl = params.weak
if wk_sg == "" and mw.ustring.sub(params.base, -2) == params.a .. params.a then
wk_sg = "’"
end
if wk_pl == "" and mw.ustring.sub(params.base, -1) == "i" then
wk_pl = "’"
end
local stems = {}
stems["nom_sg"] = {nom_sg or params.base .. params.strong .. params.a}
stems["sg"] = {params.base .. params.strong .. params.a}
stems["sg_weak"] = {params.base .. wk_sg .. params.a}
stems["pl"] = {params.base .. params.strong .. (apo_pl and "'" or "") .. "i"}
stems["pl_weak"] = {params.base .. wk_pl .. (apo_pl and "'" or "") .. "i"}
inflection_type_is(data, 10, "koira", params.strong, params.weak)
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. params.strong .. params.a .. "in"}
end
inflections["omena"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["sg"] = {params.base .. params.a}
stems["pl"] = {params.base .. params.o .. "i", params.base .. "i"}
stems["par_pl"] = {params.base .. "i", params.base .. params.o .. "it"}
stems["ill_pl"] = {params.base .. "i", params.base .. params.o .. "ih"}
inflection_type_is(data, 11, "omena")
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. params.o .. "jen", params.base .. params.a .. "in"}
data.forms["par_pl"].rare = {params.base .. params.o .. "j" .. params.a}
end
inflections["kulkija"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["sg"] = {params.base .. params.a}
stems["pl"] = {params.base .. params.o .. "i"}
stems["par_pl"] = {params.base .. params.o .. "it"}
stems["ill_pl"] = {params.base .. params.o .. "ih"}
inflection_type_is(data, 12, "kulkija")
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. params.a .. "in"}
end
inflections["katiska"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["sg"] = {params.base .. params.a}
stems["pl"] = {params.base .. params.o .. "i"}
stems["par_pl"] = {params.base .. params.o .. "it", params.base .. params.o .. "j"}
stems["ill_pl"] = {params.base .. params.o .. "ih"}
inflection_type_is(data, 13, "katiska")
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. params.a .. "in"}
end
inflections["solakka"] = function(args, data)
local params = get_params(args, 4)
local stems = {}
stems["sg"] = {params.base .. params.strong .. params.a}
stems["sg_weak"] = {params.base .. params.weak .. params.a}
stems["pl"] = {params.base .. params.strong .. params.o .. "i"}
stems["pl_weak"] = {params.base .. params.weak .. params.o .. "i"}
stems["par_pl"] = {params.base .. params.weak .. params.o .. "it", params.base .. params.strong .. params.o .. "j"}
stems["ill_pl"] = {params.base .. params.weak .. params.o .. "ih", params.base .. params.strong .. params.o .. "ih"}
inflection_type_is(data, 14, "solakka", params.strong, params.weak)
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. params.strong .. params.a .. "in"}
end
inflections["korkea"] = function(args, data)
local params = get_params(args, 2)
local final = mw.ustring.sub(params.base, -1)
local stems = {}
stems["sg"] = {params.base .. params.a}
stems["par_sg"] = {params.base .. params.a, params.base .. params.a .. "t"}
stems["pl"] = {params.base .. "i"}
stems["par_pl"] = {params.base .. "it"}
stems["ill_pl"] = {params.base .. "isi", params.base .. "ih"}
inflection_type_is(data, 15, "korkea")
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. params.a .. "in"}
end
inflections["vanhempi"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. "mpi"}
stems["sg"] = {params.base .. "mp" .. params.a}
stems["sg_weak"] = {params.base .. "mm" .. params.a}
stems["pl"] = {params.base .. "mpi"}
stems["pl_weak"] = {params.base .. "mmi"}
inflection_type_is(data, 16, "vanhempi", "mp", "mm")
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. "mp" .. params.a .. "in"}
end
inflections["vapaa"] = function(args, data)
local params = get_params(args, 2)
local final = mw.ustring.sub(params.base, -1)
local stems = {}
stems["sg"] = {params.base .. final}
stems["par_sg"] = {params.base .. final .. "t"}
stems["ill_sg"] = {params.base .. final .. "se"}
stems["pl"] = {params.base .. "i"}
stems["par_pl"] = {params.base .. "it"}
stems["ill_pl"] = {params.base .. "isi"}
inflection_type_is(data, 17, "vapaa")
process_stems(data, stems, params.a)
data.forms["ill_pl"].rare = {params.base .. "ihin"}
end
inflections["maa"] = function(args, data)
local params = get_params(args, 2)
local pl_stem = mw.ustring.sub(params.base, 1, -2)
local stems = {}
stems["sg"] = {params.base}
stems["par_sg"] = {params.base .. "t"}
stems["pl"] = {pl_stem .. "i"}
stems["par_pl"] = {pl_stem .. "it"}
stems["ill_pl"] = {pl_stem .. "ih"}
inflection_type_is(data, 18, "maa")
process_stems(data, stems, params.a)
end
inflections["suo"] = function(args, data)
local params = get_params(args, 2)
local final = mw.ustring.sub(params.base, -1)
local stem = mw.ustring.sub(params.base, 1, -3)
local plural
if mw.ustring.sub(stem, -1) == final then
plural = stem .. "-" .. final
elseif mw.ustring.find(stem, "-$") and mw.ustring.sub(stem, -1) ~= final then
plural = mw.ustring.sub(stem, 1, -2) .. final
else
plural = stem .. final
end
local stems = {}
stems["sg"] = {params.base}
stems["par_sg"] = {params.base .. "t"}
stems["ill_sg"] = {params.base .. "h"}
stems["pl"] = {plural .. "i"}
stems["par_pl"] = {plural .. "it"}
stems["ill_pl"] = {plural .. "ih"}
inflection_type_is(data, 19, "suo")
process_stems(data, stems, params.a)
end
inflections["filee"] = function(args, data)
local params = get_params(args, 2)
local nom_sg = get_extra_arg(args, data, "nom_sg"); if nom_sg == "" then nom_sg = nil end
local pl_stem = mw.ustring.sub(params.base, 1, -2)
local stems = {}
stems["nom_sg"] = {nom_sg or params.base}
stems["sg"] = {params.base}
stems["par_sg"] = {params.base .. "t"}
stems["ill_sg"] = {params.base .. "h", params.base .. "se"}
stems["pl"] = {pl_stem .. "i"}
stems["par_pl"] = {pl_stem .. "it"}
stems["ill_pl"] = {pl_stem .. "ih", pl_stem .. "isi"}
inflection_type_is(data, 20, "filee")
process_stems(data, stems, params.a)
end
inflections["rosé"] = function(args, data)
local params = get_params(args, 2)
local ill_sg_vowel = get_extra_arg(args, data, "ill_sg_vowel"); if ill_sg_vowel == "" then error("Parameter \"ill_sg_vowel=\" cannot be empty.") end
local ill_sg_vowel2 = get_extra_arg(args, data, "ill_sg_vowel2"); if ill_sg_vowel2 == "" then error("Parameter \"ill_sg_vowel2=\" cannot be empty.") end
local nom_sg = get_extra_arg(args, data, "nom_sg"); if nom_sg == "" then nom_sg = nil end
local stems = {}
stems["nom_sg"] = {nom_sg or params.base}
stems["sg"] = {params.base}
stems["par_sg"] = {params.base .. "t"}
stems["ill_sg"] = {params.base .. "h"}
stems["pl"] = {params.base .. "i"}
stems["par_pl"] = {params.base .. "it"}
stems["ill_pl"] = {params.base .. "ih"}
inflection_type_is(data, 21, "rosé")
process_stems(data, stems, params.a)
if ill_sg_vowel then
data.forms["ill_sg"] = {params.base .. "h" .. ill_sg_vowel .. "n"}
end
if ill_sg_vowel2 then
table.insert(data.forms["ill_sg"], params.base .. "h" .. ill_sg_vowel2 .. "n")
end
end
inflections["parfait"] = function(args, data)
local params = get_params(args, 2)
local ill_sg_vowel = get_extra_arg(args, data, "ill_sg_vowel"); if ill_sg_vowel == "" then error("Parameter \"ill_sg_vowel=\" is missing.") end
local ill_sg_vowel2 = get_extra_arg(args, data, "ill_sg_vowel2"); if ill_sg_vowel2 == "" then error("Parameter \"ill_sg_vowel2=\" cannot be empty.") end
local stems = {}
stems["nom_sg"] = {params.base}
stems["sg"] = {params.base .. "’"}
stems["par_sg"] = {params.base .. "’t"}
stems["pl"] = {params.base .. "’i"}
stems["par_pl"] = {params.base .. "’it"}
stems["ill_pl"] = {params.base .. "’ih"}
inflection_type_is(data, 22, "parfait")
process_stems(data, stems, params.a)
data.forms["ill_sg"] = {params.base .. "’h" .. ill_sg_vowel .. "n"}
if ill_sg_vowel2 then
table.insert(data.forms["ill_sg"], params.base .. "h" .. ill_sg_vowel2 .. "n")
end
end
inflections["tiili"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. "i"}
stems["sg"] = {params.base .. "e"}
stems["par_sg"] = {params.base .. "t"}
stems["pl"] = {params.base .. "i"}
inflection_type_is(data, 23, "tiili")
process_stems(data, stems, params.a)
end
inflections["uni"] = function(args, data)
local params = get_params(args, 2)
local par_sg_a = get_extra_arg(args, data, "par_sg_a"); if par_sg_a and par_sg_a ~= "a" and par_sg_a ~= "ä" then error("Parameter \"par_sg_a=\" must be \"a\" or \"ä\".") end
local stems = {}
stems["nom_sg"] = {params.base .. "i"}
stems["sg"] = {params.base .. "e"}
stems["par_sg"] = {params.base .. "t"}
stems["pl"] = {params.base .. "i"}
stems["gen_pl"] = {params.base .. "i", params.base .. "t"}
inflection_type_is(data, 24, "uni")
process_stems(data, stems, params.a)
if par_sg_a then
data.forms["par_sg"] = {}
for _, stem in ipairs(stems["par_sg"]) do
table.insert(data.forms["par_sg"], stem .. par_sg_a)
end
end
end
inflections["toimi"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. "mi"}
stems["sg"] = {params.base .. "me"}
stems["par_sg"] = {params.base .. "nt", params.base .. "me"}
stems["pl"] = {params.base .. "mi"}
stems["gen_pl"] = {params.base .. "mi", params.base .. "nt"}
inflection_type_is(data, 25, "toimi")
process_stems(data, stems, params.a)
end
inflections["pieni"] = function(args, data)
local params = get_params(args, 2)
local par_sg_a = get_extra_arg(args, data, "par_sg_a"); if par_sg_a and par_sg_a ~= "a" and par_sg_a ~= "ä" then error("Parameter \"par_sg_a=\" must be \"a\" or \"ä\".") end
local stems = {}
stems["nom_sg"] = {params.base .. "i"}
stems["sg"] = {params.base .. "e"}
stems["par_sg"] = {params.base .. "t"}
stems["pl"] = {params.base .. "i"}
stems["gen_pl"] = {params.base .. "t", params.base .. "i"}
inflection_type_is(data, 26, "pieni")
process_stems(data, stems, params.a)
if par_sg_a then
data.forms["par_sg"] = {}
for _, stem in ipairs(stems["par_sg"]) do
table.insert(data.forms["par_sg"], stem .. par_sg_a)
end
end
end
inflections["käsi"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. "si"}
stems["sg"] = {params.base .. "te"}
stems["sg_weak"] = {params.base .. "de"}
stems["par_sg"] = {params.base .. "tt"}
stems["pl"] = {params.base .. "si"}
inflection_type_is(data, 27, "käsi", "t", "d")
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. "tten"}
end
inflections["kynsi"] = function(args, data)
local params = get_params(args, 2, false, "n")
local cons = mw.ustring.match(params.base, "[lnr]$")
if not cons then error("Stem must end in \"l\", \"n\" or \"r\".") end
local stems = {}
stems["nom_sg"] = {params.base .. "si"}
stems["sg"] = {params.base .. "te"}
stems["sg_weak"] = {params.base .. cons .. "e"}
stems["par_sg"] = {params.base .. "tt"}
stems["pl"] = {params.base .. "si"}
inflection_type_is(data, 28, "kynsi", cons .. "t", cons .. cons)
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. "tten"}
end
inflections["lapsi"] = function(args, data)
local params = get_params(args, 2, false, "p")
if not mw.ustring.match(params.base, "[kp]$") then error("Stem must end in \"k\" or \"p\".") end
local syncopated_stem = mw.ustring.sub(params.base, 1, -2)
local stems = {}
stems["nom_sg"] = {params.base .. "si"}
stems["sg"] = {params.base .. "se"}
stems["par_sg"] = {syncopated_stem .. "st"}
stems["pl"] = {params.base .. "si"}
stems["gen_pl"] = {params.base .. "si", syncopated_stem .. "st"}
inflection_type_is(data, 29, "lapsi")
process_stems(data, stems, params.a)
end
inflections["veitsi"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. "tsi"}
stems["sg"] = {params.base .. "tse"}
stems["par_sg"] = {params.base .. "st"}
stems["pl"] = {params.base .. "tsi"}
inflection_type_is(data, 30, "veitsi")
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. "sten"}
end
inflections["kaksi"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. "ksi"}
stems["sg"] = {params.base .. "hte"}
stems["sg_weak"] = {params.base .. "hde"}
stems["par_sg"] = {params.base .. "ht"}
stems["pl"] = {params.base .. "ksi"}
inflection_type_is(data, 31, "kaksi", "t", "d")
process_stems(data, stems, params.a)
end
inflections["sisar"] = function(args, data)
local params = get_params(args, 5, true)
local nom_sg = get_extra_arg(args, data, "nom_sg"); if nom_sg == "" then nom_sg = nil end
local stems = {}
stems["nom_sg"] = {nom_sg or params.base .. params.weak .. params.final}
stems["sg"] = {params.base .. params.strong .. params.final .. "e"}
stems["par_sg"] = {params.base .. params.weak .. params.final .. "t"}
stems["pl"] = {params.base .. params.strong .. params.final .. "i"}
stems["gen_pl"] = {params.base .. params.strong .. params.final .. "i", params.base .. params.weak .. params.final .. "t"}
inflection_type_is(data, 32, "sisar", params.strong, params.weak)
process_stems(data, stems, params.a)
end
inflections["kytkin"] = function(args, data)
local params = get_params(args, 5, true)
local stems = {}
stems["nom_sg"] = {params.base .. params.weak .. params.final .. "n"}
stems["sg"] = {params.base .. params.strong .. params.final .. "me"}
stems["par_sg"] = {params.base .. params.weak .. params.final .. "nt"}
stems["pl"] = {params.base .. params.strong .. params.final .. "mi"}
stems["gen_pl"] = {params.base .. params.strong .. params.final .. "mi", params.base .. params.weak .. params.final .. "nt"}
inflection_type_is(data, 33, "kytkin", params.strong, params.weak)
process_stems(data, stems, params.a)
end
inflections["onneton"] = function(args, data)
local no_gradation = get_extra_arg(args, data, "no_tt") == "1"
local strong
if no_gradation then
strong = "t"
else
strong = "tt"
end
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. "t" .. params.o .. "n"}
stems["sg"] = {params.base .. strong .. params.o .. "m" .. params.a}
stems["par_sg"] = {params.base .. "t" .. params.o .. "nt"}
stems["pl"] = {params.base .. strong .. params.o .. "mi"}
inflection_type_is(data, 34, "onneton", strong, "t")
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. "t" .. params.o .. "nten"}
end
inflections["lämmin"] = function(args, data)
local params = get_params(args, 5, true)
local stems = {}
stems["nom_sg"] = {params.base .. params.weak .. params.final .. "n"}
stems["sg"] = {params.base .. params.strong .. params.final .. "m" .. params.a}
stems["par_sg"] = {params.base .. params.weak .. params.final .. "nt"}
stems["pl"] = {params.base .. params.strong .. params.final .. "mi"}
inflection_type_is(data, 35, "lämmin", params.strong, params.weak)
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. params.strong .. params.final .. "m" .. params.a .. "in"}
end
inflections["sisin"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. "in"}
stems["sg"] = {params.base .. "imp" .. params.a}
stems["sg_weak"] = {params.base .. "imm" .. params.a}
stems["par_sg"] = {params.base .. "int"}
stems["pl"] = {params.base .. "impi"}
stems["pl_weak"] = {params.base .. "immi"}
stems["gen_pl"] = {params.base .. "impi", params.base .. "int"}
inflection_type_is(data, 36, "sisin", "mp", "mm")
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. "imp" .. params.a .. "in"}
end
inflections["vasen"] = function(args, data)
local params = get_params(args, 1)
params.base = params.base .. "vase"
params.a = "a"
local stems = {}
stems["nom_sg"] = {params.base .. "n"}
stems["sg"] = {params.base .. "mp" .. params.a}
stems["sg_weak"] = {params.base .. "mm" .. params.a}
stems["par_sg"] = {params.base .. "nt", params.base .. "mp" .. params.a}
stems["pl"] = {params.base .. "mpi"}
stems["pl_weak"] = {params.base .. "mmi"}
stems["gen_pl"] = {params.base .. "mpi", params.base .. "nt"}
inflection_type_is(data, 37, "vasen", "mp", "mm")
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. "mp" .. params.a .. "in"}
end
inflections["nainen"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. "nen"}
stems["sg"] = {params.base .. "se"}
stems["par_sg"] = {params.base .. "st"}
stems["pl"] = {params.base .. "si"}
stems["gen_pl"] = {params.base .. "st", params.base .. "si"}
inflection_type_is(data, 38, "nainen")
process_stems(data, stems, params.a)
end
inflections["vastaus"] = function(args, data)
local params = get_params(args, 2)
local nom_sg = get_extra_arg(args, data, "nom_sg"); if nom_sg == "" then nom_sg = nil end
local stems = {}
stems["nom_sg"] = {nom_sg or params.base .. "s"}
stems["sg"] = {params.base .. "kse"}
stems["par_sg"] = {params.base .. "st"}
stems["pl"] = {params.base .. "ksi"}
stems["gen_pl"] = {params.base .. "st", params.base .. "ksi"}
inflection_type_is(data, 39, "vastaus")
process_stems(data, stems, params.a)
end
inflections["kalleus"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. "s"}
stems["sg"] = {params.base .. "te"}
stems["sg_weak"] = {params.base .. "de"}
stems["par_sg"] = {params.base .. "tt"}
stems["pl"] = {params.base .. "ksi"}
inflection_type_is(data, 40, "kalleus", "t", "d")
process_stems(data, stems, params.a)
end
inflections["vieras"] = function(args, data)
local params = get_params(args, 5, true)
local nom_sg = get_extra_arg(args, data, "nom_sg"); if nom_sg == "" then nom_sg = nil end
local stems = {}
stems["nom_sg"] = {nom_sg or (params.base .. params.weak .. params.final .. "s")}
stems["sg"] = {params.base .. params.strong .. params.final .. params.final}
stems["par_sg"] = {params.base .. params.weak .. params.final .. "st"}
stems["ill_sg"] = {params.base .. params.strong .. params.final .. params.final .. "se"}
stems["pl"] = {params.base .. params.strong .. params.final .. "i"}
stems["par_pl"] = {params.base .. params.strong .. params.final .. "it"}
stems["ill_pl"] = {params.base .. params.strong .. params.final .. "isi"}
inflection_type_is(data, 41, "vieras", params.strong, params.weak)
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. params.weak .. params.final .. "sten"}
data.forms["ill_pl"].rare = {params.base .. params.strong .. params.final .. "ihin"}
end
inflections["mies"] = function(args, data)
local params = get_params(args, 1)
local cap = get_extra_arg(args, data, "cap"); if cap == "" then nom_sg = nil end
params.base = params.base .. (cap and "Mie" or "mie")
params.a = "ä"
local stems = {}
stems["nom_sg"] = {params.base .. "s"}
stems["sg"] = {params.base .. "he"}
stems["par_sg"] = {params.base .. "st"}
stems["pl"] = {params.base .. "hi"}
stems["gen_pl"] = {params.base .. "st", params.base .. "hi"}
inflection_type_is(data, 42, "mies")
process_stems(data, stems, params.a)
end
inflections["ohut"] = function(args, data)
local params = get_params(args, 5, true)
local stems = {}
stems["nom_sg"] = {params.base .. params.weak .. params.final .. "t"}
stems["sg"] = {params.base .. params.strong .. params.final .. "e"}
stems["par_sg"] = {params.base .. params.weak .. params.final .. "tt"}
stems["pl"] = {params.base .. params.strong .. params.final .. "i"}
stems["par_pl"] = {params.base .. params.strong .. params.final .. "it"}
stems["ill_pl"] = {params.base .. params.strong .. params.final .. "isi", params.base .. params.strong .. params.final .. "ih"}
inflection_type_is(data, 43, "ohut", params.strong, params.weak)
process_stems(data, stems, params.a)
end
inflections["kevät"] = function(args, data)
local params = get_params(args, 4, true)
local vowel = params.a
local stems = {}
stems["nom_sg"] = {params.base .. params.weak .. vowel .. "t"}
stems["sg"] = {params.base .. params.strong .. vowel .. vowel}
stems["par_sg"] = {params.base .. params.weak .. vowel .. "tt"}
stems["ill_sg"] = {params.base .. params.strong .. vowel .. vowel .. "se"}
stems["pl"] = {params.base .. params.strong .. vowel .. "i"}
stems["par_pl"] = {params.base .. params.strong .. vowel .. "it"}
stems["ill_pl"] = {params.base .. params.strong .. vowel .. "isi"}
inflection_type_is(data, 44, "kevät", params.strong, params.weak)
process_stems(data, stems, params.a)
data.forms["ill_pl"].rare = {params.base .. params.strong .. vowel .. "ihin"}
end
inflections["kahdeksas"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. "s"}
stems["sg"] = {params.base .. "nte"}
stems["sg_weak"] = {params.base .. "nne"}
stems["par_sg"] = {params.base .. "tt"}
stems["pl"] = {params.base .. "nsi"}
inflection_type_is(data, 45, "kahdeksas", "nt", "nn")
process_stems(data, stems, params.a)
end
inflections["tuhat"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. "t"}
stems["sg"] = {params.base .. "nte"}
stems["sg_weak"] = {params.base .. "nne"}
stems["par_sg"] = {params.base .. "tt"}
stems["pl"] = {params.base .. "nsi"}
inflection_type_is(data, 46, "tuhat", "nt", "nn")
process_stems(data, stems, params.a)
data.forms["gen_pl"].rare = {params.base .. "nten"}
end
inflections["kuollut"] = function(args, data)
local params = get_params(args, 2)
local stems = {}
stems["nom_sg"] = {params.base .. params.u .. "t"}
stems["sg"] = {params.base .. "ee"}
stems["par_sg"] = {params.base .. params.u .. "tt"}
stems["ill_sg"] = {params.base .. "eese"}
stems["pl"] = {params.base .. "ei"}
stems["par_pl"] = {params.base .. "eit"}
stems["ill_pl"] = {params.base .. "eisi", params.base .. "eih"}
inflection_type_is(data, 47, "kuollut")
process_stems(data, stems, params.a)
end
inflections["hame"] = function(args, data)
local params = get_params(args, 4, true)
local stem_vowel = get_extra_arg(args, data, "stem_vowel"); if stem_vowel == "" then stem_vowel = nil end
stem_vowel = stem_vowel or "e"
local nom_sg = get_extra_arg(args, data, "nom_sg"); if nom_sg == "" then nom_sg = nil end
local stems = {}
stems["nom_sg"] = {nom_sg or (params.base .. params.weak .. stem_vowel)}
stems["sg"] = {params.base .. params.strong .. stem_vowel .. stem_vowel}
stems["par_sg"] = {params.base .. params.weak .. stem_vowel .. "tt"}
stems["ill_sg"] = {params.base .. params.strong .. stem_vowel .. stem_vowel .. "se"}
stems["pl"] = {params.base .. params.strong .. stem_vowel .. "i"}
stems["par_pl"] = {params.base .. params.strong .. stem_vowel .. "it"}
stems["ill_pl"] = {params.base .. params.strong .. stem_vowel .. "isi", params.base .. params.strong .. stem_vowel .. "ih"}
inflection_type_is(data, 48, "hame", params.strong, params.weak)
process_stems(data, stems, params.a)
end
inflections["askel"] = function(args, data)
local params = get_params(args, 5, true)
local prefer_hame = get_extra_arg(args, data, "e") == "1"
local stems_sisar = {}
stems_sisar["sg"] = {params.base .. params.strong .. params.final .. "e"}
stems_sisar["nom_sg"] = {params.base .. params.weak .. params.final}
stems_sisar["par_sg"] = {params.base .. params.weak .. params.final .. "t"}
stems_sisar["ill_sg"] = {params.base .. params.strong .. params.final .. "e"}
stems_sisar["pl"] = {params.base .. params.strong .. params.final .. "i"}
stems_sisar["gen_pl"] = {params.base .. params.strong .. params.final .. "i", params.base .. params.weak .. params.final .. "t"}
stems_sisar["par_pl"] = {params.base .. params.strong .. params.final .. "i"}
stems_sisar["ill_pl"] = {params.base .. params.strong .. params.final .. "i"}
local stems_hame = {}
stems_hame["sg"] = {params.base .. params.strong .. params.final .. "ee"}
stems_hame["nom_sg"] = {params.base .. params.strong .. params.final .. "e"}
stems_hame["par_sg"] = {params.base .. params.strong .. params.final .. "ett"}
stems_hame["ill_sg"] = {params.base .. params.strong .. params.final .. "eese"}
stems_hame["pl"] = {params.base .. params.strong .. params.final .. "ei"}
stems_hame["gen_pl"] = {params.base .. params.strong .. params.final .. "eid", params.base .. params.strong .. params.final .. "eitt"}
stems_hame["par_pl"] = {params.base .. params.strong .. params.final .. "eit"}
stems_hame["ill_pl"] = {params.base .. params.strong .. params.final .. "eisi", params.base .. params.strong .. params.final .. "eih"}
local stems = {}
if prefer_hame then
feed_list(stems, stems_hame)
feed_list(stems, stems_sisar)
else
feed_list(stems, stems_sisar)
feed_list(stems, stems_hame)
end
inflection_type_is(data, 49, "askel", params.strong, params.weak)
process_stems(data, stems, params.a)
end
-- Helper functions
-- joins data.words[...].forms to data.forms
function export.join_words(data, sep_supplier)
local reorganized = {}
local classes = {}
-- reorganize from words[n].forms[case](.rare) to forms[case],words[n](.rare)
for windex, word in ipairs(data.words) do
table.insert(classes, word.class)
for case, forms in pairs(word.forms) do
if reorganized[case] == nil then
reorganized[case] = {}
end
reorganized[case][windex] = {}
for _, form in ipairs(forms) do
table.insert(reorganized[case][windex], form)
end
if word.forms[case].rare then
reorganized[case][windex].rare = {}
for _, form in ipairs(word.forms[case].rare) do
table.insert(reorganized[case][windex].rare, form)
end
end
end
end
-- merge the forms with a Cartesian product to produce all possible combinations
data.forms = {}
for case, words in pairs(reorganized) do
data.forms[case] = forms_cart_product(words, case, sep_supplier, classes)
end
if #data.words <= 1 then
-- use title and categories of the sole word if there is only one
data.title = data.words[1].title
data.categories = data.words[1].categories
else
-- if there are multiple words, force nuoripari type
data.title = make_kotus_title(51, "nuoripari")
data.categories = {"Finnish nuoripari-type nominals"}
end
data.words = nil
end
local function cleanup_suffix(suffix)
if suffix and mw.ustring.find(suffix, "_") then
return mw.ustring.gsub(suffix, "_", " ")
else
return suffix
end
end
-- computes the Cartesian product of tables
function cart_product(words, depth)
depth = depth or 1
local prod = {}
for _, val in ipairs(words[depth]) do
if depth < #words then
-- go over the next list
for _, res in ipairs(cart_product(words, depth + 1)) do
table.insert(prod, { val, unpack(res) })
end
else
-- end of list, simply return the original
table.insert(prod, { val })
end
end
return prod
end
local function supplied_concat(list, sep_supplier)
local result = ""
local n = #list
if n >= 1 then
for i = 1, n - 1 do
local v = mw.ustring.match(list[i], "^[aeiouyäö]")
if v and mw.ustring.find(result, v .. "$") then
result = result .. "-"
end
result = result .. list[i] .. sep_supplier(i)
end
local v = mw.ustring.match(list[n], "^[aeiouyäö]")
if v and mw.ustring.find(result, v .. "$") then
result = result .. "-"
end
result = result .. list[n]
end
return result
end
-- computes the Cartesian product of tables, also concats
function cart_product_concat(words, sep_supplier)
local res = {}
for _, combination in ipairs(cart_product(words)) do
table.insert(res, supplied_concat(combination, sep_supplier))
end
return res
end
-- returns a bit mask (!) or nil
function get_rhyming_pattern(word, case, class)
if class == "askel" then
return nil
end
if case == "gen_pl" then
if mw.ustring.match(word, "tten$") then
return 2
elseif mw.ustring.match(word, "ten$") then
return 3
else
return 1
end
elseif case == "ill_sg" then
if mw.ustring.match(word, "seen$") then
return 1
elseif mw.ustring.match(word, "hen$") then
return 2
end
elseif case == "ill_pl" then
if mw.ustring.match(word, "siin$") then
return 1
elseif mw.ustring.match(word, "hin$") then
return 2
end
end
return nil -- not applicable
end
function is_nonrhyming(form, case, classes)
local expected = m_bit32.bnot(0) -- -1
for i, word in ipairs(form) do
local got = get_rhyming_pattern(word, case, classes[i])
if got then
expected = m_bit32.band(expected, got)
end
if expected == 0 then
return true
end
end
return false
end
-- computes the Cartesian product of tables, also concats
-- returns non-rhyming combinations as rare
function cart_product_concat_nonrhyming_rare(words, case, sep_supplier, classes)
local res = {}
local rare = {}
local multichoice = 0
local allow_pruning = false
for _, position in ipairs(words) do
if #position > 1 then
multichoice = multichoice + 1
end
end
allow_pruning = multichoice > 1
for _, combination in ipairs(cart_product(words)) do
local item = supplied_concat(combination, sep_supplier)
if is_nonrhyming(combination, case, classes) then
table.insert(rare, item)
else
table.insert(res, item)
end
end
if #res < 1 then
rare.rare = {}
return rare
end
res.rare = rare
return res
end
-- converts a list of words to extract the rare forms for ipairs
-- the number is interpreted bit-by-bit to decide which combination
-- to choose
function prepare_rare_tables(words, code)
local result = {}
for _, forms in ipairs(words) do
-- replace with rare if bit is 1
if m_bit32.band(code, 1) == 1 then
table.insert(result, forms.rare or {})
else
table.insert(result, forms)
end
-- shift right to test next bit
code = m_bit32.rshift(code, 1)
end
return result
end
-- copies all entries of source and inserts them to target
function merge_table(target, source)
for _, value in ipairs(source) do
table.insert(target, value)
end
end
function merge_table_rare(target, source)
for _, value in ipairs(source) do
table.insert(target, value)
end
target.rare = source.rare
end
-- the Cartesian product of possible forms
function forms_cart_product(words, case, sep_supplier, classes)
local result = {}
result.rare = {}
m_bit32 = require("bit32")
-- merge possible non-rare forms
merge_table_rare(result, cart_product_concat_nonrhyming_rare(words, case, sep_supplier, classes))
-- merge possible rare forms
-- for example, with two words:
-- 1 = rare A, common B
-- 2 = common A, rare B
-- 3 = rare A, rare B
-- (2 ^ #words) - 1 == m_bit32.lshift(1,#words)-1
-- (prepare_rare_tables actually takes out the rare forms)
for i = 1,m_bit32.lshift(1,#words)-1 do
merge_table(result.rare, cart_product_concat(prepare_rare_tables(words, i), sep_supplier))
end
-- if no rare forms, remove the table completely
if #result.rare < 1 then
result.rare = nil
end
return result
end
function make_word_possessive(args, data, poss, always_add)
local pos = get_extra_arg(args, data, "pos"); if not pos or pos == "" then pos = "noun" end
local par_nom_sg = get_extra_arg(args, data, "par_nom_sg") == "1"
-- "no possessive forms exist" sentinel value
if poss == "-" then
return data.forms
end
if always_add or pos == "noun" then
-- add possessive suffix
if poss == "3" or poss == "3p" then
poss = "3s" -- 3rd person forms are identical
end
if not poss_forms[poss] then
error("Invalid poss value: '" .. p .. "'")
end
return make_poss_with_suffix(data.forms, data.stems, poss_forms[poss], "", poss_alt[poss], par_nom_sg)
end
return data.forms
end
function postprocess_word(args, data, gdata, always_add)
local pos = get_extra_arg(args, data, "pos"); if not pos or pos == "" then pos = "noun" end
local alwayspl = get_extra_arg(args, data, "alwayspl"); if alwayspl == "" then alwayspl = nil end
if gdata.poss then
data.forms = make_word_possessive(args, data, gdata.poss, always_add)
elseif pos == "noun" and data.forms["com_pl"] then
-- Add the possessive suffix to the comitative plural, if the word is a noun
for key, subform in ipairs(data.forms["com_pl"]) do
data.forms["com_pl"][key] = subform .. "en"
end
gdata.tagged_com_pl = true
end
if get_extra_arg(args, data, "gen_nom_sg") == "1" then
data.forms["nom_sg"] = data.forms["gen_sg"]
elseif get_extra_arg(args, data, "par_nom_sg") == "1" then
data.forms["nom_sg"] = data.forms["par_sg"]
end
if gdata.poss then
data.forms["ins_pl"] = nil
end
if alwayspl then -- [[Saint Vincent ja Grenadiinit]]
for k, v in pairs(data.forms) do
local k_sg = k:gsub("_pl", "_sg")
if data.forms[k_sg] then
data.forms[k_sg] = data.forms[k]
end
end
end
end
function postprocess(args, data)
local pos = args["pos"]; if not pos or pos == "" then pos = "noun" end
local nosg = args["nosg"]; if nosg == "" then nosg = nil end
local nopl = args["nopl"]; if nopl == "" then nopl = nil end
local n = args["n"]; if n == "" then n = nil end
local suffix = cleanup_suffix(args["suffix"]); if suffix == "" then suffix = nil end
local appendix = args["appendix"]; if appendix == "" then appendix = nil end
local has_ins_sg = args["has_ins_sg"]; if has_ins_sg == "" then has_ins_sg = nil end
local has_no_nom = args["has_no_nom"]; if has_no_nom == "" then has_no_nom = nil end
-- Add the possessive suffix to the comitative plural, if the word is a noun
-- now done per word; see postprocess_word
if nosg or n == "pl" then
table.insert(data.categories, "Finnish pluralia tantum")
end
-- TODO: This says "nouns", but this module is also used for adjectives!
if nopl or n == "sg" then
table.insert(data.categories, "Danh từ tiếng Phần Lan không đếm được")
end
if n == "csg" then -- "chiefly singular"
data.rare_plural = true
end
if not has_ins_sg then
data.forms["ins_sg"] = nil
end
for key, form in pairs(data.forms) do
-- Add suffix to forms
for i, subform in ipairs(form) do
subform = subform .. (suffix or "")
form[i] = subform
end
if form.rare then
for i, subform in ipairs(form.rare) do
subform = subform .. (suffix or "")
form.rare[i] = subform
end
end
-- Do not show singular or plural forms for nominals that don't have them
if ((nosg or n == "pl") and key:find("_sg$")) or ((nopl or n == "sg") and key:find("_pl$")) then
form = nil
end
data.forms[key] = form
end
-- Check if the lemma form matches the page name
local lemma = data.forms[(nosg or n == "pl") and "nom_pl" or "nom_sg"][1]
if not appendix and lemma ~= data.pagename and not data.poss then
--error("The lemma " .. lemma .. " does not match the page title. Check the parameters!")
mw.addWarning("<i>Please check the fi-decl-... parameters!</i>")
table.insert(data.categories, "Finnish entries with inflection not matching pagename")
end
data.is_appendix = appendix
if has_no_nom then
data.forms["nom_sg"] = nil
data.forms["nom_pl"] = nil
end
end
-- Make the table
function make_table(data, preview, title_override, collapse_class_override, accel_class_prefix)
local rare_plural = data.rare_plural
local note = rare_plural and "Plural forms of this word are not commonly used, but might be found in figurative uses, in some set phrases or in colloquial language." or nil
local function show_form(forms, code, no_rare)
if code:find("^com_") and not data.poss and data.tagged_com_pl then
if code:find("_pl$") then return "" end
return ' colspan="2" | \'\'Xem dạng sở hữu phía dưới.\'\''
end
local form = forms[code]
if not form then
return "—"
elseif type(form) ~= "table" then
error("a non-table value was given in the list of inflected forms.")
end
local ret = {}
local accel
if rare_plural and code:find("_pl$") then
-- plural is marginal
for key, subform in ipairs(form) do
table.insert(ret, "(''" .. make_link(subform) .. "'')")
end
if not no_rare and form.rare then
for key, subform in ipairs(form.rare) do
table.insert(ret, "(''" .. make_link(subform) .. "''<sup>rare</sup>)")
end
end
return table.concat(ret, "<br/>")
end
-- See [[Module talk:fi-nominals]].
if code == "nom_sg" and not data.poss then
accel = nil
elseif code == "nom_pl" then
accel = "nom//acc|p"
else
accel = code:gsub("%f[^_](%a%a)$", {sg = "s", pl = "p"}):gsub("ins", "ist"):gsub("_", "|")
end
if accel_class_prefix and accel then
accel = accel_class_prefix .. accel
end
for key, subform in ipairs(form) do
table.insert(ret, make_link(subform, accel))
end
if not no_rare and form.rare then
if accel then
accel = 'rare-' .. accel
end
for key, subform in ipairs(form.rare) do
table.insert(ret, make_link(subform, accel) .. "<sup>hiếm</sup>")
end
end
return table.concat(ret, "<br/>")
end
local function repl(param)
if param == "title" then
if title_override then return title_override end
return "[[Phụ lục:Biến cách danh từ tiếng Phần Lan|Biến tố]] của " .. (data.is_appendix and make_link(data.pagename) or tag_term(data.pagename)) .. ( data.title and " (" .. data.title .. ")" or "")
elseif param == "maybenote" then
if note then
return [=[
|- class="vsHide"
| colspan="4" style="width:100px" | ]=] .. note .. "\n"
else
return ""
end
else
local param2 = mw.ustring.match(param, "^(.-):c$")
if param2 then
return show_form(data.forms, param2, true)
else
return show_form(data.forms, param)
end
end
end
if preview then
preview = [=[
|- class="vsShow"
! class="case-column" colspan="2" | [[nominative|nom.]]
| class="number-column" | {{{nom_sg:c}}}
| class="number-column" | {{{nom_pl:c}}}
|- class="vsShow"
! colspan="2" | [[genitive|gen.]]
| {{{gen_sg:c}}}
| {{{gen_pl:c}}}
|- class="vsShow"
! colspan="2" | [[partitive|par.]]
| {{{par_sg:c}}}
| {{{par_pl:c}}}
|- class="vsShow"
! colspan="2" | [[illative|ill.]]
| {{{ill_sg:c}}}
| {{{ill_pl:c}}}
]=]
else
preview = ""
end
local wikicode = [=[
{| class="inflection-table fi-decl vsSwitcher" data-toggle-category="]=] .. (collapse_class_override or "biến cách") .. [=["
|-
! class="vsToggleElement" colspan="4" | {{{title}}}
]=] .. preview .. [=[
|- class="vsHide"
! class="case-column" colspan="2" |
! class="number-column" | số ít
! class="number-column" | số nhiều
|- class="vsHide"
! colspan="2" | [[nominative|nom.]]
| {{{nom_sg}}}
| {{{nom_pl}}}
|- class="vsHide"
! rowspan="2" | [[accusative|acc.]]
! [[nominative|nom.]]<sup title="The nominative accusative is used, for example, as the object of certain passives and imperatives."></sup>
| {{{nom_sg}}}
| rowspan="2" | {{{nom_pl}}}
|- class="vsHide"
! [[genitive|gen.]]
| {{{gen_sg}}}
|- class="vsHide"
! colspan="2" | [[genitive|gen.]]
| {{{gen_sg}}}
| {{{gen_pl}}}
|- class="vsHide"
! colspan="2" | [[partitive|par.]]
| {{{par_sg}}}
| {{{par_pl}}}
|- class="vsHide"
! colspan="2" | [[inessive|ine.]]
| {{{ine_sg}}}
| {{{ine_pl}}}
|- class="vsHide"
! colspan="2" | [[elative|ela.]]
| {{{ela_sg}}}
| {{{ela_pl}}}
|- class="vsHide"
! colspan="2" | [[illative|ill.]]
| {{{ill_sg}}}
| {{{ill_pl}}}
|- class="vsHide"
! colspan="2" | [[adessive|ade.]]
| {{{ade_sg}}}
| {{{ade_pl}}}
|- class="vsHide"
! colspan="2" | [[ablative|abl.]]
| {{{abl_sg}}}
| {{{abl_pl}}}
|- class="vsHide"
! colspan="2" | [[allative|all.]]
| {{{all_sg}}}
| {{{all_pl}}}
|- class="vsHide"
! colspan="2" | [[essive|ess.]]
| {{{ess_sg}}}
| {{{ess_pl}}}
|- class="vsHide"
! colspan="2" | [[translative|tra.]]
| {{{tra_sg}}}
| {{{tra_pl}}}
|- class="vsHide"
! colspan="2" | [[abessive|abe.]]
| {{{abe_sg}}}
| {{{abe_pl}}}
|- class="vsHide"
! colspan="2" | [[instructive|ins.]]
| {{{ins_sg}}}
| {{{ins_pl}}}
|- class="vsHide"
! colspan="2" | [[comitative|com.]]
| {{{com_sg}}}
| {{{com_pl}}}
{{{maybenote}}}|}]=]
return mw.ustring.gsub(wikicode, "{{{([a-z0-9_:]+)}}}", repl)
end
------------------------------------------
-- POSSESSIVE FORM GENERATION & DISPLAY --
------------------------------------------
local function prepare_possessive_list(forms)
local res = {}
for _, v in ipairs(forms) do
table.insert(res, v)
end
if forms["rare"] then
for _, v in ipairs(forms["rare"]) do
table.insert(res, v)
res[v] = "rare"
end
end
return res
end
local function wrap_rare_forms(forms)
local newforms = {}
for case, subforms in pairs(forms) do
local common = {}
local rare = {}
for _, v in ipairs(subforms) do
if subforms[v] == "rare" then
table.insert(rare, v)
else
table.insert(common, v)
end
end
common.rare = rare
newforms[case] = common
end
return newforms
end
local function make_possessives_from_stems(stems, suffix, extra_suffix)
local pforms = {}
for _, stem in pairs(stems) do
table.insert(pforms, stem .. suffix .. extra_suffix)
end
return pforms
end
function make_poss_with_suffix(forms, stems, poss_suffix, extra_suffix, allow_alt, par_nom_sg)
local result = {}
local par_sg_a = false
if poss_suffix:find("a") and mw.ustring.sub(forms["ine_sg"][1], -1) == "ä" then
poss_suffix = mw.ustring.gsub(poss_suffix, "a", "ä")
end
if mw.ustring.sub(forms["ine_sg"][1], -1) ~= mw.ustring.sub(forms["par_sg"][1], -1) then
par_sg_a = true
end
for k, v in pairs(forms_alt_ok) do
if forms[k] then
local suffix = poss_suffix
if k == "par_sg" and par_sg_a and mw.ustring.find(suffix, "ä$") then
suffix = mw.ustring.gsub(poss_suffix, "ä", "a")
end
result[k] = {}
if k == "par_sg" and allow_alt then
-- par_sg is a bit of an exception: it allows
-- alt form if it doesn't end in two "aa"/"ää"
local prepared = prepare_possessive_list(forms[k])
for _, form in ipairs(prepared) do
local modform = form
if mw.ustring.sub(modform, -2, -2) ~= mw.ustring.sub(modform, -1) then
local final = modform .. mw.ustring.sub(modform, -1) .. "n"
table.insert(result[k], final)
result[k][final] = prepared[form]
end
end
elseif forms_alt_ok[k] and allow_alt then
local prepared = prepare_possessive_list(forms[k])
for _, form in ipairs(prepared) do
local modform = form
if k == "tra_sg" or k == "tra_pl" then
modform = mw.ustring.sub(form, 1, -2) .. "e"
end
local final = modform .. mw.ustring.sub(modform, -1) .. "n"
table.insert(result[k], final)
result[k][final] = prepared[form]
end
end
if k == "gen_sg" or k == "ins_sg" then
result[k] = make_possessives_from_stems(stems["sg"], suffix, extra_suffix)
elseif k == "ins_pl" then
result[k] = make_possessives_from_stems(stems["pl"], suffix, extra_suffix)
elseif forms_gen_ok[k] then
local prepared = prepare_possessive_list(forms[k])
for _, form in ipairs(prepared) do
local tmp = form
tmp = mw.ustring.sub(tmp, 1, -2)
local final = tmp .. suffix .. extra_suffix
table.insert(result[k], final)
result[k][final] = prepared[form]
end
else
local prepared = prepare_possessive_list(forms[k])
for _, form in ipairs(prepared) do
local modform = form
if k == "tra_sg" or k == "tra_pl" then
modform = mw.ustring.sub(form, 1, -2) .. "e"
end
local final = modform .. suffix .. extra_suffix
table.insert(result[k], final)
result[k][final] = prepared[form]
end
end
end
end
-- nominative forms are (usually) identical to genitive singular
result["nom_sg"] = result[par_nom_sg and "par_sg" or "gen_sg"]
result["nom_pl"] = result["gen_sg"]
return wrap_rare_forms(result)
end
local function serialize_args(args)
local items = {}
local entries = {}
local max_number = 0
for key, value in pairs(args) do
if type(key) == "number" and key > 0 and key == math.floor(key) then
items[key] = value
max_number = math.max(key, max_number)
else
table.insert(entries, key .. "=" .. value)
end
end
for i = 1,max_number,1 do
items[i] = items[i] or ""
end
-- entries before items
for i, v in ipairs(entries) do
table.insert(items, i, v)
end
return table.concat(items, "|")
end
local poss_headings = {
["1s"] = "ngôi 1 số ít", ["2s"] = "ngôi 2 số ít",
["1p"] = "ngôi 1 số nhiều", ["2p"] = "ngôi 2 số nhiều",
["3"] = "ngôi 3",
}
local poss_accel = {
["1s"] = "1|s", ["2s"] = "2|s", ["1p"] = "1|p", ["2p"] = "2|p", ["3"] = "3"
}
function make_possessive_table(pagename, args, pos, infl_title, get_forms)
local note = nil
if args["noposs"] then
return ""
elseif pos == "adj" then
note = not args["hideadjnote"] and "'''[[Phụ lục:Hậu tố sở hữu trong tiếng Phần Lan#Tính từ|Hiếm]]'''. Chỉ được dùng với [[substantive adjective|danh tính từ]]." or ""
elseif pos ~= "noun" then
return ""
end
return "\n" .. make_possessive_table_internal(pagename, args, infl_title, note, get_forms)
end
function make_possessive_table_internal(pagename, args, infl_title, note, get_forms)
local function show_subtable(code)
return make_table(get_forms(code), false, "chủ sở hữu " .. poss_headings[code], "biến tố sở hữu", poss_accel[code] .. "|poss|form|of|")
end
local function repl(param)
if param == "lemma" then
return tag_term(pagename)
elseif param == "info" then
return " <small>(" .. infl_title .. ")</small>"
elseif param == "maybenote" then
if note then
return [=[
|- class="vsHide"
| colspan="3" | ]=] .. note .. "\n"
else
return ""
end
else
return show_subtable(param)
end
end
local wikicode = [=[
{| class="inflection-table vsSwitcher fi-decl-poss" data-toggle-category="biến tố sở hữu" style="text-align: center;" cellspacing="1" cellpadding="2"
|- class="fi-decl-poss-header"
! class="vsToggleElement" style="min-width: 30em; text-align: left;" colspan="3" | [[Phụ lục:Hậu tố sở hữu trong tiếng Phần Lan|Dạng sở hữu]] của {{{lemma}}}{{{info}}}
{{{maybenote}}}|- class="vsHide"
|
{{{1s}}}
{{{2s}}}
{{{1p}}}
{{{2p}}}
{{{3}}}
|}]=]
return mw.ustring.gsub(wikicode, "{{{([a-z0-9_:]+)}}}", repl)
end
export.inflections = inflections
return export