Module:zu-nouns

local m_utilities = require("Module:utilities") local m_links = require("Module:links") local m_common = require("Module:zu-common")

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

local export = {}

local prefixes = { ["1"] = {		"^([uU][" .. m_common.diacritic .. "]*[mM][uU][" .. m_common.diacritic .. "]*)(.+)$", "^([uU][" .. m_common.diacritic .. "]*[mM][" .. m_common.diacritic .. "]*)(.+)$", "^([uU][" .. m_common.diacritic .. "]*)([nN].+)$", },	["1a"] = { "^([uU][" .. m_common.diacritic .. "]*)(.+)$", },	["2"] = {		"^([aA][" .. m_common.diacritic .. "]*[bB][aeAE][" .. m_common.diacritic .. "]*)(.+)$", "^([aA][" .. m_common.diacritic .. "]*[bB])([" .. m_common.vowel .. ".+)$", },	["2a"] = { "^([oO][" .. m_common.diacritic .. "]*)(.+)$", },	["3"] = {		"^([uU][" .. m_common.diacritic .. "]*[mM][uU][" .. m_common.diacritic .. "]*)(.+)$", "^([uU][" .. m_common.diacritic .. "]*[mM][" .. m_common.diacritic .. "]*)(.+)$", "^([uU][" .. m_common.diacritic .. "]*)([nN].+)$", },	["4"] = {		"^([iI][" .. m_common.diacritic .. "]*[mM][iI][" .. m_common.diacritic .. "]*)(.+)$", "^([iI][" .. m_common.diacritic .. "]*[mM])([" .. m_common.vowel .. "].+)$", },	["5"] = {		"^([iI][" .. m_common.diacritic .. "]*)(.+)$", },	["6"] = {		"^([aA][" .. m_common.diacritic .. "]*[mM][aA][" .. m_common.diacritic .. "]*)(.+)$", "^([aA][" .. m_common.diacritic .. "]*[mM])([" .. m_common.vowel .. "].+)$", },	["7"] = {		"^([iI][" .. m_common.diacritic .. "]*[sS][iI][" .. m_common.diacritic .. "]*)(.+)$", "^([iI][" .. m_common.diacritic .. "]*[sS])([" .. m_common.vowel .. "].+)$", },	["8"] = {		"^([iI][" .. m_common.diacritic .. "]*[zZ][iI][" .. m_common.diacritic .. "]*)(.+)$", "^([iI][" .. m_common.diacritic .. "]*[zZ])([" .. m_common.vowel .. "].+)$", },	["9"] = {		"^([iI][" .. m_common.diacritic .. "]*[mMnN])([^" .. m_common.vowel .. "].+)$", "^([iI][" .. m_common.diacritic .. "]*)([lLmMnN][" .. m_common.vowel .. "].+)$", },	["10"] = {		"^([iI][" .. m_common.diacritic .. "]*[zZ][iI][" .. m_common.diacritic .. "]*[mMnN])([^" .. m_common.vowel .. "].+)$", "^([iI][" .. m_common.diacritic .. "]*[zZ][iI][" .. m_common.diacritic .. "]*)([hHlLmMnN][" .. m_common.vowel .. "wW].+)$", },	["11"] = {		"^([uU][" .. m_common.diacritic .. "]*)(.+)$", --"^([uU][" .. m_common.diacritic .. "]*[lL][uU][" .. m_common.diacritic .. "]*)(.+)$", --"^([uU][" .. m_common.diacritic .. "]*[lL][wW])([" .. m_common.vowel .. "].+)$", },	["14"] = {		"^([uU][" .. m_common.diacritic .. "]*[bB][uU][" .. m_common.diacritic .. "]*)(.+)$", "^([uU][" .. m_common.diacritic .. "]*[bB])([" .. m_common.vowel .. "].+)$", "^([uU][" .. m_common.diacritic .. "]*[tT][sS][hH][wW]?)([aA].+)$", },	["15"] = {		"^([uU][" .. m_common.diacritic .. "]*[kK][uU][" .. m_common.diacritic .. "]*)(.+)$", "^([uU][" .. m_common.diacritic .. "]*[kK][wW])([" .. m_common.vowel .. "].+)$", },	["17"] = {		"^([uU][" .. m_common.diacritic .. "]*[kK][uU][" .. m_common.diacritic .. "]*)(.+)$", "^([uU][" .. m_common.diacritic .. "]*[kK][wW])([" .. m_common.vowel .. "].+)$", }, }

local function split_prefix(word, class, tone) if not prefixes[class] then error("Invalid class \"" .. class .. "\".") end

local prefix, stem word = mw.ustring.toNFD(word) for _, pattern in ipairs(prefixes[class]) do		prefix, stem = mw.ustring.match(word, pattern) if prefix then break end end if not prefix then if mw.title.getCurrentTitle.nsText ~= "Template" then error("Word \"" .. word .. "\" does not match any valid prefix of class \"" .. class .. "\".") end else local sstem = m_common.split_syllables(stem) local stone = mw.text.split(tone or mw.ustring.rep("L", #sstem), "") if #sstem ~= #stone then error("The word \"" .. stem .. "\" and the tone pattern " .. tone .. " have different numbers of syllables.") end return mw.ustring.toNFC(prefix), mw.ustring.toNFC(stem) end end

function makeSortKey(word, class) local prefix, stem = split_prefix(word, class) return (lang:makeSortKey(stem or word)) end

local function simple(data, base, prefix, class) base = (lang:makeEntryName(base)) if prefix then prefix = prefix .. "_"	else prefix = "" end if class == "2a" then data.forms[prefix .. "simp"] = {"b" .. base} elseif class == "5" then data.forms[prefix .. "simp"] = {(mw.ustring.gsub(base, "^i", "li"))} elseif class == "11" then data.forms[prefix .. "simp"] = {(mw.ustring.gsub(base, "^u", "lu"))} else data.forms[prefix .. "simp"] = {(mw.ustring.gsub(base, "^[aiu]%-?", ""))} end end

local function locative_ku(data, base, prefix, tone) base = (lang:makeEntryName(base)) if prefix then prefix = prefix .. "_"	else prefix = "" end if mw.ustring.find(base, "^[au]") then data.forms[prefix .. "loc"] = {m_common.apply_tone("ku" .. mw.ustring.gsub(base, "^[au]", ""), tone)} elseif mw.ustring.find(base, "^[" .. m_common.vowel .. "]") then data.forms[prefix .. "loc"] = {m_common.apply_tone("k" .. base)} elseif base == "mi" or base == "thi" or base == "ni" then data.forms[prefix .. "loc"] = {m_common.apply_tone("ki" .. base, tone)} else data.forms[prefix .. "loc"] = {m_common.apply_tone("ku" .. base, tone)} end end

local function locative_e(data, base, prefix, class) base = (lang:makeEntryName(base)) if prefix then prefix = prefix .. "_"	else prefix = "" end if mw.ustring.find(base, "^u") and class == "11" then base = mw.ustring.gsub(base, "^u", "o") else base = mw.ustring.gsub(base, "^[aiu]", "e") end data.forms[prefix .. "loc"] = {base} end

local function locative_extend(base) base = (lang:makeEntryName(base)) base = mw.ustring.gsub(base, "[aou]$", {["a"] = "e", ["o"] = "we", ["u"] = "wi"}) .. "ni" base = mw.ustring.gsub(base, "mbw([ei]ni)$", "nj%1") base = mw.ustring.gsub(base, "mpw([ei]ni)$", "ntsh%1") base = mw.ustring.gsub(base, "bhw([ei]ni)$", "j%1") base = mw.ustring.gsub(base, "[bp]w([ei]ni)$", "tsh%1") base = mw.ustring.gsub(base, "phw([ei]ni)$", "sh%1") base = mw.ustring.gsub(base, "mw([ei]ni)$", "ny%1") base = mw.ustring.gsub(base, "([fvw])w([ei]ni)$", "%1%2") return base end

local function copulative(data, base, prefix, class, tone) base = (lang:makeEntryName(base)) if prefix then prefix = prefix .. "_"	else prefix = "" end if mw.ustring.find(base, "^u") and class == "11" then data.forms[prefix .. "cop"] = {m_common.apply_tone("w" .. base)} elseif mw.ustring.find(base, "^[aou]") then data.forms[prefix .. "cop"] = {m_common.apply_tone("ng" .. base)} elseif mw.ustring.find(base, "^i") then data.forms[prefix .. "cop"] = {m_common.apply_tone("y" .. base)} elseif base == "we" or base == "ye" then data.forms[prefix .. "cop"] = {m_common.apply_tone("ngu" .. base, tone)} else data.forms[prefix .. "cop"] = {m_common.apply_tone("yi" .. base, tone)} end end

local function possessive(data, base, prefix, ka, tone) base = (lang:makeEntryName(base)) local tone_subst if tone then tone_subst = "H" .. tone end if prefix then prefix = prefix .. "_"	else prefix = "" end if ka then base = mw.ustring.gsub(base, "^u", "") data.forms[prefix .. "poss_mod_c1" ] = { "ka" .. base} data.forms[prefix .. "poss_mod_c2" ] = {"baka" .. base} data.forms[prefix .. "poss_mod_c3" ] = { "ka" .. base} data.forms[prefix .. "poss_mod_c4" ] = { "ka" .. base} data.forms[prefix .. "poss_mod_c5" ] = {"lika" .. base} data.forms[prefix .. "poss_mod_c6" ] = { "ka" .. base} data.forms[prefix .. "poss_mod_c7" ] = {"sika" .. base} data.forms[prefix .. "poss_mod_c8" ] = {"zika" .. base} data.forms[prefix .. "poss_mod_c9" ] = { "ka" .. base} data.forms[prefix .. "poss_mod_c10"] = {"zika" .. base} data.forms[prefix .. "poss_mod_c11"] = {"luka" .. base} data.forms[prefix .. "poss_mod_c14"] = {"buka" .. base} data.forms[prefix .. "poss_mod_c15"] = {"kuka" .. base} data.forms[prefix .. "poss_mod_c17"] = {"kuka" .. base} data.forms[prefix .. "poss_subst_c1" ] = { "oka" .. base} data.forms[prefix .. "poss_subst_c2" ] = {"abaka" .. base} data.forms[prefix .. "poss_subst_c3" ] = { "oka" .. base} data.forms[prefix .. "poss_subst_c4" ] = { "eka" .. base} data.forms[prefix .. "poss_subst_c5" ] = {"elika" .. base} data.forms[prefix .. "poss_subst_c6" ] = { "aka" .. base} data.forms[prefix .. "poss_subst_c7" ] = {"esika" .. base} data.forms[prefix .. "poss_subst_c8" ] = {"ezika" .. base} data.forms[prefix .. "poss_subst_c9" ] = { "eka" .. base} data.forms[prefix .. "poss_subst_c10"] = {"ezika" .. base} data.forms[prefix .. "poss_subst_c11"] = {"oluka" .. base} data.forms[prefix .. "poss_subst_c14"] = {"obuka" .. base} data.forms[prefix .. "poss_subst_c15"] = {"okuka" .. base} data.forms[prefix .. "poss_subst_c17"] = {"okuka" .. base} else local w		if mw.ustring.find(base, "^[ou]") then base = mw.ustring.gsub(base, "^u", "o") w = "" elseif mw.ustring.find(base, "^[ai]") then base = mw.ustring.gsub(base, "^i", "e") w = "w" else base = "a" .. base w = "w" end data.forms[prefix .. "poss_mod_c1" ] = {m_common.apply_tone("w" .. base, tone)} data.forms[prefix .. "poss_mod_c2" ] = {m_common.apply_tone("b" .. base, tone)} data.forms[prefix .. "poss_mod_c3" ] = {m_common.apply_tone("w" .. base, tone)} data.forms[prefix .. "poss_mod_c4" ] = {m_common.apply_tone("y" .. base, tone)} data.forms[prefix .. "poss_mod_c5" ] = {m_common.apply_tone("l" .. base, tone)} data.forms[prefix .. "poss_mod_c6" ] = {m_common.apply_tone(base, tone)} data.forms[prefix .. "poss_mod_c7" ] = {m_common.apply_tone("s" .. base, tone)} data.forms[prefix .. "poss_mod_c8" ] = {m_common.apply_tone("z" .. base, tone)} data.forms[prefix .. "poss_mod_c9" ] = {m_common.apply_tone("y" .. base, tone)} data.forms[prefix .. "poss_mod_c10"] = {m_common.apply_tone("z" .. base, tone)} data.forms[prefix .. "poss_mod_c11"] = {m_common.apply_tone("l" .. w .. base, tone)} data.forms[prefix .. "poss_mod_c14"] = {m_common.apply_tone("b" .. base, tone)} data.forms[prefix .. "poss_mod_c15"] = {m_common.apply_tone("k" .. w .. base, tone)} data.forms[prefix .. "poss_mod_c17"] = {m_common.apply_tone("k" .. w .. base, tone)} data.forms[prefix .. "poss_subst_c1" ] = {m_common.apply_tone("ow" .. base, tone_subst)} data.forms[prefix .. "poss_subst_c2" ] = {m_common.apply_tone("ab" .. base, tone_subst)} data.forms[prefix .. "poss_subst_c3" ] = {m_common.apply_tone("ow" .. base, tone_subst)} data.forms[prefix .. "poss_subst_c4" ] = {m_common.apply_tone("ey" .. base, tone_subst)} data.forms[prefix .. "poss_subst_c5" ] = {m_common.apply_tone("el" .. base, tone_subst)} data.forms[prefix .. "poss_subst_c6" ] = {m_common.apply_tone("aw" .. base, tone_subst)} data.forms[prefix .. "poss_subst_c7" ] = {m_common.apply_tone("es" .. base, tone_subst)} data.forms[prefix .. "poss_subst_c8" ] = {m_common.apply_tone("ez" .. base, tone_subst)} data.forms[prefix .. "poss_subst_c9" ] = {m_common.apply_tone("ey" .. base, tone_subst)} data.forms[prefix .. "poss_subst_c10"] = {m_common.apply_tone("ez" .. base, tone_subst)} data.forms[prefix .. "poss_subst_c11"] = {m_common.apply_tone("ol" .. w .. base, tone_subst)} data.forms[prefix .. "poss_subst_c14"] = {m_common.apply_tone("ob" .. base, tone_subst)} data.forms[prefix .. "poss_subst_c15"] = {m_common.apply_tone("ok" .. w .. base, tone_subst)} data.forms[prefix .. "poss_subst_c17"] = {m_common.apply_tone("ok" .. w .. base, tone_subst)} end end

local function forms(data, n, class, base, shortloc, loc) -- Full form data.forms[n .. "_full"] = {base} -- Simple form simple(data, base, n, class) -- Locative if class == "1" or class == "1a" or class == "2" or class == "2a" then locative_ku(data, base, n)	elseif shortloc then locative_e(data, base, n, class) elseif loc then data.forms[n .. "_loc"] = {loc} else local loc = locative_extend(base) locative_e(data, loc, n, class) end -- Copulative copulative(data, base, n, class) -- Possessive forms possessive(data, base, n, class == "1a") end

function export.noun(frame) local params = { [1] = {default = mw.title.getCurrentTitle.nsText == "Template" and "L" or nil}, [2] = {required = true, default = "1"}, [3] = {default = mw.title.getCurrentTitle.nsText == "Template" and "2" or nil}, [4] = {default = mw.title.getCurrentTitle.nsText == "Template" and "abantu" or nil}, ["shortloc"] = {type = "boolean"}, ["loc_sg"] = {default = false}, ["loc_pl"] = {default = false} }	local args = require("Module:parameters").process(frame:getParent.args, params) local data = {forms = {}, info = "", categories = {lang:getCanonicalName .. " class " .. args[2] .. " nouns"}} if args[1] then table.insert(data.categories, lang:getCanonicalName .. " nouns with tone " .. args[1]) else table.insert(data.categories, "Requests for tone in " .. lang:getCanonicalName .. " noun entries") end data.info = "class " .. args[2] .. (args[3] and "/" .. args[3] or "") if args[2] == "2" or args[2] == "2a" or args[2] == "4" or args[2] == "6" or args[2] == "8" or args[2] == "10" then if args[3] or args[4] then error("Nouns of plural classes cannot have plural forms.") end forms(data, "pl", args[2], mw.title.getCurrentTitle.subpageText, args["shortloc"], args["loc_pl"]) table.insert(data.categories, lang:getCanonicalName .. " pluralia tantum") else forms(data, "sg", args[2], mw.title.getCurrentTitle.subpageText, args["shortloc"], args["loc_sg"]) -- Plural if args[3] then forms(data, "pl", args[3], args[4], args["shortloc"], args["loc_pl"]) else table.insert(data.categories, lang:getCanonicalName .. " singularia tantum") end end if args["shortloc"] then data.info = data.info .. ", short locative" table.insert(data.categories, lang:getCanonicalName .. " nouns with short locative") end return make_table(data) .. m_utilities.format_categories(data.categories, lang, (makeSortKey(mw.title.getCurrentTitle.subpageText, args[2]))) end

function export.pron(frame) local params = { [1] = {},		[2] = {},		[3] = {},		[4] = {},		[5] = {},		["head"] = {}, }	local args = require("Module:parameters").process(frame:getParent.args, params) local data = {forms = {}, info = "", categories = {}} data.pron = true if args[1] then table.insert(data.categories, lang:getCanonicalName .. " pronouns with tone " .. args[1]) else table.insert(data.categories, "Requests for tone in " .. lang:getCanonicalName .. " pronoun entries") end local base = m_common.apply_tone(args["head"] or mw.title.getCurrentTitle.subpageText, args[1]) local stem = args[2] and m_common.apply_tone(args[2], args[3]) or base local pstem = args[4] and m_common.apply_tone(args[4], args[5]) or stem data.info = "stem " .. m_links.full_link({lang = lang, alt = "-" .. stem}, "term") if args[4] then data.info = data.info .. ", poss. stem " .. m_links.full_link({lang = lang, alt = "-" .. pstem}, "term") end data.forms["full"] = {base}

if args[3] then locative_ku(data, stem, nil, "H" .. args[3]) copulative(data, stem, nil, nil, "H" .. args[3]) else locative_ku(data, stem) copulative(data, stem) end if stem == "mi" or stem == "we" then possessive(data, pstem, nil, nil, "HL") elseif pstem == "ithu" or stem == "inu" then possessive(data, pstem, nil, nil, "FL") else if args[5] then possessive(data, pstem, nil, nil, "FL") else possessive(data, pstem) end end return make_table(data) .. m_utilities.format_categories(data.categories, lang) end

-- Make the table function make_table(data) local function repl(param) if param == "info" then return mw.getContentLanguage:ucfirst(data.info or "") end local form = data.forms[param] if not form or #form == 0 then return "&mdash;" end local ret = {} for key, subform in ipairs(form) do			table.insert(ret, m_links.full_link({lang = lang, term = subform})) end return table.concat(ret, ", ") end local names = { ["full"] = "full form", ["simp"] = "simple form", ["loc"] = "locative", ["cop"] = "copulative", ["sg"] = "singular", ["pl"] = "plural", ["mod"] = "modifier", ["subst"] = "substantive", ["c1"] = "class 1", ["c2"] = "class 2", ["c3"] = "class 3", ["c4"] = "class 4", ["c5"] = "class 5", ["c6"] = "class 6", ["c7"] = "class 7", ["c8"] = "class 8", ["c9"] = "class 9", ["c10"] = "class 10", ["c11"] = "class 11", ["c14"] = "class 14", ["c15"] = "class 15", ["c17"] = "class 17", }	local columns = {"mod", "subst"} local numbers = {"sg", "pl"} local cases = {"full", "simp", "loc", "cop"} local classes = {"c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11", "c14", "c15", "c17"} if data.pron then numbers = {""} cases = {"full", "loc", "cop"} end local wikicode = {} table.insert(wikicode, "{| class=\"wikitable inflection-table vsSwitcher\" data-toggle-category=\"inflection\" style=\"border-style: double; border-width: 3px; margin: 0;\"") table.insert(wikicode, "|-") table.insert(wikicode, "! class=\"vsToggleElement\" style=\"background: #CCC; text-align: left;\" colspan=\"" .. tostring(#numbers * #columns + 1) .. "\" | ") if not data.pron then table.insert(wikicode, "|- class=\"vsShow\"") table.insert(wikicode, "|") for _, number in ipairs(numbers) do table.insert(wikicode, "! " .. mw.getContentLanguage:ucfirst(names[number])) end end for _, case in ipairs({"full", "loc"}) do		table.insert(wikicode, "|- class=\"vsShow\"") table.insert(wikicode, "! style=\"min-width: 8em;\" | " .. mw.getContentLanguage:ucfirst(names[case])) if data.pron then table.insert(wikicode, "| style=\"min-width: 10em;\" | ") else for _, number in ipairs(numbers) do				table.insert(wikicode, "| style=\"min-width: 10em;\" | ") end end end if not data.pron then table.insert(wikicode, "|- class=\"vsHide\"") table.insert(wikicode, "|") for _, number in ipairs(numbers) do table.insert(wikicode, "! colspan=\"" .. tostring(#columns) .. "\" | " .. mw.getContentLanguage:ucfirst(names[number])) end end for _, case in ipairs(cases) do		table.insert(wikicode, "|- class=\"vsHide\"") table.insert(wikicode, "! style=\"min-width: 8em;\" | " .. mw.getContentLanguage:ucfirst(names[case])) if data.pron then table.insert(wikicode, "| colspan=\"" .. tostring(#columns) .. "\" | ") else for _, number in ipairs(numbers) do table.insert(wikicode, "| colspan=\"" .. tostring(#columns) .. "\" | ") end end end table.insert(wikicode, "|- class=\"vsHide\"") table.insert(wikicode, "! colspan=\"" .. tostring(#numbers * #columns + 1) .. "\" | Possessive forms") if not data.pron then table.insert(wikicode, "|- class=\"vsHide\"") table.insert(wikicode, "|") for _, number in ipairs(numbers) do table.insert(wikicode, "! colspan=\"" .. tostring(#columns) .. "\" | " .. mw.getContentLanguage:ucfirst(names[number])) end end table.insert(wikicode, "|- class=\"vsHide\"") table.insert(wikicode, "|") for _, number in ipairs(numbers) do		for _, column in ipairs(columns) do table.insert(wikicode, "! style=\"min-width: 8em;\" | " .. mw.getContentLanguage:ucfirst(names[column])) end end for _, class in ipairs(classes) do		table.insert(wikicode, "|- class=\"vsHide\"") table.insert(wikicode, "! " .. mw.getContentLanguage:ucfirst(names[class])) for _, number in ipairs(numbers) do			for _, column in ipairs(columns) do				table.insert(wikicode, "| ") end end end table.insert(wikicode, "|}") wikicode = table.concat(wikicode, "\n") return mw.ustring.gsub(wikicode, "", repl) end

return export