local m_utilities = require("Module:utilities")
local m_links = require("Module:links")
local export = {}
local lang = require("Module:languages").getByCode("sv")
local vowel = "[aeiouyåäö]"
local consonant = "[bcdfghjklmnpqrstvwxz]"
local inflections = {}
local function postprocess(args, data)
if args["noa"] then
for key, form in pairs(data.forms) do
if (key:find("actv$")) then
data.forms[key] = nil
end
end
-- default handling of participles for passive-only verbs
if not args["prepart"] then
for key, form in pairs(data.forms) do
if key == "prespart" then
for i, subform in ipairs(form) do
form[i] = form[i] .. "s"
end
end
end
end
if not args["pp"] then
data.forms["pastpart"] = nil
end
else
-- only deponent verbs have passive imperative forms
data.forms["imppasv"] = nil
data.forms["impppasv"] = nil
end
if args["nop"] then
for key, form in pairs(data.forms) do
if (key:find("pasv$")) then
data.forms[key] = nil
end
end
end
if args["noprepart"] then
data.forms["prespart"] = nil
end
if args["nopp"] then
data.forms["pastpart"] = nil
end
-- add particle to participles; it is added separately for the table later
if args["particle"] or args["particle2"] then
data.particle = args["particle"]
table.insert(data.categories, "Swedish phrasal verbs")
local part = args["particle2"] or args["particle"] or ""
for key, form in pairs(data.forms) do
if key == "prespart" or key == "pastpart" then
for i, subform in ipairs(form) do
form[i] = part .. form[i]
end
end
end
end
if args["note"] and data.definitions and data.definitions:find("%)$") then
data.definitions = mw.ustring.sub(data.definitions, 1, mw.ustring.len(data.definitions) - 1) .. ", " .. args["note"] .. ")"
end
end
local function convert_to_accel(form)
-- no accel for now
return nil
end
-- Make the table
local function make_table(data)
local function show_form(form, accel, show_particle)
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 part = ""
if show_particle and data.particle then
part = " " .. m_links.full_link({lang = lang, term = data.particle})
end
for key, subform in ipairs(form) do
table.insert(ret, m_links.full_link({lang = lang, term = subform, accel = accel and { ["form"] = accel } or nil}) .. part)
end
return table.concat(ret, ", ")
end
local function repl(param)
if param == "head" then
return data.particle and (data.head .. " " .. data.particle) or data.head
elseif param == "definitions" then
return data.definitions
else
return show_form(data.forms[param], convert_to_accel(param), param ~= "prespart" and param ~= "pastpart")
end
end
local wikicode = [=[
<div class="NavFrame" style="max-width:54em;" data-toggle-category="inflection">
<div class="NavHead" >Conjugation of ]=] .. mw.getCurrentFrame():expandTemplate{title = "l-self", args = {"sv", data.head}} .. [=[ {{{definitions}}}</div>
<div class="NavContent" style="overflow:auto">
{| class="inflection-table" style="width: 100%; line-height: 125%; background-color: #F9F9F9; text-align: center; border: 1px solid #CCCCFF;" cellpadding="3" cellspacing="1"
|-
!
! colspan=2 style="width: 50%; background-color:#EFEFEF;" | Active
! colspan=2 style="width: 50%; background-color:#EFEFEF;" | Passive
|-
! style="background-color:#EFEFEF;" | Infinitive
| colspan=2 | {{{infactv}}}
| colspan=2 | {{{infpasv}}}
|-
! style="background-color:#EFEFEF;" | Supine
| colspan=2 | {{{supactv}}}
| colspan=2 | {{{suppasv}}}
|-
! style="background-color:#EFEFEF;" | Imperative
| colspan=2 | {{{impactv}}}
| colspan=2 | {{{imppasv}}}
|-
! style="background-color:#EFEFEF;" | ''Imper. plural''<sup>1</sup>
| colspan=2 | {{{imppactv}}}
| colspan=2 | {{{impppasv}}}
|-
!
! style="width: 25%; background-color:#EFEFEF;" | Present
! style="width: 25%; background-color:#EFEFEF;" | Past
! style="width: 25%; background-color:#EFEFEF;" | Present
! style="width: 25%; background-color:#EFEFEF;" | Past
|-
! style="background-color:#EFEFEF;" | Indicative
| {{{indpresactv}}}
| {{{indpastactv}}}
| {{{indprespasv}}}
| {{{indpastpasv}}}
|-
! style="background-color:#EFEFEF;" | ''Ind. plural''<sup>1</sup>
| {{{indppresactv}}}
| {{{indppastactv}}}
| {{{indpprespasv}}}
| {{{indppastpasv}}}
|-
! style="background-color:#EFEFEF;" | ''Subjunctive''<sup>2</sup>
| {{{subjpresactv}}}
| {{{subjpastactv}}}
| {{{subjprespasv}}}
| {{{subjpastpasv}}}
|-
!
! colspan=4 style="width: 100%; background-color:#EFEFEF;" | Participles
|-
! style="background-color:#EFEFEF;"| Present participle
| colspan=4 | {{{prespart}}}
|-
! style="background-color:#EFEFEF;" | Past participle
| colspan=4 | {{{pastpart}}}
|-
| colspan=5 style="text-align: left;" | <small><sup>1</sup> Archaic. <sup>2</sup> Dated. See [[Appendix:Swedish verbs#Dated and archaic forms|the appendix on Swedish verbs]].</small>
|}</div></div>]=]
return mw.ustring.gsub(wikicode, "{{{([a-z0-9_]+)}}}", repl)
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 = {head = args["head"] or mw.title.getCurrentTitle().text, definitions = "", forms = {}, categories = {}}
-- Generate the forms
inflections[infl_type](args, data)
-- Postprocess
postprocess(args, data)
return make_table(data) .. m_utilities.format_categories(data.categories, lang)
end
local function split_multi(forms)
if not forms or forms == "" or forms == "-" then
return nil
end
return mw.text.split(forms, ",")
end
--[=[
Inflection functions
]=]--
local function make_passive(forms)
local pasv = {}
for i, subform in ipairs(forms) do
table.insert(pasv, subform .. "s")
end
return pasv
end
local weak_present_endings = {
["r"] = "",
["a"] = "r",
["vw"] = "r",
["fv"] = "ver",
["mm"] = "mer",
["nn"] = "ner"
}
local weak_past_endings = {
["t"] = "",
["d"] = "",
["s"] = "t",
["vl"] = "t",
["vw"] = "dd"
}
local weak_sup_endings = {
["t"] = "",
["vw"] = "tt"
}
local weak_part_endings = {
["vw"] = "ende"
}
local weak_prespasv_endings1 = {
["nn"] = "ns"
}
local weak_prespasv_endings2 = {
["fv"] = "ves",
["mm"] = "mes",
["nn"] = "nes"
}
local weak_subj_endings = {
["mm"] = "me",
["nn"] = "ne"
}
local weak_impp_endings = {
["vw"] = "n",
["fv"] = "ven",
["mm"] = "men",
["nn"] = "nen"
}
local function make_weak_present_form(stem, endc)
local result = {stem .. (weak_present_endings[endc] or "er")}
if endc == "dj" then
table.insert(result, stem .. "jer")
end
return result
end
local function make_weak_prespasv_form(stem, endc)
if endc == "s" then
return {stem .. "es"}
end
local result = {stem .. (weak_prespasv_endings1[endc] or "s")}
if endc ~= "vw" and endc ~= "a" then
table.insert(result, stem .. (weak_prespasv_endings2[endc] or "es"))
end
if endc == "dj" then
table.insert(result, stem .. "jes")
end
return result
end
inflections["weak"] = function(args, data)
data.definitions = "(weak)"
table.insert(data.categories, "Swedish weak verbs")
local head = data.head
-- remove passive final -s to make forms correct
if head:find("s$") and args["noa"] then
head = mw.ustring.sub(head, 1, mw.ustring.len(head) - 1)
end
local basic = args[1] or head
local past = args[2] or basic
local full = args["full"] or head
local endc = args["end"] or (args[1] and "" or "a")
local bare = basic
local vowelstem = mw.ustring.find(basic, vowel .. "$")
if endc == "a" then
bare = mw.ustring.sub(bare, 1, mw.ustring.len(bare) - 1)
vowelstem = false
end
data.forms["infactv"] = {head}
data.forms["indpresactv"] = make_weak_present_form(basic, endc)
data.forms["indpastactv"] = args["past"] and split_multi(args["past"]) or {past .. (weak_past_endings[endc] or "d") .. "e"}
data.forms["supactv"] = args["sup"] and split_multi(args["sup"]) or {past .. (weak_sup_endings[endc] or "t")}
data.forms["impactv"] = args["imp"] and split_multi(args["imp"]) or {basic .. ((endc == "nn") and "n" or "")}
data.forms["imppactv"] = args["impp"] and split_multi(args["impp"]) or {bare .. (weak_impp_endings[endc] or "en")}
data.forms["prespart"] = args["prepart"] and split_multi(args["prepart"]) or {full .. (not args["full"] and weak_part_endings[endc] or "nde")}
data.forms["pastpart"] = args["pp"] and split_multi(args["pp"]) or {past .. (weak_past_endings[endc] or "d")}
data.forms["indppresactv"] = data.forms["infactv"]
data.forms["indppastactv"] = data.forms["indpastactv"]
data.forms["subjpresactv"] = args["sbj"] and split_multi(args["sbj"]) or (vowelstem and data.forms["infactv"] or {bare .. (weak_subj_endings[endc] or "e")})
data.forms["subjpastactv"] = data.forms["indpastactv"]
data.forms["infpasv"] = make_passive(data.forms["infactv"])
data.forms["indprespasv"] = make_weak_prespasv_form(basic, endc)
data.forms["indpastpasv"] = make_passive(data.forms["indpastactv"])
data.forms["suppasv"] = make_passive(data.forms["supactv"])
data.forms["imppasv"] = make_passive(data.forms["impactv"])
data.forms["impppasv"] = make_passive(data.forms["imppactv"])
data.forms["indpprespasv"] = data.forms["infpasv"]
data.forms["indppastpasv"] = data.forms["indpastpasv"]
data.forms["subjprespasv"] = make_passive(data.forms["subjpresactv"])
data.forms["subjpastpasv"] = data.forms["indpastpasv"]
end
local strong_pres_endings = {
["r"] = "",
["vw"] = "r",
["fv"] = "ver",
["mm"] = "mer",
["nn"] = "ner"
}
local strong_sup_endings = {
["fv"] = "vit",
["mm"] = "mit",
["nn"] = "nit"
}
local strong_pastpart_endings = {
["fv"] = "ven",
["mm"] = "men",
["nn"] = "nen"
}
local strong_subj_endings = {
["vw"] = "",
["fv"] = "ve",
["mm"] = "me",
["nn"] = "ne"
}
local strong_impp_endings = {
["vw"] = "n",
["fv"] = "ven",
["mm"] = "men",
["nn"] = "nen"
}
local function make_strong_ppl_stem(class, endc, past, sup)
local base
if class == "3" or class == "4" then
base = sup
else
base = past
end
if endc == "mm" then
base = base .. "m"
elseif endc == "nn" then
base = base .. "n"
end
return base
end
local function make_strong_prespasv_form(stem, endc)
if endc == "s" then
return {stem .. "es"}
end
local result = {stem .. (weak_prespasv_endings1[endc] or "s")}
if endc ~= "vw" and endc ~= "a" then
table.insert(result, stem .. (weak_prespasv_endings2[endc] or "es"))
end
if endc == "dj" then
table.insert(result, stem .. "jes")
end
return result
end
local function get_final_vowel(stem)
return mw.ustring.match(stem, ".*(" .. vowel .. ")")
end
local function try_detect_strong_class(pres, past, sup, endc)
local presv = get_final_vowel(pres)
local pastv = get_final_vowel(past)
local supv = get_final_vowel(sup)
if supv == "i" or supv == "ä" or supv == "e" then
if supv == "i" and pastv == "e" and presv == "i" then
return "1"
elseif (pastv == "a" or pastv == "å") and (presv == "e" or presv == "i" or presv == "ä") then
return "5"
end
elseif supv == "u" then
if pastv == "ö" and (presv == "u" or presv == "y") then
return "2"
elseif pastv == "a" then
if presv == "i" then
return "3"
elseif presv == "e" or presv == "ä" then
if pres:find(consonant .. consonant .. "$") then
return "3"
else
return "4"
end
end
end
elseif supv == "a" or supv == "å" then
if supv == "a" and pastv == "o" and presv == "a" then
return "6"
elseif (pastv == "ö" or pastv == "ä") and (presv == "å" or presv == "a") then
return "7"
end
end
return nil
end
inflections["strong"] = function(args, data)
table.insert(data.categories, "Swedish strong verbs")
local head = data.head
-- remove passive final -s to make forms correct
if head:find("s$") and args["noa"] then
head = mw.ustring.sub(head, 1, mw.ustring.len(head) - 1)
end
local endc = args["end"] or ""
local pres = args[1] or error("At least 3 arguments required for strong verb inflections (missing present stem)")
local past = args[2] or error("At least 3 arguments required for strong verb inflections (missing past stem)")
local sup = args[3]
-- it's fine to not specify the supine stem if supine and pp forms are manually given
if not sup and (not args["sup"] or not (args["pp"] or args["nopp"])) then
error("At least 3 arguments required for strong verb inflections (missing supine stem; alternatively specify supine and past participle forms manually)")
elseif not sup then
sup = mw.ustring.sub(args["sup"], 1, mw.ustring.len(args["sup"]) - 1)
end
local class = args["class"] or try_detect_strong_class(pres, past, sup, endc)
local full = args["full"] or (head .. (endc == "vw" and "e" or ""))
local ppl = args["ppl"] or make_strong_ppl_stem(class, endc, past, sup)
if class then
table.insert(data.categories, "Swedish class " .. class .. " strong verbs")
data.definitions = "(class " .. class .. " strong)"
else
data.definitions = "(strong)"
end
if class == "5" then -- for class 5, replace final -a- with -å- in plural/subjunctive stem
ppl = mw.ustring.gsub(ppl, "(.*)a(.*)", "%1å%2")
end
if endc == "fv" and ppl:find("f$") then
ppl = ppl .. "v"
end
data.forms["infactv"] = {head}
data.forms["indpresactv"] = {pres .. (strong_pres_endings[endc] or "er")}
data.forms["indpastactv"] = {past}
data.forms["supactv"] = args["sup"] and split_multi(args["sup"]) or {sup .. (strong_sup_endings[endc] or "it")}
data.forms["impactv"] = args["imp"] and split_multi(args["imp"]) or {pres}
data.forms["imppactv"] = args["impp"] and split_multi(args["impp"]) or {pres .. (strong_impp_endings[endc] or "en")}
data.forms["prespart"] = args["prepart"] and split_multi(args["prepart"]) or {full .. "nde"}
data.forms["pastpart"] = args["pp"] and split_multi(args["pp"]) or {sup .. (strong_pastpart_endings[endc] or "en")}
data.forms["indppresactv"] = args["pl"] and split_multi(args["pl"]) or data.forms["infactv"]
data.forms["indppastactv"] = {ppl .. "o"}
data.forms["subjpresactv"] = args["sbj"] and split_multi(args["sbj"]) or {pres .. (strong_subj_endings[endc] or "e")}
data.forms["subjpastactv"] = args["psbj"] and split_multi(args["psbj"]) or {ppl .. "e"}
data.forms["infpasv"] = make_passive(data.forms["infactv"])
data.forms["indprespasv"] = make_strong_prespasv_form(pres, endc)
data.forms["indpastpasv"] = make_passive(data.forms["indpastactv"])
data.forms["suppasv"] = make_passive(data.forms["supactv"])
data.forms["imppasv"] = make_passive(data.forms["impactv"])
data.forms["impppasv"] = make_passive(data.forms["imppactv"])
data.forms["indpprespasv"] = make_passive(data.forms["indppresactv"])
data.forms["indppastpasv"] = make_passive(data.forms["indppastactv"])
data.forms["subjprespasv"] = make_passive(data.forms["subjpresactv"])
data.forms["subjpastpasv"] = make_passive(data.forms["subjpastactv"])
end
inflections["irreg"] = function(args, data)
table.insert(data.categories, "Swedish irregular verbs")
data.definitions = "(irregular)"
data.forms["infactv"] = split_multi(args[1])
data.forms["indpresactv"] = split_multi(args[2])
data.forms["indpastactv"] = split_multi(args[3])
data.forms["supactv"] = split_multi(args[4])
data.forms["impactv"] = split_multi(args[5])
data.forms["imppactv"] = split_multi(args["impp"])
data.forms["prespart"] = split_multi(args[6])
data.forms["pastpart"] = split_multi(args[7])
data.forms["indppresactv"] = split_multi(args["pl"])
data.forms["indppastactv"] = split_multi(args["ppl"])
data.forms["subjpresactv"] = split_multi(args["sbj"])
data.forms["subjpastactv"] = split_multi(args["psbj"])
end
return export