Module:se-common

Definition from Wiktionary, the free dictionary
Jump to navigation Jump to search
Text-x-generic with pencil.svg This module needs documentation.
Please document this module by describing its purpose and usage on the documentation page.

local export = {}


local consonants = {
	-- Single consonants
	{[3] = "hpp", [2] = "hp", [1] = "b"},
	{[3] = "htt", [2] = "ht", [1] = "đ"},
	{[3] = "hcc", [2] = "hc", [1] = "z"},
	{[3] = "hčč", [2] = "hč", [1] = "ž"},
	{[3] = "hkk", [2] = "hk", [1] = "g"},
	
	{[3] = "đˈđ", [2] = "đđ", [1] = "đ"},
	{[3] = "fˈf", [2] = "ff", [1] = "f"},
	{[3] = "hjˈj", [2] = "hjj", [1] = "hj"},
	{[3] = "hlˈl", [2] = "hll", [1] = "hl"},
	{[3] = "hmˈm", [2] = "hmm", [1] = "hm"},
	{[3] = "hnˈn", [2] = "hnn", [1] = "hn"},
	{[3] = "hrˈr", [2] = "hrr", [1] = "hr"},
	{[3] = "lˈl", [2] = "ll", [1] = "l"},
	{[3] = "mˈm", [2] = "mm", [1] = "m"},
	{[3] = "nˈn", [2] = "nn", [1] = "n"},
	{[3] = "nˈnj", [2] = "nnj", [1] = "nj"},
	{[3] = "ŋˈŋ", [2] = "ŋŋ", [1] = "ŋ"},
	{[3] = "ŋˈŋ", [2] = "ŋŋ", [1] = "ŋ"},
	{[3] = "rˈr", [2] = "rr", [1] = "r"},
	{[3] = "sˈs", [2] = "ss", [1] = "s"},
	{[3] = "šˈš", [2] = "šš", [1] = "š"},
	{[3] = "ŧˈŧ", [2] = "ŧŧ", [1] = "ŧ"},
	{[3] = "vˈv", [2] = "vv", [1] = "v"},
	
	{[3] = "bm", [2] = "pm", [1] = "m"},
	{[3] = "dn", [2] = "tn", [1] = "n"},
	{[3] = "dnj", [2] = "tnj", [1] = "nj"},
	{[3] = "gŋ", [2] = "kŋ", [1] = "ŋ"},
	
	{[3] = "ddj", [2] = "dj", [1] = "j"},
	
	-- Clusters
	{[3] = "bb", [2] = "pp"},
	{[3] = "dd", [2] = "tt"},
	{[3] = "zz", [2] = "cc"},
	{[3] = "žž", [2] = "čč"},
	{[3] = "gg", [2] = "kk"},
	
	{[3] = "llj", [2] = "lj"},
	{[3] = "lˈj", [2] = "ljj"},
	
	{[3] = "rbm", [2] = "rpm"},
	{[3] = "rdn", [2] = "rtn"},
	{[3] = "rdnj", [2] = "rtnj"},
	{[3] = "rgŋ", [2] = "rkŋ"},
}


local grades = {{}, {}, {}}

for _, cons in ipairs(consonants) do
	for q, c in pairs(cons) do
		grades[q][c] = cons
	end
end


local vowels_simp = {
	["ea"] = "ē",
	["ie"] = "ī",
	["oa"] = "ō",
	["uo"] = "ū"
}

local stem_variants = {
	normal        = {                                                                  },
	short         = {                           ["i"] = "ẹ" ,              ["u"] = "ọ" },
	e             = {                           ["i"] = "á" ,              ["u"] = "oS"},
	e_contr_j     = {["a"] = "iS", ["e"] = "i", ["i"] = "á" , ["o"] = "u", ["u"] = "uS"},
	i             = {                           ["i"] = "eS",              ["u"] = "oS"},
	j             = {              ["e"] = "i", ["i"] = "iS", ["o"] = "u", ["u"] = "ū" },
	j_contr       = {["a"] = "eS",              ["i"] = "eS",              ["u"] = "oS"},
	j_contr_final = {["a"] = "i" ,                                                     },
	pres_12sg     = {                           ["i"] = "á" ,                          },
	pres_3sg      = {["a"] = "á" ,              ["i"] = "á" ,                          },
}


export.Stem = {}
export.Stem.__index = export.Stem

setmetatable(export.Stem, {__call = function(_, stem, final)
	local self = setmetatable({}, export.Stem)
	self.init = stem
	self.final = final
	
	self.init = mw.ustring.gsub(self.init, "([aáeēiīoōuūy])i$", "%1j")
	self.init, self.fcons = mw.ustring.match(self.init, "^(.-)([^aáeēiīoōuūy{}-]*)$")
	
	if mw.ustring.find(self.init, "[aáeēiīoōuūy]i$") then
		self.init = string.sub(self.init, 1, -2)
		self.fcons = "i" .. self.fcons
	end
	
	self.init, self.vowel = mw.ustring.match(self.init, "^(.-)([aáeēiīoōuūy]?)$")
	self.init, self.cons = mw.ustring.match(self.init, "^(.-)([^aáeēiīoōuūyAÁEĒIĪOŌUŪY{}-]*)$")
	
	if mw.ustring.find(self.init, "[aáeēiīoōuūyAÁEĒIĪOŌUŪY]i$") then
		self.init = string.sub(self.init, 1, -2)
		self.cons = "i" .. self.cons
	end
	
	local diph = string.sub(self.init, -2)
	
	if vowels_simp[mw.ustring.lower(diph)] then
		self.svowel = diph
		self.init = string.sub(self.init, 1, -3)
	else
		self.init, self.svowel = mw.ustring.match(self.init, "^(.-)([aáeēiīoōuūyAÁEĒIĪOŌUŪY]?)$")
	end
	
	return self
end})


function export.Stem:variant(variant, newvowel)
	if variant == "none" then
		if self.fcons ~= "" then
			return export.make_final(self.init .. self.svowel .. self.cons .. self.vowel .. self.fcons, self.final)
		elseif self.final then
			return export.make_final(self.init .. self.svowel .. self.cons)
		else
			return self.init .. self.svowel .. self.cons .. (newvowel or self.vowel)
		end
	end
	
	if self.fcons ~= "" then
		return self.init .. self.svowel .. self.cons .. self.vowel .. self.fcons
	end
	
	if not stem_variants[variant] then
		error("The stem variant \"" .. variant .. "\" does not exist.")
	end
	
	local vowel, tag = mw.ustring.match(stem_variants[variant][newvowel or self.vowel] or newvowel or self.vowel, "^(.-)([A-Z]?)$")
	local svowel = self.svowel
	
	if tag == "S" then
		svowel = vowels_simp[self.svowel] or self.svowel
	end
	
	return self.init .. svowel .. self.cons .. vowel
end


function export.Stem:make_weak()
	if grades[1][self.cons] then
		error("The consonant \"" .. self.cons .. "\" cannot gradate.")
	elseif self.cons == "" then
		return self
	end
	
	local newcons
	
	-- Try the list of predefined consonants first
	for _, q in ipairs({2, 3}) do
		if grades[q][self.cons] then
			newcons = grades[q][self.cons][q-1]
			break
		end
	end
	
	-- We haven't found our consonants among the predefined consonants,
	-- which means we are dealing with a regular consonant cluster.
	if not newcons then
		newcons = mw.ustring.gsub(self.cons, "^k", "v")
		
		if mw.ustring.find(newcons, "bm$") then
			newcons = mw.ustring.gsub(newcons, "bm$", "mm")
		elseif mw.ustring.find(newcons, "dn$") then
			newcons = mw.ustring.gsub(newcons, "dn$", "nn")
		elseif mw.ustring.find(newcons, "dnj$") then
			newcons = mw.ustring.gsub(newcons, "dnj$", "nnj")
		elseif mw.ustring.find(newcons, "gŋ$") then
			newcons = mw.ustring.gsub(newcons, "gŋ$", "ŋŋ")
		else
			newcons = mw.ustring.gsub(newcons, "(.)$", "%1%1")
		end
	end
	
	return export.Stem(self.init .. self.svowel .. newcons .. self.vowel, self.final)
end


function export.Stem:make_extra()
	if grades[1][self.cons] then
		error("The consonant \"" .. self.cons .. "\" cannot gradate.")
	elseif grades[2][self.cons] then
		return export.Stem(self.init .. self.svowel .. grades[2][self.cons][3] .. self.vowel, self.final)
	else
		return self
	end
end


local final_consonants = {
	["b"] = "t", ["hp"] = "t", ["hpp"] = "t",
	["d"] = "t", ["ht"] = "t", ["htt"] = "t",
	["g"] = "t", ["hk"] = "t", ["hkk"] = "t",
	["h"] = "t",
	["j"] = "i",
	["m"] = "n",
	["z"] = "s",
	["ž"] = "š",
	
	["ld"] = "l",
	["lg"] = "l",
	
	["rd"] = "r",
	
	["sk"] = "s",
	["sm"] = "s",
	["st"] = "s",
	
	["št"] = "š",
}

function export.make_final(stem, final)
	if final then
		return (mw.ustring.gsub(stem, "[^aáeēiīoōuūy]+$", final))
	end
	
	-- If the stem ends in a vowel, it's already ok.
	if mw.ustring.find(stem, "[aáeēiīoōuūy]$") then
		return stem
	end
	
	-- If the stem ends in a double consonant, remove one.
	if mw.ustring.find(stem, "[aáeēiīoōuūy]([^aáeēiīoōuūy])%1$") then
		stem = mw.ustring.sub(stem, 1, -2)
	end
	
	-- If the stem now ends in an allowed consonant, it's ok too.
	if mw.ustring.find(stem, "[aáeēiīoōuūy-][lnrsšpt]$") then
		return stem
	end
	
	local base, final = mw.ustring.match(stem, "^(.-)([^aáeēiīoōuūy-]+)$")
	
	if not final_consonants[final] then
		if mw.title.getCurrentTitle().nsText == "Template" then
			return stem
		else
			return nil
		end
	end
	
	return base .. final_consonants[final]
end


return export