Module:gmw-noun

From Wiktionary, the free dictionary
Jump to navigation Jump to search
This module needs documentation.
Please document this module by describing its purpose and usage on the documentation page.

local lang = require("Module:languages").getByCode("gmw-pro")

local export = {}

local genders = {
	["m"] = "masculine",
	["f"] = "feminine",
	["n"] = "neuter",
}

local function detect_j(stem)
	-- match long vowel or diphthong followed by consonants
	local rest, nucleus, coda = mw.ustring.match(stem, "^(.-)([āēīōūąįų]?̄?[aeiou]*)([bdfghjklmnprʀstþw]+)$")

	if not rest or nucleus == "" then
		error("Stem does not end in a vowel or diphthong followed by consonants")
	elseif mw.ustring.len(coda) > 1 or mw.ustring.find(nucleus, "^[āēīōūąįų]̄?$") or mw.ustring.find(nucleus, "^[aeiou][aeiou]$") then
		return "ij"
	elseif mw.ustring.find(rest, "^[bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW]*$") then
		return "j"
	else
		error("Stem consists of multiple syllables or its weight cannot be otherwise be determined")
	end
end

local function geminate(stem)
	stem = mw.ustring.gsub(stem, "w$", "uw")
	stem = mw.ustring.gsub(stem, "([bdghklmnpstþ])$", "%1%1")
	return stem
end

-- Inflection functions

function export.a(frame)
	local params = {
		[1] = {default = mw.title.getCurrentTitle().nsText == "Template" and "{{{1}}}" or mw.title.getCurrentTitle().subpageText},
		
		["g"] = {required = true, default = "m"},
		["n"] = {},
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	if not (args["g"] == "m" or args["g"] == "n") then
		error("g= must be m or n")
	end
	
	local data = {
		forms = {},
		info = nil,
		categories = {},
	}

	local stem, suffix = mw.ustring.match(args[1], "^(.-)([iīu])$")
	local stem_u

	if suffix == "ī" then
		stem = stem .. "ij"
		data.info = "''ja''-stem"
		table.insert(data.categories, lang:getCanonicalName() .. " " .. genders[args["g"]] .. " ja-stem nouns")
	elseif suffix == "i" then
		stem = geminate(stem) .. "j"
		data.info = "''ja''-stem"
		table.insert(data.categories, lang:getCanonicalName() .. " " .. genders[args["g"]] .. " ja-stem nouns")
	elseif suffix == "u" then
		stem_u = stem
		stem = stem .. "w"
		data.info = "''wa''-stem"
		table.insert(data.categories, lang:getCanonicalName() .. " " .. genders[args["g"]] .. " wa-stem nouns")
	else
		stem = args[1]
		data.info = "''a''-stem"
		table.insert(data.categories, lang:getCanonicalName() .. " " .. genders[args["g"]] .. " a-stem nouns")
	end
	
	stem_u = stem_u or stem
	data.info = genders[args["g"]] .. " " .. data.info
	
	data.forms["nom|s"] = {args[1]}
	data.forms["acc|s"] = data.forms["nom|s"]
	data.forms["gen|s"] = {stem .. "as"}
	data.forms["dat|s"] = {stem .. "ē"}
	data.forms["ins|s"] = {stem_u .. "u"}
	
	data.forms["nom|p"] = args["g"] == "n" and {stem_u .. "u"} or {stem .. "ō", stem .. "ōs"}
	data.forms["acc|p"] = args["g"] == "n" and {stem_u .. "u"} or {stem .. "ā"}
	data.forms["gen|p"] = {stem .. "ō"}
	data.forms["dat|p"] = {stem_u .. "um"}
	data.forms["ins|p"] = data.forms["dat|p"]

	postprocess(args, data)
	return make_table(data)
end

function export.an(frame)
	local params = {
		[1] = {default = mw.title.getCurrentTitle().nsText == "Template" and "{{{1}}}ō" or mw.title.getCurrentTitle().subpageText},
		
		["n"] = {},
		["wk"] = {},
	}

	local args = require("Module:parameters").process(frame:getParent().args, params)

	local stem, suffix = mw.ustring.match(args[1], "^(.-)([āō])$")
	local g

	if suffix == "ā" then
		g = "n"
	elseif suffix == "ō" then
		g = "m"
	else
		error("an-stems must end in -ō or -ā")
	end
	
	local data = {
		forms = {},
		info = "''an''-stem",
		categories = {lang:getCanonicalName() .. " " .. genders[g] .. " an-stem nouns"},
	}

	data.info = genders[g] .. " " .. data.info
	
	if args["wk"] then
		stem_weak = args["wk"]
		
		table.insert(data.categories, lang:getCanonicalName() .. " irregular nouns")
	else
		stem_weak = stem
	end
	
	data.forms["nom|s"] = {args[1]}
	data.forms["acc|s"] = g == "n" and {args[1]} or {stem .. "an"}
	data.forms["gen|s"] = {stem_weak .. "ini", stem_weak .. "an"}
	data.forms["dat|s"] = data.forms["gen|s"]
	data.forms["ins|s"] = data.forms["gen|s"]
	
	data.forms["nom|p"] = g == "n" and {stem .. "ōn"} or {stem .. "an"}
	data.forms["acc|p"] = data.forms["nom|p"]
	data.forms["gen|p"] = {stem_weak .. "anō"}
	data.forms["dat|p"] = {stem_weak .. "um"}
	data.forms["ins|p"] = data.forms["dat|p"]

	postprocess(args, data)
	return make_table(data)
end

function export.cons(frame)
	local params = {
		[1] = {default = mw.title.getCurrentTitle().nsText == "Template" and "{{{1}}}" or mw.title.getCurrentTitle().subpageText},
		
		["n"] = {},
		["ns"] = {},
		["wk"] = {},
	}

	local args = require("Module:parameters").process(frame:getParent().args, params)

	local data = {
		forms = {},
		info = "consonant stem",
		categories = {lang:getCanonicalName() .. " consonant stem nouns"},
	}
	
	if args["wk"] then
		stem_weak = args["wk"]
		
		table.insert(data.categories, lang:getCanonicalName() .. " irregular nouns")
	else
		stem_weak = args[1]
	end
	
	if args["ns"] then
		table.insert(data.categories, lang:getCanonicalName() .. " irregular nouns")
	end

	data.forms["nom|s"] = {args["ns"] or args[1]}
	data.forms["acc|s"] = {args["ns"] or args[1] .. "u"}
	data.forms["gen|s"] = {stem_weak .. "i"}
	data.forms["dat|s"] = data.forms["gen|s"]
	data.forms["ins|s"] = data.forms["gen|s"]
	
	data.forms["nom|p"] = {args[1] .. "i"}
	data.forms["acc|p"] = data.forms["nom|p"]
	data.forms["gen|p"] = {stem_weak .. "ō"}
	data.forms["dat|p"] = {stem_weak .. "um"}
	data.forms["ins|p"] = data.forms["dat|p"]

	postprocess(args, data)
	return make_table(data)
end

function export.i(frame)
	local params = {
		[1] = {default = mw.title.getCurrentTitle().nsText == "Template" and "{{{1}}}i" or mw.title.getCurrentTitle().subpageText},

		["j"] = {default = mw.title.getCurrentTitle().nsText == "Template" and "ij" or nil},
		["n"] = {},
		["wk"] = {},
	}

	local args = require("Module:parameters").process(frame:getParent().args, params)

	local data = {
		forms = {},
		info = nil,
		categories = {},
	}

	local stem, suffix = mw.ustring.match(args[1], "^(.-)(i)$")
	local stem_j, stem_weak_j
	
	if args["wk"] then
		stem_weak = args["wk"]
		
		table.insert(data.categories, lang:getCanonicalName() .. " irregular nouns")
	else
		stem_weak = stem
	end
	
	if suffix == "i" then
		if (args["j"] or detect_j(stem)) == "ij" then
			stem_j = stem .. "ij"
			stem_weak_j = stem_weak .. "ij"
		else
			stem_j = geminate(stem) .. "j"
			stem_weak_j = geminate(stem_weak) .. "j"
		end
	else
		error("i-stems must end in -i")
	end
	
	data.info = "''i''-stem"
	table.insert(data.categories, lang:getCanonicalName() .. " i-stem nouns")
	
	data.forms["nom|s"] = {args[1]}
	data.forms["acc|s"] = data.forms["nom|s"]
	data.forms["gen|s"] = {stem_weak .. "ī"}
	data.forms["dat|s"] = data.forms["gen|s"]
	data.forms["ins|s"] = data.forms["gen|s"]
	
	data.forms["nom|p"] = {stem .. "ī"}
	data.forms["acc|p"] = data.forms["nom|p"]
	data.forms["gen|p"] = {stem_weak_j .. "ō"}
	data.forms["dat|p"] = {stem_weak .. "im", stem_weak_j .. "um"}
	data.forms["ins|p"] = data.forms["dat|p"]

	postprocess(args, data)
	return make_table(data)
end

export["in"] = function(frame)
	local params = {
		[1] = {default = mw.title.getCurrentTitle().nsText == "Template" and "{{{1}}}ī" or mw.title.getCurrentTitle().subpageText},

		["n"] = {},
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)

	local data = {
		forms = {},
		info = "''īn''-stem",
		categories = {lang:getCanonicalName() .. " īn-stem nouns"},
	}

	local stem, suffix = mw.ustring.match(args[1], "^(.-)(ī)$")

	if suffix ~= "ī" then
		error("īn-stems must end in -ī")
	end
	
	data.forms["nom|s"] = {args[1]}
	data.forms["acc|s"] = {stem .. "īn"}
	data.forms["gen|s"] = data.forms["acc|s"]
	data.forms["dat|s"] = data.forms["acc|s"]
	data.forms["ins|s"] = data.forms["acc|s"]

	postprocess(args, data)
	return make_table(data)
end

function export.o(frame)
	local params = {
		[1] = {default = mw.title.getCurrentTitle().nsText == "Template" and "{{{1}}}u" or mw.title.getCurrentTitle().subpageText},

		["j"] = {},
		["n"] = {},
		["w"] = {type = "boolean"},
	}

	local args = require("Module:parameters").process(frame:getParent().args, params)

	local data = {
		forms = {},
		info = nil,
		categories = {},
	}

	local stem, suffix = mw.ustring.match(args[1], "^(.-)([iu])$")
	local stem_u

	if suffix == "i" then
		if (args["j"] or detect_j(stem)) == "ij" then
			stem = stem .. "ij"
		elseif mw.ustring.match(stem, "^(.-)([bdfghjklmnprʀstþw-]+)(in)$") then
			stem = mw.ustring.gsub(stem, "in$", "unn") .. "j"
		else
			stem = geminate(stem) .. "j"
		end

		data.info = "''ī''/''jō''-stem"
		table.insert(data.categories, lang:getCanonicalName() .. " ī/jō-stem nouns")
	elseif suffix == "u" then
		if args["w"] then
			stem_u = stem
			stem = stem .. "w"
			data.info = "''wō''-stem"
			table.insert(data.categories, lang:getCanonicalName() .. " wō-stem nouns")
		else
			data.info = "''ō''-stem"
			table.insert(data.categories, lang:getCanonicalName() .. " ō-stem nouns")
		end
	else
		error("ō-stems must end in -i or -u")
	end

	stem_u = stem_u or stem

	data.forms["nom|s"] = {args[1]}
	data.forms["acc|s"] = {stem .. "ā"}
	data.forms["gen|s"] = data.forms["acc|s"]
	data.forms["dat|s"] = {stem .. "ē"}
	data.forms["ins|s"] = {stem_u .. "u"}
	
	data.forms["nom|p"] = {stem .. "ō"}
	data.forms["acc|p"] = {stem .. "ā"}
	data.forms["gen|p"] = {stem .. "ō"}
	data.forms["dat|p"] = {stem .. "ōm", stem_u .. "um"}
	data.forms["ins|p"] = data.forms["dat|p"]

	postprocess(args, data)
	return make_table(data)
end

function export.on(frame)
	local params = {
		[1] = {default = mw.title.getCurrentTitle().nsText == "Template" and "{{{1}}}ā" or mw.title.getCurrentTitle().subpageText},

		["n"] = {},
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)

	local data = {
		forms = {},
		info = "''ōn''-stem",
		categories = {lang:getCanonicalName() .. " ōn-stem nouns"},
	}

	local stem, suffix = mw.ustring.match(args[1], "^(.-)(ā)$")

	if suffix ~= "ā" then
		error("ōn-stems must end in -ā")
	end
	
	data.forms["nom|s"] = {args[1]}
	data.forms["acc|s"] = {stem .. "ōn"}
	data.forms["gen|s"] = data.forms["acc|s"]
	data.forms["dat|s"] = data.forms["acc|s"]
	data.forms["ins|s"] = data.forms["acc|s"]
	
	data.forms["nom|p"] = data.forms["acc|s"]
	data.forms["acc|p"] = data.forms["acc|s"]
	data.forms["gen|p"] = {stem .. "ōnō"}
	data.forms["dat|p"] = {stem .. "ōm", stem .. "um"}
	data.forms["ins|p"] = data.forms["dat|p"]

	postprocess(args, data)
	return make_table(data)
end

function export.r(frame)
	local params = {
		[1] = {default = mw.title.getCurrentTitle().nsText == "Template" and "{{{1}}}er" or mw.title.getCurrentTitle().subpageText},

		["n"] = {},
	}

	local args = require("Module:parameters").process(frame:getParent().args, params)

	local data = {
		forms = {},
		info = "r-stem",
		categories = {lang:getCanonicalName() .. " r-stem nouns"},
	}

	local stem, suffix = mw.ustring.match(args[1], "^(.-)(er)$")

	if suffix ~= "er" then
		error("r-stems must end in -er")
	end
	
	data.forms["nom|s"] = {args[1]}
	data.forms["acc|s"] = {stem .. "ar"}
	data.forms["gen|s"] = {stem .. "ur"}
	data.forms["dat|s"] = {stem .. "ri"}
	data.forms["ins|s"] = data.forms["dat|s"]
	
	data.forms["nom|p"] = {stem .. "ar"}
	data.forms["acc|p"] = data.forms["nom|p"]
	data.forms["gen|p"] = {stem .. "rō"}
	data.forms["dat|p"] = {stem .. "rum"}
	data.forms["ins|p"] = data.forms["dat|p"]

	postprocess(args, data)
	return make_table(data)
end

function export.u(frame)
	local params = {
		[1] = {default = mw.title.getCurrentTitle().nsText == "Template" and "{{{1}}}u" or mw.title.getCurrentTitle().subpageText},

		["n"] = {},
	}

	local args = require("Module:parameters").process(frame:getParent().args, params)

	local data = {
		forms = {},
		info = nil,
		categories = {},
	}

	local stem, suffix = mw.ustring.match(args[1], "^(.-)(u)$")

	if suffix ~= "u" then
		error("u-stems must end in -u")
	end
	
	data.info = "''u''-stem"
	table.insert(data.categories, lang:getCanonicalName() .. " u-stem nouns")
	
	data.forms["nom|s"] = {args[1]}
	data.forms["acc|s"] = data.forms["nom|s"]
	data.forms["gen|s"] = {stem .. "ō"}
	data.forms["dat|s"] = {stem .. "iwi", stem .. "ō"}
	data.forms["ins|s"] = {stem .. "u"}

	data.forms["nom|p"] = {stem .. "iwi", stem .. "ō"}
	data.forms["acc|p"] = {stem .. "ū"}
	data.forms["gen|p"] = {stem .. "iwō"}
	data.forms["dat|p"] = {stem .. "um"}
	data.forms["ins|p"] = data.forms["dat|p"]

	postprocess(args, data)
	return make_table(data)
end

function export.z(frame)
	local params = {
		[1] = {default = mw.title.getCurrentTitle().nsText == "Template" and "{{{1}}}" or mw.title.getCurrentTitle().subpageText},

		["n"] = {},
		["ns"] = {},
	}

	local args = require("Module:parameters").process(frame:getParent().args, params)

	local data = {
		forms = {},
		info = "''z''-stem",
		categories = {lang:getCanonicalName() .. " z-stem nouns"},
	}
	
	local stem_i = mw.ustring.gsub(args[1], "e(u?[bdfghklmnprʀstþw]*)$", "i%1")
	
	if args["ns"] then
		table.insert(data.categories, lang:getCanonicalName() .. " irregular nouns")
	end

	data.forms["nom|s"] = {args["ns"] or args[1]}
	data.forms["acc|s"] = data.forms["nom|s"]
	data.forms["gen|s"] = {stem_i .. "iʀi"}
	data.forms["dat|s"] = data.forms["gen|s"]
	data.forms["ins|s"] = data.forms["gen|s"]
	
	data.forms["nom|p"] = {stem_i .. "iʀu"}
	data.forms["acc|p"] = data.forms["nom|p"]
	data.forms["gen|p"] = {stem_i .. "iʀō"}
	data.forms["dat|p"] = {stem_i .. "iʀum"}
	data.forms["ins|p"] = data.forms["dat|p"]

	postprocess(args, data)
	return make_table(data)
end

function postprocess(args, data)
	data.n = args["n"]
	
	if args["n"] == "p" then
		table.insert(data.categories, lang:getCanonicalName() .. " pluralia tantum")
	elseif args["n"] == "s" then
		table.insert(data.categories, lang:getCanonicalName() .. " singularia tantum")
	elseif args["n"] then
		error("args= must be \"s\" or \"p\".")
	end

	for key, form in pairs(data.forms) do
		-- Do not show singular or plural forms for nominals that don't have them
		if (args["n"] == "p" and key:find("|s$")) or (args["n"] == "s" and key:find("|p$")) then
			form = nil
		end

		data.forms[key] = form
	end
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 forms = data.forms[param]
		
		if not forms then
			return "—"
		end
		
		local ret = {}
		
		for key, subform in ipairs(forms) do
			
			-- i-umlaut
			if mw.ustring.find(subform, "[iīįǐj]") then
			    subform = mw.ustring.gsub(subform, "([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW])e(u?)([bdfghjklmnprʀstþw]+)([iīįj])", "%1i%2%3%4")
			    subform = mw.ustring.gsub(subform, "([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW])o([bdfghjklmnprʀstþw]+)([iīįj])", "%1u%2%3")
			end
			
			-- *u[+stress] > *o /{C,#}_C[-nasal]V[+back]
			if mw.ustring.find(subform, "u") then
			    subform = mw.ustring.gsub(subform, "^([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW]+)u([bdfghklprʀstþw]+)([aoāōą])", "%1o%2%3")
			end
			
			-- *w > ∅ /V́_*u
			if mw.ustring.find(subform, "[aeiouāēīōūAEIOUĀĒĪŌŪ]wu") then
				subform = mw.ustring.gsub(subform, "^([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW]*)uwu", "%1ū")
			    subform = mw.ustring.gsub(subform, "^([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW]*)([aeiouāēīōūAEIOUĀĒĪŌŪ])w(u)", "%1%2%3")
			end
			
			-- Mahlow's Law (*ōu > *ō / _C{#,V})
			if mw.ustring.find(subform, "ō[uw]") then
			    subform = mw.ustring.gsub(subform, "(ō)[uw]", "%1")
			end
			
			if mw.ustring.find(subform, "ū[uw]") then
			    subform = mw.ustring.gsub(subform, "(ū)[uw]", "%1")
			end
			
			-- C[+plosive -voice] > CC /_LV (Ringe 2014:54)
			if mw.ustring.find(subform, "[ptkh][lr]") then
			    subform = mw.ustring.gsub(subform, "([aeiouāēīōūAEIOUĀĒĪŌŪ])([ptkh])([lr][aeiouāēīōūąįų])", "%1%2%2%3")
			end
			
			table.insert(ret, require("Module:links").full_link({lang = lang, alt = "*" .. subform}))
		end
		
		return table.concat(ret, ", ")
	end
	
	local wikicode = {}
	table.insert(wikicode, [=[
{| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="border: solid 1px #CCCCCC;"
|- style="background: #CCCCCC; text-align: left;"
! class="vsToggleElement" colspan="3" | {{{info}}}
|- class="vsShow"
! style="width: 9em;" |
! style="width: 15em; background: #DDDDDD;" colspan="2" | Singular
|- class="vsShow"
! style="background: #EEEEEE" | Nominative
| colspan="2" | {{{nom|s}}}
|- class="vsShow"
! style="background: #EEEEEE" | Genitive
| colspan="2" | {{{gen|s}}}
|- class="vsHide"
| style="width: 9em;" |
! style="width: 15em; background: #DDDDDD;" | Singular
! style="width: 15em; background: #DDDDDD;" | Plural
|- class="vsHide"
! style="background: #EEEEEE" | Nominative
| {{{nom|s}}}
| {{{nom|p}}}
|- class="vsHide"
! style="background: #EEEEEE" | Accusative
| {{{acc|s}}}
| {{{acc|p}}}
|- class="vsHide"
! style="background: #EEEEEE" | Genitive
| {{{gen|s}}}
| {{{gen|p}}}
|- class="vsHide"
! style="background: #EEEEEE" | Dative
| {{{dat|s}}}
| {{{dat|p}}}
|- class="vsHide"
! style="background: #EEEEEE" | Instrumental
| {{{ins|s}}}
| {{{ins|p}}}
|}]=])

	return mw.ustring.gsub(table.concat(wikicode), "{{{([#!]?[a-z0-9|]+)}}}", repl) .. require("Module:utilities").format_categories(data.categories, lang)
end

return export