বিষয়বস্তুতে চলুন

মডিউল:be-noun-old

উইকিঅভিধান, মুক্ত অভিধান থেকে

এই মডিউলের জন্য মডিউল:be-noun-old/নথি-এ নথিপত্র তৈরি করা হয়ে থাকতে পারে

local strutils = require("Module:string utilities")

local export = {}

templates = {
	["half"] = "be-decl-noun-unc|{nom_sg}|{gen_sg}|{dat_sg}|{acc_sg}|{ins_sg}|{loc_sg}",
	["half_pl"] = "be-decl-noun-pl|{nom_pl}|{gen_pl}|{dat_pl}|{acc_pl}|{ins_pl}|{loc_pl}",
	["full"] = "be-decl-noun|{nom_sg}|{nom_pl}|{gen_sg}|{gen_pl}|{dat_sg}|{dat_pl}|{acc_sg}|{acc_pl}|{ins_sg}|{ins_pl}|{loc_sg}|{loc_pl}"
}

-- Make the table
function make_table(args)
	local temp = nil

	if args.n == "s" then
		temp = "half"
	elseif args.n == "p" then
		temp = "half_pl"
	else
		temp = "full"
	end

	return strutils.format(templates[temp], args)
end

-- "s" – lexical accent somewhere on the stem
-- "e" – accent on the ending
-- "1" – accent on the first syllable of the word
-- "<" – accent on the last syllable of the stem
accent_curves = {
	["a"] = { ["nom_sg"] = "s", ["gen_sg"] = "s", ["dat_sg"] = "s", ["acc_sg"] = "s", ["ins_sg"] = "s", ["loc_sg"] = "s",
              ["nom_pl"] = "s", ["gen_pl"] = "s", ["dat_pl"] = "s", ["acc_pl"] = "s", ["ins_pl"] = "s", ["loc_pl"] = "s" },
	["b"] = { ["nom_sg"] = "e", ["gen_sg"] = "e", ["dat_sg"] = "e", ["acc_sg"] = "e", ["ins_sg"] = "e", ["loc_sg"] = "e",
              ["nom_pl"] = "e", ["gen_pl"] = "e", ["dat_pl"] = "e", ["acc_pl"] = "e", ["ins_pl"] = "e", ["loc_pl"] = "e" },
	["c"] = { ["nom_sg"] = "1", ["gen_sg"] = "1", ["dat_sg"] = "1", ["acc_sg"] = "1", ["ins_sg"] = "1", ["loc_sg"] = "1",
              ["nom_pl"] = "e", ["gen_pl"] = "e", ["dat_pl"] = "e", ["acc_pl"] = "e", ["ins_pl"] = "e", ["loc_pl"] = "e" },
	["e"] = { ["nom_sg"] = "1", ["gen_sg"] = "1", ["dat_sg"] = "1", ["acc_sg"] = "1", ["ins_sg"] = "1", ["loc_sg"] = "1",
              ["nom_pl"] = "1", ["gen_pl"] = "e", ["dat_pl"] = "e", ["acc_pl"] = "1", ["ins_pl"] = "e", ["loc_pl"] = "e" },
	["d"] = { ["nom_sg"] = "e", ["gen_sg"] = "e", ["dat_sg"] = "e", ["acc_sg"] = "e", ["ins_sg"] = "e", ["loc_sg"] = "e",
              ["nom_pl"] = "<", ["gen_pl"] = "<", ["dat_pl"] = "<", ["acc_pl"] = "<", ["ins_pl"] = "<", ["loc_pl"] = "<" },
	["f"] = { ["nom_sg"] = "e", ["gen_sg"] = "e", ["dat_sg"] = "e", ["acc_sg"] = "e", ["ins_sg"] = "e", ["loc_sg"] = "e",
              ["nom_pl"] = "1", ["gen_pl"] = "e", ["dat_pl"] = "e", ["acc_pl"] = "1", ["ins_pl"] = "e", ["loc_pl"] = "e" },
	["f''"] = { ["nom_sg"] = "e", ["gen_sg"] = "e", ["dat_sg"] = "e", ["acc_sg"] = "e", ["ins_sg"] = "<", ["loc_sg"] = "e",
              ["nom_pl"] = "<", ["gen_pl"] = "e", ["dat_pl"] = "e", ["acc_pl"] = "<", ["ins_pl"] = "e", ["loc_pl"] = "e" },
}

palat = { ["к"] = "ц", ["г"] = "з", ["х"] = "с", ["т"] = "ц", ["д"] = "дз" }
back = { ["е"] = "э", ["ё"] = "о", ["і"] = "ы", ["ь"] = "", ["ю"] = "у", ["я"] = "а" }
front = { ["э"] = "е", ["о"] = "ё", ["ы"] = "і", [""] = "ь", ["у"] = "ю", ["а"] = "я" }

function generate_form(stem, ending, accent)
	stem = stem .. "/"

	if accent == "e" and mw.ustring.match(ending, "[аеёіоуыюэя]") then
		stem = mw.ustring.gsub(stem, mw.ustring.char(0x301), "")
		ending = mw.ustring.gsub(ending, "([аеёіоуыюэя])(_?)", "%1" .. mw.ustring.char(0x301) .. "%2", 1)
	else
		ending = mw.ustring.gsub(ending, mw.ustring.char(0x301), "")
		if accent == "1" then
			ending = mw.ustring.gsub(ending, mw.ustring.char(0x301), "")
			stem = mw.ustring.gsub(stem, "[аеёіоуыюэя]", "%1" .. mw.ustring.char(0x301), 1)
		elseif accent ~= "s" then
			if accent == "<" or not mw.ustring.match(ending, "[аеёіоуыюэя]") then
				stem = mw.ustring.gsub(stem, "([аеёіоуыюэя∅])([^аеёіоуыюэя∅]*)/", "%1" .. mw.ustring.char(0x301) .. "%2/")
			else
				error("Accent undetermined")
			end
		end
	end
	form = "#" .. stem .. ending .. "#"

	-- Handle reduced vowels
	form = mw.ustring.gsub(form, "ь∅(" .. mw.ustring.char(0x301) .. "[^аеёіоуыюэя]ь)", "ье_%1")
	form = mw.ustring.gsub(form, "ь∅(" .. mw.ustring.char(0x301) .. "[йцчшж])", "ье_%1")
	form = mw.ustring.gsub(form, "∅" .. mw.ustring.char(0x301), "о_" .. mw.ustring.char(0x301))
	form = mw.ustring.gsub(form, "ь∅([^аеёіоуыюэя]ь/[^аеёіоуыюэя])", "ье_%1")
	form = mw.ustring.gsub(form, "ь∅([йцчшж]/[^аеёіоуыюэя])", "ье_%1")
	form = mw.ustring.gsub(form, "∅([^аеёіоуыюэя]*/[^аеёіоуыюэя])", "о_%1")
	form = mw.ustring.gsub(form, "ль∅", "ль")
	form = mw.ustring.gsub(form, "([цсзн])ь∅([бпмвфкгх])", "%1ь%2")
	form = mw.ustring.gsub(form, "ць∅", "т")
	form = mw.ustring.gsub(form, "дзь∅", "д")
	form = mw.ustring.gsub(form, "ь?∅", "")

	-- Syllabic sonorants
	form = mw.ustring.gsub(form, "([^аеёіоуыюэя/_" .. mw.ustring.char(0x301) .. "][рл])([^аеёіоуыюэя/])", "%1ы%2")

	-- Vocalic /v/
	form = mw.ustring.gsub(form, "вь?(/?[^/аеёіоуьыюэя])", "ў%1")

	form = mw.ustring.gsub(form, "([^/_∅аеёіоуыюэябпфмрйў" .. mw.ustring.char(0x301) .. "])(ь?)(/?)й", "%1%1%2%3")

	-- ‘Soft’ vowel letters
	form = mw.ustring.gsub(form, "ь(/?)([аоуыэ])", function (a, b) return a .. front[b] end)
	form = mw.ustring.gsub(form, "ь(/?)([еёіюя])", function (a, b) return a .. b end)

	form = mw.ustring.gsub(form, "й(/?)([аоуыэ])", function (a, b) return a .. front[b] end)
	form = mw.ustring.gsub(form, "й/([еёіюя])", "/%1")

	-- Velar palatalisation
	form = mw.ustring.gsub(form, "([кгх])(/[еі])", function (a, b) return palat[a] .. b end)

	-- Vowel reduction
	form = mw.ustring.gsub(form, "о_([^" .. mw.ustring.char(0x301) .. "])", "а%1")
	form = mw.ustring.gsub(form, "ё_([^" .. mw.ustring.char(0x301) .. "])", "е%1")
	form = mw.ustring.gsub(form, "е_([^" .. mw.ustring.char(0x301) .. "][^аеёіоуыюэя]*[аеёіоуыюэя]_?" .. mw.ustring.char(0x301) .. ")", "я%1")
	form = mw.ustring.gsub(form, "э_([^" .. mw.ustring.char(0x301) .. "][^аеёіоуыюэя]*[аеёіоуыюэя]_?" .. mw.ustring.char(0x301) .. ")", "а%1")

	-- Prosthetic /v/
	form = mw.ustring.gsub(form, "#о́_", "во́")

	-- Deaccent monosyllabic forms
	if not mw.ustring.match(form, "[аеёіоуыюэя][^ ]*[аеёіоуыюэя]") then
		form = mw.ustring.gsub(form, mw.ustring.char(0x301), "")
	end

	-- /ɨ/ fronting after velars
	form = mw.ustring.gsub(form, "([кгх])/ы", "%1/і")

	-- Hard-only consonants
	form = mw.ustring.gsub(form, "([рцчшж])/([еёіьюя])", function (a, b) return a .. "/" .. back[b] end)

	-- Dental assibilation
	form = mw.ustring.gsub(form, "([тд])/([еёіьюя])", function (a, b) return palat[a] .. "/" .. b end)

	-- Strip juncture marks
	form = mw.ustring.gsub(form, "[_/#]", "")

	-- Deaccent ё
	form = mw.ustring.gsub(form, "ё" .. mw.ustring.char(0x301), "ё")

	return form
end

function generate_forms(args)
	local forms = {}

	term = args["term"]
	if not term then
		error("No term specified")
	end
	decl = args["decl"]
	number = args["number"]
	gender = args["gender"]
	animate = args["animate"]
	accent = args["accent"]
	reduced = args["reduced"]
	number = args["number"]

	if (not accent) or (accent == "a") then
		if mw.ustring.match(term, "[аеёіоуыюэя][^ ]*[аеёіоуыюэя]") then
			acute = mw.ustring.find(term, mw.ustring.char(0x301))
			if acute == mw.ustring.len(term) then
				term = mw.ustring.sub(term, 1, -2)
				ending = mw.ustring.sub(term, -1)
				if ending == "а" or ending == "я" then
					gender = "f"
				end
				accent = "b"
			elseif not acute then
				error("Accent must be given")
			else
				if not mw.ustring.find(term, mw.ustring.char(0x301), acute + 1) then
					accent = "a"
				else
					error("Only one accent must be specified")
				end
			end
		else
			term = mw.ustring.gsub(term, "([аеёіоуыюэя])([^ ])", "%1" .. mw.ustring.char(0x301) .. "%2")
			accent = "a"
		end
	else
		term = mw.ustring.gsub(term, mw.ustring.char(0x301), "")
	end

	local stem = mw.ustring.sub(term, 1, -2)
	local ending = mw.ustring.sub(term, -1)

	if ending == "ы" or number == "p" then
		gender = ""
		number = "p"
	end

	if gender == "f" then
		if ending == "ь" then
			decl = "i"
			stem = stem .. "ь"
		elseif ending == "ў" then
			decl = "i"
			stem = stem .. "вь"
		else
			if ending == "я" then
				stem = stem .. "ь"
				decl = "a"
			elseif ending ~= "а" then
				if mw.ustring.match(ending, "[чшжр]") then
					if not (decl or (accent == "a" or accent == "b")) then
						error("Must specify declension")
					else
						stem = stem .. ending
					end
				else
					stem = stem .. ending
					decl = "a"
				end
			else
				decl = "a"
			end
		end
	else
		decl = "o"
		if ending ~= "а" then
			gender = "n"
			if ending ~= "о" then
				if ending == "е" then
					stem = stem .. "ь"
				else
					gender = "m"
					stem = stem .. ending
				end
			end
		elseif not gender then
			error("Gender must be specified")
		end
	end

	-- Mark reduced vowels
	if reduced then
		stem = mw.ustring.gsub(stem .. "/", "([^аеёіоуъьыюэя])[её]([^аеёіоуъьыюэя]ь?)/", "%1ь%2")
		stem = mw.ustring.gsub(stem .. "/", "([^аеёіоуъыюэя])[оа]?([^аеёіоуъьыюэя]ь?)//?", "%1∅%2")
	end

	local datloc_sg = function()
	                  	if gender == "m" then
	                  		if accent_curves[accent]["dat_sg"] ~= "e" or mw.ustring.match(stem .. "/", "[кгх]/") then
	                  			return "у"
	                  		else
	                  			return mw.ustring.match(stem .. "/", "ь/") and "і" or "е"
	                  		end
	                  	else
	                  		if mw.ustring.sub(stem, -1) == "к" then
	                  			return accent_curves[accent]["dat_sg"] == "e" and "е" or "і"
	                  		else
	                  			return mw.ustring.find(stem .. "/", "[рцчшж]/") and "ы" or "е"
	                  		end
	                  	end
	end

	local gen_pl = function()
	                  	if  mw.ustring.match(stem .. "/", "[^аеёіоуыюэя∅_" .. mw.ustring.char(0x301) .. "][^аеёіоуъьыюэя]ь?/") then
	                  		return "о_ў"
	                  	else
	                  		return ""
	                  	end
	end

	endings_sg = {
		["a"] = { ["nom_sg"] = "а", ["gen_sg"] = "ы", ["dat_sg"] = datloc_sg, ["acc_sg"] = "у", ["ins_sg"] = "о_й", ["loc_sg"] = datloc_sg },
		["o"] = { ["nom_sg"] = function() return gender == "n" and "о_" or "" end, ["gen_sg"] = function() return number == "s" and "у" or "а" end, ["dat_sg"] = "у", ["ins_sg"] = "о_м",
		          ["loc_sg"] = function() return mw.ustring.match(stem .. "/", "[кгх]/") and "у" or (mw.ustring.match(stem .. "/", "[йь]/") and "і" or "е") end },
		["i"] = { ["nom_sg"] = "", ["gen_sg"] = "і", ["dat_sg"] = "і", ["ins_sg"] = "йу", ["loc_sg"] = "і" }
	}

	endings_pl = { ["nom_pl"] = "ы", ["gen_pl"] = function() return gender == "m" and "о_ў" or (decl == "i" and "ей" or gen_pl()) end, ["dat_pl"] = "ам", ["ins_pl"] = "амі", ["loc_pl"] = "ах" }

	-- Mark reducible vowels
	for k, v in pairs(accent_curves[accent]) do
		ending = endings_sg[decl][k] or endings_pl[k]
		if type(ending) == "function" then
			ending = ending()
		end
		if v ~= "s" then
			if v == "1" then
				stem = mw.ustring.gsub(stem, "[аеёіоуыюэя]", "%1_", 1)
			elseif v == "<" or ending == "" then
				stem = mw.ustring.gsub(stem .. "/", "([аеёіоуыюэя∅])([^аеёіоуыюэя∅]*)/", "%1_%2", 1)
				stem = mw.ustring.gsub(stem .. "/", "([аеёіоуыюэя∅])([^аеёіоуыюэя∅]*[аеёіоуыюэя∅][^аеёіоуыюэя∅]*)/", "%1_%2", 1)
				stem = mw.ustring.gsub(stem, "∅_", "∅") -- redundant
				stem = mw.ustring.gsub(stem, "/", "")
			end
		end
	end

	for k, v in pairs(endings_sg[decl]) do
		if type(v) == "function" then v = v() end
		forms[k] = generate_form(stem, v, accent_curves[accent][k])
	end
	if decl ~= "a" then
		if gender == "m" and animate then
			forms["acc_sg"] = forms["gen_sg"]
		else
			forms["acc_sg"] = forms["nom_sg"]
		end
	end

	for k, v in pairs(endings_pl) do
		if type(v) == "function" then v = v() end
		forms[k] = generate_form(stem, v, accent_curves[accent][k])
	end
	if animate then
		forms["acc_pl"] = forms["gen_pl"]
	else
		forms["acc_pl"] = forms["nom_pl"]
	end

	forms.n = number

	return forms
end

function export.decline(term, gender, animate, accent, reduced, number, decl)
	term = mw.ustring.gsub(term, "ѐ", "ѐ")
	term = mw.ustring.gsub(term, "ѝ", "ѝ")
	return mw.ustring.toNFC("{{" .. make_table(generate_forms({ ["term"] = term, ["gender"] = gender, ["animate"] = animate, ["accent"] = accent, ["reduced"] = reduced, ["number"] = number, ["decl"] = decl })) .. "}}")
end

return export