Module:vep-verbs

local m_utilities = require("Module:utilities") local m_links = require("Module:links")

local export = {}

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

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

-- 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 = mw.title.getCurrentTitle.text, info = nil, categories = {}} if mw.title.getCurrentTitle.namespace == 10 then data.title = args["title"] or data.title end

local lemma = data.title if args["prefix"] and #args["prefix"] > 0 then local prefix = args["prefix"] if mw.ustring.sub(lemma, 1, mw.ustring.len(prefix)) ~= prefix then error("|prefix= does not match the lemma") end lemma = mw.ustring.sub(lemma, mw.ustring.len(prefix) + 1) end if args["suffix"] and #args["suffix"] > 0 then local suffix = args["suffix"] if mw.ustring.sub(lemma, -mw.ustring.len(suffix)) ~= suffix then error("|suffix= does not match the lemma") end lemma = mw.ustring.sub(lemma, 1, -mw.ustring.len(suffix) - 1) end data.lemma = lemma -- Generate the forms inflections[infl_type](args, data) -- Postprocess postprocess(args, data) return make_table(data) .. m_utilities.format_categories(data.categories, lang) end

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

local function get_param(args, first) local param = args[first] or "" if param == "" and mw.title.getCurrentTitle.nsText == "Template" then return "" end return param end

local function count_syllables(word) local count = 0

local function do_count(a, b)		if a == b then return a, b		elseif b == "i" or (b == "u" and mw.ustring.find(a, "[aoäö]")) then count = count + 1 return a .. b		else count = count + 1 return a, b		end end require("Module:gsub lookahead")(word, "([aeiouäöü])(.?)", do_count) return count end

local function get_inf3_ill(impr3_suff, potn_stem, harmony) local reduce_ok = mw.ustring.match(impr3_suff, "[gk]") and count_syllables(potn_stem) == 1 if reduce_ok then return potn_stem .. "mh" .. harmony else return potn_stem .. "m" .. harmony .. "h" .. harmony end end

local consonants = { ["d"] = {["b"] = "b", ["d"] = "d", ["g"] = "g"}, ["t"] = {["b"] = "p", ["d"] = "t", ["g"] = "k"}, }

--[=[	New auto-inflection types ]=]--

local function add_info(data, number, specimen) data.info = "inflection type " .. number .. "/" .. m_links.full_link({lang = lang, term = specimen}, "term") table.insert(data.categories, lang:getCanonicalName .. " " .. specimen .. "-type verbs") end

local function extract_stem(stem, suffix) local result = mw.ustring.match(stem, suffix .. "$") if not result then error("Unsupported stem for this inflection type") end return mw.ustring.gsub(stem, suffix .. "$", ""), result end

local function generate_from_stems(args, data, inf, pres, past, impr3) local inf_stem local pres_stem = pres local past_stem = past local past_actv_ptcp_stem local cond_stem local potn_stem

local cons, harmony inf_stem, cons, harmony = mw.ustring.match(inf, "^(.-)([dt])([aä])$") cons = consonants[cons] if not mw.ustring.find(pres_stem, "[aeiouüäö]$") then error("Present must end in a vowel followed by -b.") end if not mw.ustring.find(past_stem, "i$") then error("Past must end in -i.") end -- Conditional stem if mw.ustring.find(pres_stem, "[aeiouüäö-][^aeiouüäö]+[eiä]$") or mw.ustring.find(pres_stem, "[aeiouüäö]i$") then cond_stem = mw.ustring.gsub(pres_stem, "[eiä]$", "") else cond_stem = pres_stem end -- Past active participle stem local past_actv_ptcp_stem = inf_stem if mw.ustring.find(inf_stem, "[kpsšt]$") then local inf_stem_voiced = mw.ustring.gsub(inf_stem, "[kpsšt]$", {["k"] = "g", ["p"] = "b", ["s"] = "z", ["š"] = "ž", ["t"] = "d"}) local pres_stem_novowel = mw.ustring.gsub(pres_stem, "[aeiouüäö]+$", "") if inf_stem_voiced == pres_stem_novowel then past_actv_ptcp_stem = inf_stem_voiced end end -- Potential stem if mw.ustring.find(inf_stem, "[aeiouüäö]$") then potn_stem = pres_stem else potn_stem = past_actv_ptcp_stem end

-- Third-person imperative stem and suffix local impr3_stem = inf_stem if not mw.ustring.find(impr3, "^[čdgkt]") then impr3 = cons["g"] .. impr3 end if mw.ustring.find(impr3, "^g") and mw.ustring.find(impr3_stem, "k$") then impr3_stem = mw.ustring.sub(impr3_stem, 1, -2) .. "g" elseif mw.ustring.find(impr3, "^k") and mw.ustring.find(impr3_stem, "g$") then impr3_stem = mw.ustring.sub(impr3_stem, 1, -2) .. "k" end -- Present indicative data.forms["1sg_pres_indc"] = {pres_stem .. "n"} data.forms["2sg_pres_indc"] = {pres_stem .. "d"} data.forms["3sg_pres_indc"] = {pres_stem .. "b"} data.forms["1pl_pres_indc"] = {pres_stem .. "m"} data.forms["2pl_pres_indc"] = {pres_stem .. "t"} data.forms["3pl_pres_indc"] = {inf_stem .. cons["d"] .. "as", pres_stem .. "ba"} data.forms["sg_pres_indc_conn"] = {pres_stem} data.forms["pl_pres_indc_conn"] = {inf_stem .. cons["g"] .. "oi"} -- Past indicative data.forms["1sg_past_indc"] = {past_stem .. "n"} data.forms["2sg_past_indc"] = {past_stem .. "d"} data.forms["3sg_past_indc"] = {past_stem} data.forms["1pl_past_indc"] = {past_stem .. "m"} data.forms["2pl_past_indc"] = {past_stem .. "t"} data.forms["3pl_past_indc"] = {past_stem .. "ba"} data.forms["sg_past_indc_conn"] = {pres_stem .. "nd"} data.forms["pl_past_indc_conn"] = {past_actv_ptcp_stem .. "nugoi"} -- Imperative data.forms["1sg_impr"] = nil data.forms["2sg_impr"] = {pres_stem} data.forms["3sg_impr"] = {impr3_stem .. impr3 .. "ha"} data.forms["1pl_impr"] = {inf_stem .. cons["g"] .. "am"} data.forms["2pl_impr"] = {inf_stem .. cons["g"] .. "at"} data.forms["3pl_impr"] = {data.forms["3sg_impr"][1]} data.forms["sg_impr_conn"] = {pres_stem} data.forms["pl_impr_conn"] = {inf_stem .. cons["g"] .. "oi"} -- Present conditional data.forms["1sg_pres_cond"] = {cond_stem .. "ižin"} data.forms["2sg_pres_cond"] = {cond_stem .. "ižid"} data.forms["3sg_pres_cond"] = {cond_stem .. "iži"} data.forms["1pl_pres_cond"] = {cond_stem .. "ižim"} data.forms["2pl_pres_cond"] = {cond_stem .. "ižit"} data.forms["3pl_pres_cond"] = {cond_stem .. "ižiba"} data.forms["pres_cond_conn"] = {cond_stem .. "iži"} -- Past conditional data.forms["1sg_past_cond"] = {past_actv_ptcp_stem .. "nuižin"} data.forms["2sg_past_cond"] = {past_actv_ptcp_stem .. "nuižid"} data.forms["3sg_past_cond"] = {past_actv_ptcp_stem .. "nuiži"} data.forms["1pl_past_cond"] = {past_actv_ptcp_stem .. "nuižim"} data.forms["2pl_past_cond"] = {past_actv_ptcp_stem .. "nuižit"} data.forms["3pl_past_cond"] = {past_actv_ptcp_stem .. "nuižiba"} data.forms["past_cond_conn"] = {past_actv_ptcp_stem .. "nuiži"} -- Potential data.forms["1sg_potn"] = {potn_stem .. "nen"} data.forms["2sg_potn"] = {potn_stem .. "ned"} data.forms["3sg_potn"] = {potn_stem .. "neb"} data.forms["1pl_potn"] = {potn_stem .. "nem"} data.forms["2pl_potn"] = {potn_stem .. "net"} data.forms["3pl_potn"] = {potn_stem .. "neba"} data.forms["potn_conn"] = {potn_stem .. "ne"} -- Infinitives data.forms["inf1"]    = {inf_stem .. cons["d"] .. harmony} data.forms["inf2_ine"] = {inf_stem .. cons["d"] .. "es"} data.forms["inf2_ins"] = {inf_stem .. cons["d"] .. "en"} data.forms["inf3_ine"] = {potn_stem .. "m" .. harmony .. "s"} if mw.ustring.find(potn_stem, "^[^aeiouüäö-]*[aeiouüäö]i?$") then data.forms["inf3_ill"] = {potn_stem .. "mh" .. harmony} elseif mw.ustring.find(potn_stem, "[^aeiouüäö]$") then data.forms["inf3_ill"] = {potn_stem .. "m" .. harmony .. "h" .. harmony} else data.forms["inf3_ill"] = {get_inf3_ill(impr3, potn_stem, harmony)} end data.forms["inf3_ela"] = {potn_stem .. "m" .. harmony .. "späi"} data.forms["inf3_ade"] = {potn_stem .. "m" .. harmony .. "l"} data.forms["inf3_abe"] = {potn_stem .. "m" .. harmony .. "t"} -- Participles if mw.ustring.find(pres_stem, "[aeiouüäö]i$") then data.forms["pres_actv_ptcp"] = {pres_stem} elseif mw.ustring.find(pres_stem, "[aeiouüäö-][^aeiouüäö]+e$") then data.forms["pres_actv_ptcp"] = {mw.ustring.gsub(pres_stem, "e$", "i") .. "i"} else data.forms["pres_actv_ptcp"] = {pres_stem .. "i"} end data.forms["past_actv_ptcp"] = {past_actv_ptcp_stem .. "nu"} data.forms["past_pasv_ptcp"] = {inf_stem .. cons["d"] .. "ud"} end

inflections["ujuda"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "da") extract_stem(stem, "[ouöü]") local syllables = count_syllables(stem) local reduce = syllables <= 3 and syllables % 2 == 1

add_info(data, 1, "ujuda") return generate_from_stems(args, data, data.lemma,			stem, stem .. "i", reduce and "" or "a") end

inflections["jauhta"] = function(args, data) local stem = args[1] if not stem or not mw.ustring.find(stem, "[ou]$") then error("A present stem ending in -o/u, equivalent to the third-person indicative present singular without the final -b, must be specified.") end add_info(data, 2, "jauhta") return generate_from_stems(args, data, data.lemma,			stem, stem .. "i", "a") end

inflections["kacta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "[dt]a") .. "u" add_info(data, 3, "kacta") return generate_from_stems(args, data, data.lemma,			stem, stem .. "i", "a") end

inflections["lahota"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta") if mw.ustring.find(stem, "[kpsš]$") then local final stem, final = extract_stem(stem, "[kpsš]") final = ({["k"] = "g", ["p"] = "b", ["s"] = "z", ["š"] = "ž"})[final] stem = stem .. final .. "u" else stem = stem .. "du" end add_info(data, 4, "lahota") return generate_from_stems(args, data, data.lemma,			stem, stem .. "i", "a") end

inflections["vodada"] = function(args, data) local stem = data.lemma local harmony = args[1] if not harmony or not mw.ustring.find(harmony, "[aä]$") then error("The vowel harmony of the present stem must be specified as a or ä.") end stem = extract_stem(stem, harmony .. "da")

local syllables = count_syllables(stem .. harmony) local reduce = syllables <= 3 and syllables % 2 == 1

add_info(data, 5, "vodada") return generate_from_stems(args, data, data.lemma,			stem .. harmony, stem .. "i", reduce and "" or "a") end

inflections["kuida"] = function(args, data) local stem = args[1] if not stem or not mw.ustring.find(stem, "[aä]$") then error("A present stem ending in -a/ä, equivalent to the third-person indicative present singular without the final -b, must be specified.") end

local reduce = not mw.ustring.find(data.lemma, "[aeiouäöü]d[aä]$")

add_info(data, 6, "kuida") return generate_from_stems(args, data, data.lemma,			stem, mw.ustring.sub(stem, 1, -2) .. "i", reduce and "" or "a") end

inflections["lüpsta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta") local harmony = args[1] if not harmony or not mw.ustring.find(harmony, "[aä]$") then error("The vowel harmony of the present stem must be specified as a or ä.") end

add_info(data, 7, "lüpsta") return generate_from_stems(args, data, data.lemma,			stem .. harmony, stem .. "i", "a") end

inflections["püta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta") local harmony = args[1] if not harmony or not mw.ustring.find(harmony, "[aä]$") then error("The vowel harmony of the present stem must be specified as a or ä.") end

local diphthong = false local reduce = false if count_syllables(stem) == 1 then diphthong = mw.ustring.find(stem, "[aoäö]u$") reduce = mw.ustring.find(stem, "[ruü]$") end

add_info(data, 8, "püta") return generate_from_stems(args, data, data.lemma,			stem .. "d" .. harmony, stem .. "di", diphthong and "tka" or reduce and "" or "a") end

inflections["kogota"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta") local harmony = args[1] if not harmony or not mw.ustring.find(harmony, "[aä]$") then error("The vowel harmony of the present stem must be specified as a or ä.") end

local diphthong = count_syllables(stem) == 1 and mw.ustring.find(stem, "[aoäö]u$")

add_info(data, 9, "kogota") return generate_from_stems(args, data, data.lemma,			stem .. "d" .. harmony, stem .. "zi", diphthong and "tka" or "a") end

inflections["küntta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta") local harmony = args[1] if not harmony or not mw.ustring.find(harmony, "[aä]$") then error("The vowel harmony of the present stem must be specified as a or ä.") end

local final stem, final = extract_stem(stem, "[kpt]") stem = stem .. ({["k"] = "g", ["p"] = "b", ["t"] = "d"})[final]

add_info(data, 10, "küntta") return generate_from_stems(args, data, data.lemma,			stem .. harmony, stem .. "i", "a") end

inflections["käta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta") local harmony = args[1] if not harmony or not mw.ustring.find(harmony, "[aä]$") then error("The vowel harmony of the present stem must be specified as a or ä.") end

add_info(data, 11, "käta") return generate_from_stems(args, data, data.lemma,			stem .. "nd" .. harmony, stem .. "ndi", "a") end

inflections["ajada"] = function(args, data) local stem = args[1] if not stem or not mw.ustring.find(stem, "[aä]$") then error("A present stem ending in -a/ä, equivalent to the third-person indicative present singular without the final -b, must be specified.") end

add_info(data, 12, "ajada") return generate_from_stems(args, data, data.lemma,			stem, mw.ustring.sub(stem, 1, -2) .. "oi", "a") end

inflections["maksta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta") if mw.ustring.match(stem, "^[^aeiouäöü]?[aeiouäöü]$") then stem = stem .. "d" end

add_info(data, 13, "maksta") return generate_from_stems(args, data, data.lemma,			stem .. "a", stem .. "oi", "a") end

inflections["antta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta")

local final stem, final = extract_stem(stem, "[kpt]") stem = stem .. ({["k"] = "g", ["p"] = "b", ["t"] = "d"})[final]

add_info(data, 14, "antta") return generate_from_stems(args, data, data.lemma,			stem .. "a", stem .. "oi", "a") end

inflections["lugeda"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "eda")

local syllables = count_syllables(stem .. "e") local reduce = syllables <= 3 and syllables % 2 == 1

add_info(data, 15, "lugeda") return generate_from_stems(args, data, data.lemma,			stem .. "e", stem .. "i", reduce and "" or "a") end

inflections["särkta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta")

local final stem, final = extract_stem(stem, "[kpt]") stem = stem .. ({["k"] = "g", ["p"] = "b", ["t"] = "d"})[final]

add_info(data, 16, "särkta") return generate_from_stems(args, data, data.lemma,			stem .. "e", stem .. "i", "ga") end

inflections["tuntta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "tta")

add_info(data, 17, "tuntta") return generate_from_stems(args, data, data.lemma,			stem .. "de", stem .. "zi", "a") end

inflections["lähtta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "htta")

add_info(data, 18, "lähtta") return generate_from_stems(args, data, data.lemma,			stem .. "hte", stem .. "ksi", "a") end

inflections["pureskelda"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "da")

local syllables = count_syllables(stem) local reduce = syllables <= 3 and syllables % 2 == 1

add_info(data, 19, "pureskelda") return generate_from_stems(args, data, data.lemma,			stem .. "e", stem .. "i", reduce and "" or "a") end

inflections["oppida"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "[dt][aä]")

local reduce if mw.ustring.match(stem, "i$") then local syllables = count_syllables(stem) reduce = syllables <= 3 and syllables % 2 == 1 else stem = mw.ustring.gsub(stem, "'$", "") .. "i" end

add_info(data, 20, "oppida") return generate_from_stems(args, data, data.lemma,			stem, stem, reduce and "" or "a") end

inflections["henkta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta")

local final stem, final = extract_stem(stem, "[kps]") stem = stem .. ({["k"] = "g", ["p"] = "b", ["s"] = "z"})[final] .. "i"

add_info(data, 21, "henkta") return generate_from_stems(args, data, data.lemma,			stem, stem, "a") end

inflections["laida"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ida") .. "ji"

local syllables = count_syllables(stem) local reduce = syllables <= 2

add_info(data, 22, "laida") return generate_from_stems(args, data, data.lemma,			stem, stem, reduce and "" or "a") end

inflections["toda"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "da")

add_info(data, 23, "toda") return generate_from_stems(args, data, data.lemma,			stem, stem .. "i", "") end

inflections["voida"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "da") extract_stem(stem, "i")

add_info(data, 24, "voida") return generate_from_stems(args, data, data.lemma,			stem, stem, "") end

inflections["purda"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "[dt]a") stem = mw.ustring.gsub(stem, "([aeiouäöü])([sš])$",           function (v, c)                return v .. ({["s"] = "z", ["š"] = "ž"})[c]            end) stem = mw.ustring.gsub(stem, "'$", "")

add_info(data, 25, "purda") return generate_from_stems(args, data, data.lemma,			stem .. "e", stem .. "i", "a") end

inflections["valita"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta") local syllables = count_syllables(stem) local diphthong = syllables == 1 local reduce = syllables == 3

add_info(data, 26, "valita") return generate_from_stems(args, data, data.lemma,			stem .. "če", stem .. "či", diphthong and "čka" or reduce and "" or "a") end

inflections["nähta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "hta") add_info(data, 27, "nähta") return generate_from_stems(args, data, data.lemma,			stem .. "ge", stem .. "gi", "a") end

inflections["edeta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta") add_info(data, 28, "edeta") return generate_from_stems(args, data, data.lemma,			stem .. "ne", stem .. "ni", "a") end

inflections["koheta"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ta") add_info(data, 29, "koheta") return generate_from_stems(args, data, data.lemma,			stem .. "nda", stem .. "nzi", "a") end

inflections["harjata"] = function(args, data) local stem = data.lemma stem = extract_stem(stem, "ata") add_info(data, 30, "harjata") return generate_from_stems(args, data, data.lemma,			stem .. "a", stem .. "oi", "a") end

-- Helper functions

function postprocess(args, data) -- Check if the lemma form matches the page name local lemma_key = "inf1" local prefix = args["prefix"] or "" local suffix = args["suffix"] or "" for key, form in pairs(data.forms) do		if form then for key2, subform in pairs(form) do form[key2] = prefix .. subform .. suffix end end data.forms[key] = form end

if data.forms[lemma_key] and data.forms[lemma_key][1] and (lang:makeEntryName(data.forms[lemma_key][1])) ~= mw.title.getCurrentTitle.text then table.insert(data.categories, lang:getCanonicalName .. " entries with inflection not matching pagename") end end

-- Make the table function make_table(data) local function show_form(form) if not form then return "&mdash;" end if 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, "?", nil, true) then table.insert(ret, "?") else table.insert(ret, m_links.full_link({lang = lang, term = subform})) end end return table.concat(ret, " ") end local function repl(param) if param == "lemma" then return m_links.full_link({lang = lang, alt = mw.title.getCurrentTitle.text}, "term") elseif param == "info" then return data.info and " (" .. data.info .. ")" or "" else return show_form(data.forms[param]) end end local wikicode = [=[ return mw.ustring.gsub(wikicode, "", repl) end

return export