Pumunta sa nilalaman

Module:la-noun/data

Mula Wiksiyonaryo


local decl = {}

local la_utilities_module = "Module:la-utilities"
local string_char_module = "Module:string/char"
local table_deep_copy_module = "Module:table/deepCopy"
local table_insert_if_not_module = "Module:table/insertIfNot"

local pairs = pairs
local toNFD = mw.ustring.toNFD
local u = require(string_char_module)
local umatch = mw.ustring.match
local usub = mw.ustring.sub

local MACRON = u(0x304)
local BREVE = u(0x306)
local DIAER = u(0x308)
local accent = "[" .. MACRON .. BREVE .. DIAER .. "]*"

local function add_form(...)
	add_form = require(la_utilities_module).add_form
	return add_form(...)
end

local function deep_copy(...)
	deep_copy = require(table_deep_copy_module)
	return deep_copy(...)
end

local function insert_if_not(...)
	insert_if_not = require(table_insert_if_not_module)
	return insert_if_not(...)
end

local function glossary_link(anchor, text)
	text = text or anchor
	return "[[Appendix:Glossary#" .. anchor .. "|" .. text .. "]]"
end

local function preprocess(...)
	local frame = mw.getCurrentFrame()

	function preprocess(text)
		return frame:preprocess(text)
	end

	return preprocess(...)
end

decl["0"] = function(data, args)
	local forms = data.forms
	local stem = args[1]

	forms["nom_sg"] = stem
	forms["gen_sg"] = stem
	forms["dat_sg"] = stem
	forms["acc_sg"] = stem
	forms["abl_sg"] = stem
	forms["voc_sg"] = stem

	forms["nom_pl"] = stem
	forms["gen_pl"] = stem
	forms["dat_pl"] = stem
	forms["acc_pl"] = stem
	forms["abl_pl"] = stem
	forms["voc_pl"] = stem

	-- with locative
	if data.loc then
		forms["loc_sg"] = stem
		forms["loc_pl"] = stem
	end
end

local function alt_gen_pl_in_um(stem, forms, types, subtitles, i_stem)
	if types.genplum then
		insert_if_not(subtitles, preprocess("alternative genitive plural in {{m|la|-um|id=genitive plural}}"))
		add_form(forms, "gen_pl", stem, (i_stem and "i" or "") .. "um")
	elseif types.not_genplum then
		-- FIXME: not a contraction.
		insert_if_not(subtitles, "uncontracted genitive plural")
	end
end

local function dat_abl_pl_subtitle(dat_abl_loc_pl, loc)
	return ("dative/ablative%s plural in ''-%s''"):format(loc and "/locative" or "", dat_abl_loc_pl)
end

decl["1"] = function(data, args)
	local forms, types, loc, subtitles = data.forms, data.types, data.loc, data.subtitles
	local stem = args[1]

	-- normal 1st
	local nom_sg = "a"
	local gen_loc_sg = "ae"
	local dat_sg = "ae"
	local acc_sg = "am"
	local abl_sg = "ā"
	local voc_sg = "a"

	local nom_voc_pl = "ae"
	local gen_pl = "ārum"
	local dat_abl_loc_pl = "īs"
	local acc_pl = "ās"

	-- pascha
	if types.N then
		insert_if_not(subtitles, "neuter")
		
		acc_sg = "a"

		nom_voc_pl = "a"
		acc_pl = "a"
		
	-- ām
	elseif types.am then
		insert_if_not(subtitles, preprocess("nominative/vocative singular in ''-ām''"))

		nom_sg = "ām"
		acc_sg = "ām"
		abl_sg = {"ām", "ā"}
		voc_sg = "ām"

	-- all Greek
	elseif types.Greek then

		if types.M then
			insert_if_not(subtitles, "masculine")
		elseif types.F then
			insert_if_not(subtitles, "feminine")
		end

		insert_if_not(subtitles, "Greek-type")

		--Greek Ma
		if types.Ma then
			insert_if_not(subtitles, preprocess("nominative singular in {{m|la||-ās}}"))

			nom_sg = "ās"
			acc_sg = "ān"
			voc_sg = "ā"

		-- Greek Me
		elseif types.Me then
			insert_if_not(subtitles, preprocess("nominative singular in {{m|la||-ēs}}"))

			nom_sg = "ēs"
			acc_sg = "ēn"
			abl_sg = "ē"
			voc_sg = "ē"

		-- Greek Fa
		elseif types.Fa then
			insert_if_not(subtitles, preprocess("nominative singular in {{m|la||-ā}}"))

			nom_sg = "ā"
			gen_loc_sg = "ās"
			acc_sg = "ān"
			voc_sg = "ā"

		-- Greek Fe
		else
			insert_if_not(subtitles, preprocess("nominative singular in {{m|la||-ē}}"))

			nom_sg = "ē"
			gen_loc_sg = "ēs"
			acc_sg = "ēn"
			abl_sg = "ē"
			voc_sg = "ē"

		end
	end

	-- ābus
	if types.abus then
		dat_abl_loc_pl = "ābus"
		insert_if_not(subtitles, dat_abl_pl_subtitle(dat_abl_loc_pl, loc))
	elseif types.not_abus then
		insert_if_not(subtitles, dat_abl_pl_subtitle(dat_abl_loc_pl, loc))
	end

	add_form(forms, "nom_sg", stem, nom_sg)
	add_form(forms, "gen_sg", stem, gen_loc_sg)
	add_form(forms, "dat_sg", stem, dat_sg)
	add_form(forms, "acc_sg", stem, acc_sg)
	add_form(forms, "abl_sg", stem, abl_sg)
	add_form(forms, "voc_sg", stem, voc_sg)

	add_form(forms, {"nom_pl", "voc_pl"}, stem, nom_voc_pl)
	add_form(forms, "gen_pl", stem, gen_pl)
	add_form(forms, {"dat_pl", "abl_pl"}, stem, dat_abl_loc_pl)
	add_form(forms, "acc_pl", stem, acc_pl)

	-- with -um genitive plural
	alt_gen_pl_in_um(stem, forms, types, subtitles)

	-- with locative
	if loc then
		add_form(forms, "loc_sg", stem, gen_loc_sg)
		add_form(forms, "loc_pl", stem, dat_abl_loc_pl)
	end
end

decl["2"] = function(data, args)
	local forms, types, subtitles, notes = data.forms, data.types, data.subtitles, data.notes
	local stem1, stem2 = args[1], args[2]

	-- normal 2nd
	forms["nom_sg"] = stem1 .. "us"
	forms["gen_sg"] = stem1 .. "ī"
	forms["dat_sg"] = stem1 .. "ō"
	forms["acc_sg"] = stem1 .. "um"
	forms["abl_sg"] = stem1 .. "ō"
	forms["voc_sg"] = stem1 .. "e"

	forms["nom_pl"] = stem1 .. "ī"
	forms["gen_pl"] = stem1 .. "ōrum"
	forms["dat_pl"] = stem1 .. "īs"
	forms["acc_pl"] = stem1 .. "ōs"
	forms["abl_pl"] = stem1 .. "īs"
	forms["voc_pl"] = stem1 .. "ī"

	-- all neuter
	if types.N then
		insert_if_not(subtitles, "neuter")

		forms["nom_sg"] = stem1 .. "um"
		forms["voc_sg"] = stem1 .. "um"

		forms["nom_pl"] = stem1 .. "a"
		forms["acc_pl"] = stem1 .. "a"
		forms["voc_pl"] = stem1 .. "a"

		-- neuter ium
		if types.ium then
			forms["nom_sg"] = stem1 .. "ium"
			forms["gen_sg"] = {stem1 .. "iī", stem1 .. "ī"}
			forms["dat_sg"] = stem1 .. "iō"
			forms["acc_sg"] = stem1 .. "ium"
			forms["abl_sg"] = stem1 .. "iō"
			forms["voc_sg"] = stem1 .. "ium"

			forms["nom_pl"] = stem1 .. "ia"
			forms["gen_pl"] = stem1 .. "iōrum"
			forms["dat_pl"] = stem1 .. "iīs"
			forms["acc_pl"] = stem1 .. "ia"
			forms["abl_pl"] = stem1 .. "iīs"
			forms["voc_pl"] = stem1 .. "ia"

			notes["gen_sg2"] = "Found in older Latin (until the Augustan Age)."

		-- -vom (aevom, etc.)
		elseif types.vom then
			insert_if_not(subtitles, "nominative singular in ''-om'' after ''v''")
			forms["nom_sg"] = stem1 .. "om"
			forms["acc_sg"] = stem1 .. "om"
			forms["voc_sg"] = stem1 .. "om"

		-- neuter Greek
		elseif types.Greek then
			insert_if_not(subtitles, "Greek-type")
			
			-- neuter Greek in -os (cētos)
			if types.us then
				insert_if_not(subtitles, "nominative/accusative/vocative in ''-os''")
				
				forms["nom_sg"] = stem1 .. "os"
				forms["acc_sg"] = stem1 .. "os"
				forms["voc_sg"] = stem1 .. "os"

				forms["nom_pl"] = stem1 .. "ē"
				forms["gen_pl"] = stem1 .. "ōn"
				forms["acc_pl"] = stem1 .. "ē"
				forms["voc_pl"] = stem1 .. "ē"
				
			else

				forms["nom_sg"] = stem1 .. "on"
				forms["acc_sg"] = stem1 .. "on"
				forms["voc_sg"] = stem1 .. "on"

			end

		-- neuter us
		elseif types.us then
			insert_if_not(subtitles, "nominative/accusative/vocative in ''-us''")

			forms["nom_sg"] = stem1 .. "us"
			forms["acc_sg"] = stem1 .. "us"
			forms["voc_sg"] = stem1 .. "us"

			forms["nom_pl"] = stem1 .. "a"
			forms["acc_pl"] = stem1 .. "a"
			forms["voc_pl"] = stem1 .. "a"

		elseif types.not_Greek or types.not_us then
			insert_if_not(subtitles, "nominative/accusative/vocative in ''-um''")
		end

	-- er
	elseif types.er then
		insert_if_not(subtitles, ("nominative singular in ''-%s''"):format(umatch(toNFD(stem1), "[eE]" .. accent .. "r$") and "er" or "r"))

		forms["nom_sg"] = stem1
		forms["gen_sg"] = stem2 .. "ī"
		forms["dat_sg"] = stem2 .. "ō"
		forms["acc_sg"] = stem2 .. "um"
		forms["abl_sg"] = stem2 .. "ō"
		forms["voc_sg"] = stem1

		forms["nom_pl"] = stem2 .. "ī"
		forms["gen_pl"] = stem2 .. "ōrum"
		forms["dat_pl"] = stem2 .. "īs"
		forms["acc_pl"] = stem2 .. "ōs"
		forms["abl_pl"] = stem2 .. "īs"
		forms["voc_pl"] = stem2 .. "ī"

	-- ius
	elseif types.ius then
		forms["nom_sg"] = stem1 .. "ius"
		forms["gen_sg"] = {stem1 .. "iī", stem1 .. "ī"}
		forms["dat_sg"] = stem1 .. "iō"
		forms["acc_sg"] = stem1 .. "ium"
		forms["abl_sg"] = stem1 .. "iō"
		if types.voci then
			-- Only for proper names and fīlius, genius
			forms["voc_sg"] = stem1 .. "ī"
		else
			forms["voc_sg"] = stem1 .. "ie"
		end

		forms["nom_pl"] = stem1 .. "iī"
		forms["gen_pl"] = stem1 .. "iōrum"
		forms["dat_pl"] = stem1 .. "iīs"
		forms["acc_pl"] = stem1 .. "iōs"
		forms["abl_pl"] = stem1 .. "iīs"
		forms["voc_pl"] = stem1 .. "iī"

		notes["gen_sg2"] = "Found in older Latin (until the Augustan Age)."

	-- -vos (servos, etc.)
	elseif types.vos then
		insert_if_not(subtitles, "nominative singular in ''-os'' after ''v''")

		forms["nom_sg"] = stem1 .. "os"
		forms["acc_sg"] = stem1 .. "om"

	-- Greek
	elseif types.Greek then
		insert_if_not(subtitles, "Greek-type")

		forms["nom_sg"] = stem1 .. "os"
		forms["acc_sg"] = stem1 .. "on"
		
		if data.num == "pl" then
			forms["nom_pl"] = stem1 .. "oe"
			forms["voc_pl"] = stem1 .. "oe"
		else
			forms["nom_pl"] = {stem1 .. "ī", stem1 .. "oe"}
			forms["voc_pl"] = {stem1 .. "ī", stem1 .. "oe"}
		end

	elseif types.not_Greek then
		insert_if_not(subtitles, "non-Greek-type")
	end

	-- with -um genitive plural
	alt_gen_pl_in_um(stem2, forms, types, subtitles, types.ius or types.ium)

	-- with locative
	if data.loc then
		if types.ius or types.ium then
			forms["loc_sg"] = stem2 .. "iī"
			forms["loc_pl"] = stem2 .. "iīs"
		else
			forms["loc_sg"] = stem2 .. "ī"
			forms["loc_pl"] = stem2 .. "īs"
		end
	end
end

local acc_sg_i_stem_subtypes = {
	acc_im = {
		-- amussis, basis, buris, cucumis, gummis, mephitis, paraphrasis, poesis, ravis, sitis, tussis, (vis) [abl -ī];
		-- cannabis, senapis, sinapis [abl -e, -ī]
		acc_sg = {"im"},
		title = {"accusative singular in ''-im''"},
	},
	acc_im_in = {
		-- cities, rivers, gods, e.g. Bilbilis, Syrtis, Tiberis, Anubis, Osiris [abl -ī];
		-- Baetis, Tigris [acc -e, -ī]
		acc_sg = {"im", "in"},
		title = {"accusative singular in ''-im'' or ''-in''"},
	},
	acc_im_in_em = {
		-- e.g. tigris, river Līris
		acc_sg = {"im", "in", "em"},
		title = {"accusative singular in ''-im'', ''-in'' or ''-em''"},
	},
	acc_im_em = {
		acc_sg = {"im", "em"},
		title = {"accusative singular in ''-im'' or ''-em''"},
	},
	acc_im_occ_em = {
		-- febris, pelvis, puppis, restis, securis, turris [abl -ī, -e]
		acc_sg = {"im", "em"},
		title = {"accusative singular in ''-im'' or occasionally ''-em''"},
	},
	acc_em_im = {
		-- aqualis, clavis, lens, navis [abl -e, -ī];
		-- cutis, restis [abl -e]
		acc_sg = {"em", "im"},
		title = {"accusative singular in ''-em'' or ''-im''"},
	},
}

local abl_sg_i_stem_subtypes = {
	abl_i = {
		-- amussis, basis, buris, cucumis, gummis, mephitis, paraphrasis, poesis, ravis, sitis, tussis, (vis) [acc -im];
		-- cities, rivers, gods, e.g. Bilbilis, Syrtis, Tiberis, Anubis, Osiris [acc -im or -in];
		-- canalis "water pipe", months in -is or -er, nouns originally i-stem adjectives such as aedilis, affinis, bipennis, familiaris, sodalis, volucris, etc. [acc -em]
		abl_sg = {"ī"},
		title = {"ablative singular in ''-ī''"},
	},
	abl_i_e = {
		-- febris, pelvis, puppis, restis, securis, turris [acc -im, -em]
		abl_sg = {"ī", "e"},
		title = {"ablative singular in ''-ī'' or ''-e''"},
	},
	abl_i_occ_e = {
		-- ignis [acc -em]
		abl_sg = {"ī", "e"},
		title = {"ablative singular in ''-ī'' or occasionally ''-e''"},
	},
	abl_e_i = {
		-- cannabis, senapis, sinapis [acc -im];
		-- Baetis, Tigris [acc -im, -in];
		-- aqualis, clavis, lens, navis [acc -em, -im];
		-- finis, mugilis, occiput, pugil, rus, supellex, vectis [acc -em]
		abl_sg = {"e", "ī"},
		title = {"ablative singular in ''-e'' or ''-ī''"},
	},
	abl_e_occ_i = {
		-- amnis, anguis, avis, civis, classis, fustis, imber, orbis, pars, postis, sors, unguis, vesper [acc -em]
		abl_sg = {"e", "ī"},
		title = {"ablative singular in ''-e'' or occasionally ''-ī''"},
	},
}

local function extract_stem(form, ending)
	local base = umatch(form, "^(.*)" .. ending .. "$")
	if not base then
		error("Form " .. form .. " should end in -" .. ending)
	end
	return base
end

local function count_vowels(stem)
	return select(2, toNFD(stem):gsub("[aeiouyAEIOUY]", ""))
end

decl["3"] = function(data, args)
	local forms, types, subtitles, notes = data.forms, data.types, data.subtitles, data.notes
	local stem1, stem2 = args[1], args[2]

	local function non_i_stem_type()
		return (count_vowels(stem1) > count_vowels(stem2) and "parisyllabic" or "imparisyllabic") .. " non-i-stem"
	end

	--normal 3rd
	forms["nom_sg"] = stem1
	forms["gen_sg"] = stem2 .. "is"
	forms["dat_sg"] = stem2 .. "ī"
	forms["acc_sg"] = stem2 .. "em"
	forms["abl_sg"] = stem2 .. "e"
	forms["voc_sg"] = stem1

	forms["nom_pl"] = stem2 .. "ēs"
	forms["gen_pl"] = stem2 .. "um"
	forms["dat_pl"] = stem2 .. "ibus"
	forms["acc_pl"] = stem2 .. "ēs"
	forms["abl_pl"] = stem2 .. "ibus"
	forms["voc_pl"] = stem2 .. "ēs"

	local acc_sg_i_stem_subtype = false
	local not_acc_sg_i_stem_subtype = false
	for subtype, _ in pairs(types) do
		if acc_sg_i_stem_subtypes[subtype] then
			acc_sg_i_stem_subtype = true
			break
		end
	end
	for acc_sg_subtype, _ in pairs(acc_sg_i_stem_subtypes) do
		if types["not_" .. acc_sg_subtype] then
			not_acc_sg_i_stem_subtype = true
			break
		end
	end
	local abl_sg_i_stem_subtype = false
	local not_abl_sg_i_stem_subtype = false
	for subtype, _ in pairs(types) do
		if abl_sg_i_stem_subtypes[subtype] then
			abl_sg_i_stem_subtype = true
			break
		end
	end
	for abl_sg_subtype, _ in pairs(abl_sg_i_stem_subtypes) do
		if types["not_" .. abl_sg_subtype] then
			not_abl_sg_i_stem_subtype = true
			break
		end
	end

	-- all Greek
	if types.Greek then
		insert_if_not(subtitles, "Greek-type")

		-- Greek er
		if types.er then
			insert_if_not(subtitles, "variant with nominative singular in ''-ēr''")
			stem1 = extract_stem(stem1, "ēr")

			forms["nom_sg"] = stem1 .. "ēr"
			forms["gen_sg"] = stem1 .. "eris"
			forms["dat_sg"] = stem1 .. "erī"
			forms["acc_sg"] = {stem1 .. "era", stem1 .. "erem"}
			forms["abl_sg"] = stem1 .. "ere"
			forms["voc_sg"] = stem1 .. "ēr"

			forms["nom_pl"] = stem1 .. "erēs"
			forms["gen_pl"] = stem1 .. "erum"
			forms["dat_pl"] = stem1 .. "eribus"
			forms["acc_pl"] = stem1 .. "erēs"
			forms["abl_pl"] = stem1 .. "eribus"
			forms["voc_pl"] = stem1 .. "erēs"

		-- Greek on
		elseif types.on then
			insert_if_not(subtitles, "variant with nominative singular in ''-ōn''")
			stem1 = extract_stem(stem1, "ōn")

			forms["nom_sg"] = stem1 .. "ōn"
			forms["gen_sg"] = {stem1 .. "ontis", stem1 .. "ontos"}
			forms["dat_sg"] = stem1 .. "ontī"
			forms["acc_sg"] = stem1 .. "onta"
			forms["abl_sg"] = stem1 .. "onte"
			forms["voc_sg"] = stem1 .. "ōn"

			forms["nom_pl"] = stem1 .. "ontēs"
			forms["gen_pl"] = {stem1 .. "ontum", stem1 .. "ontium"}
			forms["dat_pl"] = stem1 .. "ontibus"
			forms["acc_pl"] = {stem1 .. "ontēs", stem1 .. "ontās"}
			forms["abl_pl"] = stem1 .. "ontibus"
			forms["voc_pl"] = stem1 .. "ontēs"

		-- Greek i-stem
		elseif types.I then
			insert_if_not(subtitles, "i-stem")
			forms["gen_sg"] = {stem2 .. "is", stem2 .. "eōs", stem2 .. "ios"}
			forms["acc_sg"] = {stem2 .. "im", stem2 .. "in", stem2 .. "em"}
			forms["abl_sg"] = {stem2 .. "ī", stem2 .. "e"}
			forms["voc_sg"] = {stem2 .. "is", stem2 .. "i"}

			notes["acc_sg3"] = "Found sometimes in Medieval and New Latin."
			notes["abl_sg2"] = "Found sometimes in Medieval and New Latin."

			forms["nom_pl"] = {stem2 .. "ēs", stem2 .. "eis"}
			forms["gen_pl"] = {stem2 .. "ium", stem2 .. "eōn"}
			forms["acc_pl"] = {stem2 .. "ēs", stem2 .. "eis"}
			forms["voc_pl"] = {stem2 .. "ēs", stem2 .. "eis"}

			if types.poetic_esi then
				forms["dat_pl"] = {stem2 .. "ibus", stem2 .. "esi"}
				forms["abl_pl"] = {stem2 .. "ibus", stem2 .. "esi"}
				notes["dat_pl2"] = "Primarily in poetry."
				notes["abl_pl2"] = "Primarily in poetry."
			end

		-- normal Greek
		else
			insert_if_not(subtitles, "normal variant")
			forms["gen_sg"] = stem2 .. "os"
			if umatch(toNFD(stem2), "[yY]" .. accent .. "$") then
				forms["acc_sg"] = stem2 .. "n"
			else
				forms["acc_sg"] = stem2 .. "a"
			end

			forms["nom_pl"] = stem2 .. "es"
			forms["acc_pl"] = stem2 .. "as"
			forms["voc_pl"] = stem2 .. "es"
			if umatch(toNFD(stem1), "[iyIY]" .. accent .. "s$") then
				-- Per Hiley, words in -is and -ys have a poetic vocative
				-- without the -s, but otherwise the vocative is the same
				-- as the nominative.
				forms["voc_sg"] = {stem1, (stem1:gsub("s$", ""))}
				notes["voc_sg2"] = "In poetry."
			end
		end
	elseif types.not_Greek then
		insert_if_not(subtitles, "non-Greek-type")
	end

	-- polis
	if types.polis then
		stem1 = extract_stem(stem1, "polis")
		insert_if_not(subtitles, "i-stem")
		insert_if_not(subtitles, "partially Greek-type")

		forms["nom_sg"] = stem1 .. "polis"
		forms["gen_sg"] = stem1 .. "polis"
		forms["dat_sg"] = stem1 .. "polī"
		forms["acc_sg"] = {stem1 .. "polim", stem1 .. "polin"}
		forms["abl_sg"] = stem1 .. "polī"
		forms["voc_sg"] = {stem1 .. "polis", stem1 .. "polī"}
	elseif types.not_polis then
		insert_if_not(subtitles, non_i_stem_type())
	end

	-- all neuter
	if types.N then
		insert_if_not(subtitles, "neuter")

		forms["acc_sg"] = stem1

		-- neuter I stem
		if types.I then

			-- pure variety
			if types.pure then
				insert_if_not(subtitles, "pure i-stem")
				forms["abl_sg"] = stem2 .. "ī"

				forms["nom_pl"] = stem2 .. "ia"
				forms["gen_pl"] = stem2 .. "ium"
				forms["acc_pl"] = stem2 .. "ia"
				forms["voc_pl"] = stem2 .. "ia"

			-- non-pure variety (rare)
			else
				insert_if_not(subtitles, "i-stem")
				forms["nom_pl"] = stem2 .. "a"
				forms["gen_pl"] = {stem2 .. "ium", stem2 .. "um"}
				forms["acc_pl"] = stem2 .. "a"
				forms["voc_pl"] = stem2 .. "a"
			end

		-- normal neuter
		else
			insert_if_not(subtitles, non_i_stem_type())
			forms["nom_pl"] = stem2 .. "a"
			forms["acc_pl"] = stem2 .. "a"
			forms["voc_pl"] = stem2 .. "a"
		end

	-- I stem
	elseif types.I or acc_sg_i_stem_subtype or abl_sg_i_stem_subtype then
		insert_if_not(subtitles, (types.not_N and "non-neuter " or "") .. (types.pure and "pure " or "") .. "i-stem")

		forms["gen_pl"] = stem2 .. "ium"
		-- Per Allen and Greenough, Hiley and others, the acc_pl in -īs
		-- applied originally to all i-stem nouns, and was current as an
		-- alternative form up through Caesar.
		forms["acc_pl"] = {stem2 .. "ēs", stem2 .. "īs"}

		-- pure variety
		if types.pure then
			forms["acc_sg"] = stem2 .. "im"
			forms["abl_sg"] = stem2 .. "ī"

			forms["nom_pl"] = stem2 .. "īs"
			forms["acc_pl"] = stem2 .. "īs"
			forms["voc_pl"] = stem2 .. "īs"
		end

		local num = data.num
		for subtype, _ in pairs(types) do
			local acc_sg_i_stem_props = acc_sg_i_stem_subtypes[subtype]
			if acc_sg_i_stem_props then
				forms["acc_sg"] = {}
				for _, ending in ipairs(acc_sg_i_stem_props.acc_sg) do
					insert_if_not(forms["acc_sg"], stem2 .. ending)
				end
				if num ~= "pl" then
					for _, t in ipairs(acc_sg_i_stem_props.title) do
						insert_if_not(subtitles, t)
					end
				end
				break
			end
		end

		-- FIXME: needs to be done for neuter nouns as well.
		for subtype, _ in pairs(types) do
			local abl_sg_i_stem_props = abl_sg_i_stem_subtypes[subtype]
			if abl_sg_i_stem_props then
				forms["abl_sg"] = {}
				for _, ending in ipairs(abl_sg_i_stem_props.abl_sg) do
					insert_if_not(forms["abl_sg"], stem2 .. ending)
				end
				if num ~= "pl" then
					for _, t in ipairs(abl_sg_i_stem_props.title) do
						insert_if_not(subtitles, t)
					end
				end
				break
			end
		end
	elseif types.not_N and types.not_I then
		insert_if_not(subtitles, "non-neuter " .. non_i_stem_type())
	elseif types.not_N then
		insert_if_not(subtitles, "non-neuter")
	elseif types.not_I then
		insert_if_not(subtitles, non_i_stem_type())
	end

	-- with locative
	if data.loc then
		-- As far as I can tell, in general both dative singular and
		-- ablative singular could be used for the third-declension locative,
		-- with different time periods preferring different forms.
		-- http://dcc.dickinson.edu/grammar/latin/3rd-declension-locative-case
		-- mentions rūrī along with either Carthāginī or Carthāgine.
		-- Wikipedia in https://en.wikipedia.org/wiki/Locative_case#Latin
		-- says this:
		--
		-- In archaic times, the locative singular of third declension nouns
		-- was still interchangeable between ablative and dative forms, but in
		-- the Augustan Period the use of the ablative form became fixed.
		-- Therefore, both forms "rūrī" and "rūre" may be encountered.
		--
		-- Lewis and Short confirm this.
		local loc_sg = forms["dat_sg"]
		if type(loc_sg) == "table" then
			loc_sg = deep_copy(loc_sg)
		else
			loc_sg = {loc_sg}
		end
		local abl_sg = forms["abl_sg"]
		if type(abl_sg) == "table" then
			for _, form in ipairs(abl_sg) do
				insert_if_not(loc_sg, deep_copy(form))
			end
		else
			insert_if_not(loc_sg, abl_sg)
		end
		forms["loc_sg"] = loc_sg
		forms["loc_pl"] = deep_copy(forms["abl_pl"])
		--The following is what we used to have, but I simply cannot believe it.
		--if types.Greek and not types.s then
		--	forms["loc_pl"] = stem2 .. "ēs"
		--end
	end
end

decl["4"] = function(data, args)
	local forms, types, subtitles, notes = data.forms, data.types, data.subtitles, data.notes
	local stem = args[1]

	-- normal 4th
	forms["nom_sg"] = stem .. "us"
	forms["gen_sg"] = stem .. "ūs"
	forms["dat_sg"] = stem .. "uī"
	forms["acc_sg"] = stem .. "um"
	forms["abl_sg"] = stem .. "ū"
	forms["voc_sg"] = stem .. "us"

	forms["nom_pl"] = stem .. "ūs"
	forms["gen_pl"] = stem .. "uum"
	forms["dat_pl"] = stem .. "ibus"
	forms["acc_pl"] = stem .. "ūs"
	forms["abl_pl"] = stem .. "ibus"
	forms["voc_pl"] = stem .. "ūs"

	if types.echo then
		insert_if_not(subtitles, "all cases except the genitive and accusative singular in ''-ō''")

		for slot in pairs(forms) do
			if slot ~= "gen_sg" then
				forms[slot] = stem .. "ō"
			end
		end

		add_form(forms, "acc_sg", stem, "ōn")

	elseif types.Callisto then
		insert_if_not(subtitles, "all cases except the genitive singular in ''-ō''")
		
		for slot in pairs(forms) do
			if slot ~= "gen_sg" then
				forms[slot] = stem .. "ō"
			end
		end

	end

	-- neuter
	if types.N then
		insert_if_not(subtitles, "neuter")

		forms["nom_sg"] = stem .. "ū̆"
		forms["gen_sg"] = {stem .. "ūs", stem .. "ū"}
		forms["dat_sg"] = {stem .. "ū", stem .. "uī"}
		forms["acc_sg"] = stem .. "ū̆"
		forms["voc_sg"] = stem .. "ū̆"

		forms["nom_pl"] = stem .. "ua"
		forms["acc_pl"] = stem .. "ua"
		forms["voc_pl"] = stem .. "ua"
		
		local note1 = "The length of the final vowel is uncertain in the nominative/accusative/vocative singular; [[w:Martianus Capella|Martianus Capella]] considers it to end with ''-ū'', while [[w:Servius the Grammarian|Servius]] considers it to end with ''-ŭ''."
		local note2 = "According to [[w:Martianus Capella|Martianus Capella]]."
		local note3 = "According to [[w:Servius the Grammarian|Servius]]."
		local note4 = "According to both."
		notes["nom_sg1"] = note1
		notes["gen_sg1"] = note2
		notes["gen_sg2"] = note3
		notes["dat_sg1"] = note4
		notes["dat_sg2"] = note2
		notes["acc_sg1"] = note1
		notes["voc_sg1"] = note1
		
	end

	-- ubus
	if types.ubus then
		insert_if_not(subtitles, "dative/ablative plural in ''-ubus''")

		forms["dat_pl"] = stem .. "ubus"
		forms["abl_pl"] = stem .. "ubus"
	elseif types.not_ubus then
		insert_if_not(subtitles, "dative/ablative plural in ''-ibus''")
	end

	-- with locative
	if data.loc then
		forms["loc_sg"] = forms["abl_sg"]
		forms["loc_pl"] = forms["abl_pl"]
	end
end

decl["5"] = function(data, args)
	local forms, types = data.forms, data.types
	local stem = args[1]

	-- ies
	if types.i then
		stem = stem .. "i"
	end

	forms["nom_sg"] = stem .. "ēs"
	forms["gen_sg"] = stem .. "eī"
	forms["dat_sg"] = stem .. "eī"
	forms["acc_sg"] = stem .. "em"
	forms["abl_sg"] = stem .. "ē"
	forms["voc_sg"] = stem .. "ēs"

	forms["nom_pl"] = stem .. "ēs"
	forms["gen_pl"] = stem .. "ērum"
	forms["dat_pl"] = stem .. "ēbus"
	forms["acc_pl"] = stem .. "ēs"
	forms["abl_pl"] = stem .. "ēbus"
	forms["voc_pl"] = stem .. "ēs"

	-- ies
	if types.i then
		forms["gen_sg"] = stem .. "ēī"
		forms["dat_sg"] = stem .. "ēī"
	end

	--with locative
	if data.loc then
		forms["loc_sg"] = stem .. "ē"
		forms["loc_pl"] = stem .. "ēbus"
	end
end

decl["sgpl"] = function(data, args)
	local forms = data.forms
	local stem1, stem2 = args[1], args[2]
	insert_if_not(data.subtitles, "with a distinct plural")

	forms["nom_sg"] = stem1
	forms["gen_sg"] = stem1
	forms["dat_sg"] = stem1
	forms["acc_sg"] = stem1
	forms["abl_sg"] = stem1
	forms["voc_sg"] = stem1

	forms["nom_pl"] = stem2
	forms["gen_pl"] = stem2
	forms["dat_pl"] = stem2
	forms["acc_pl"] = stem2
	forms["abl_pl"] = stem2
	forms["voc_pl"] = stem2

	-- with locative
	if data.loc then
		forms["loc_sg"] = stem1
		forms["loc_pl"] = stem2
	end
end

decl["indecl"] = function(data, args)
	local forms = data.forms
	local stem = args[1]
	insert_if_not(data.subtitles, "used only in the nominative and accusative")

	forms["nom_sg"] = stem
	forms["gen_sg"] = "-"
	forms["dat_sg"] = "-"
	forms["acc_sg"] = stem
	forms["abl_sg"] = "-"
	forms["voc_sg"] = "-"

	forms["nom_pl"] = "-"
	forms["gen_pl"] = "-"
	forms["dat_pl"] = "-"
	forms["acc_pl"] = "-"
	forms["abl_pl"] = "-"
	forms["voc_pl"] = "-"

	-- with locative (for multiword terms)
	if data.loc then
		forms["loc_sg"] = "-"
		forms["loc_pl"] = "-"
	end

	data.num = "sg"
end

decl["irreg"] = function(data, args)
	local forms, subtitles, notes = data.forms, data.subtitles, data.notes
	local stem = args[1]

	forms["nom_sg"] = "-"
	forms["gen_sg"] = "-"
	forms["dat_sg"] = "-"
	forms["acc_sg"] = "-"
	forms["abl_sg"] = "-"
	forms["voc_sg"] = "-"

	forms["nom_pl"] = "-"
	forms["gen_pl"] = "-"
	forms["dat_pl"] = "-"
	forms["acc_pl"] = "-"
	forms["abl_pl"] = "-"
	forms["voc_pl"] = "-"

	if stem == "bōs" then
		data.decl = "3"
		local stem1, stem2 = "bōs", "bov"
		
		decl["3"](data, {stem1, stem2})

		add_form(forms, "abl_sg", stem2, "īd")
		notes["abl_sg" .. #forms["abl_sg"]] = "Old Latin."

		add_form(forms, "gen_pl", "bo", "um", 1)
		add_form(forms, "gen_pl", stem2, "erum")
		add_form(forms, "dat_pl", "", "bōbus", 1)
		add_form(forms, "dat_pl", "", "būbus", 2)
		add_form(forms, "abl_pl", "", "bōbus", 1)
		add_form(forms, "abl_pl", "", "būbus", 2)

	elseif stem:match("^[dD]eus$") then
		data.decl = "2"
		local dD = stem:sub(1, 1)
		
		forms["nom_sg"] = dD .. "eus"
		forms["gen_sg"] = dD .. "eī"
		forms["dat_sg"] = dD .. "eō"
		forms["acc_sg"] = dD .. "eum"
		forms["abl_sg"] = dD .. "eō"
		forms["voc_sg"] = {dD .. "eus", dD .. "ee"}
		notes["voc_sg1"] = "Rare during the Classical period."
		notes["voc_sg2"] = "From Late Latin onwards."
		
		if stem == "deus" then
			forms["nom_pl"] = {"dī", "diī", "deī"}
			forms["gen_pl"] = {"deōrum", "deum"}
			forms["dat_pl"] = {"dīs", "diīs", "deīs"}
			forms["acc_pl"] = "deōs"
			forms["abl_pl"] = {"dīs", "diīs", "deīs"}
			forms["voc_pl"] = {"dī", "diī", "deī"}
		end

	elseif stem == "domus" then
		data.decl = "4,2"
		data.title = "[[Appendix:Latin fourth declension|fourth]]/[[Appendix:Latin second declension|second-declension]] noun"

		forms["nom_sg"] = "domus"
		forms["gen_sg"] = {"domūs", "domī"}
		forms["dat_sg"] = {"domuī", "domō", "domū"}
		forms["acc_sg"] = "domum"
		forms["abl_sg"] = {"domū", "domō"}
		forms["voc_sg"] = "domus"
		forms["loc_sg"] = "domī"

		forms["nom_pl"] = "domūs"
		forms["gen_pl"] = {"domuum", "domōrum"}
		forms["dat_pl"] = "domibus"
		forms["acc_pl"] = {"domūs", "domōs"}
		forms["abl_pl"] = "domibus"
		forms["voc_pl"] = "domūs"
		forms["loc_pl"] = "-"

		data.loc = true

	elseif umatch(stem, "^[IÏJ]ēs[uū]" .. BREVE .. "?s$") then
		local ij = usub(stem, 1, 1)
		local uu = umatch(stem, "[uū]" .. BREVE .. "?")

		forms["nom_sg"] = stem
		forms["gen_sg"] = ij .. "ēsū"
		forms["dat_sg"] = ij .. "ēsū"
		forms["acc_sg"] = ij .. "ēs" .. uu .. "m"
		forms["abl_sg"] = ij .. "ēsū"
		forms["voc_sg"] = ij .. "ēsū"
		data.num = "sg"
		
	elseif stem == "Mōsēs" or stem == "Moesēs" or umatch(stem, "^M[oō]" .. BREVE .. "?[īȳ]sēs$") then
		local mos = usub(stem, 1, -3)

		forms["nom_sg"] = stem
		forms["gen_sg"] = {mos .. "ī", mos .. "ēī", mos .. "is", mos .. "ēn", mos .. "eōs"}
		forms["dat_sg"] = mos .. "ī"
		forms["acc_sg"] = {mos .. "ēn", mos .. "em"}
		forms["abl_sg"] = {mos .. "e", mos .. "ēn", mos .. "ī"}
		forms["voc_sg"] = {mos .. "ēs", mos .. "ē"}
		data.num = "sg"

	elseif stem:match("^[ij]ūgerum$") then
		data.decl = "2,3"
		local ij = stem:sub(1, 1)
		data.title = "[[Appendix:Latin second declension|second]]–[[Appendix:Latin third declension|third-declension]] hybrid noun"
		insert_if_not(subtitles, "neuter")

		forms["nom_sg"] = ij .. "ūgerum"
		forms["gen_sg"] = ij .. "ūgerī"
		forms["dat_sg"] = ij .. "ūgerō"
		forms["acc_sg"] = ij .. "ūgerum"
		forms["abl_sg"] = ij .. "ūgerō"
		forms["voc_sg"] = ij .. "ūgerum"
		forms["nom_pl"] = ij .. "ūgera"
		forms["gen_pl"] = ij .. "ūgerum"
		forms["dat_pl"] = ij .. "ūgeribus"
		forms["acc_pl"] = ij .. "ūgera"
		forms["abl_pl"] = {ij .. "ūgeribus", ij .. "ūgerīs"}
		forms["voc_pl"] = ij .. "ūgera"

		notes["abl_pl2"] = "Once only, in:<br/>M. Terentius Varro, ''Res Rusticae'', bk I, ch. x"

	elseif stem == "sūs" then
		data.decl = "3"

		forms["nom_sg"] = "sūs"
		forms["gen_sg"] = "suis"
		forms["dat_sg"] = "suī"
		forms["acc_sg"] = "suem"
		forms["abl_sg"] = "sue"
		forms["voc_sg"] = "sūs"

		forms["nom_pl"] = "suēs"
		forms["gen_pl"] = "suum"
		forms["dat_pl"] = {"suibus", "sūbus", "subus"}
		forms["acc_pl"] = "suēs"
		forms["abl_pl"] = {"suibus", "sūbus", "subus"}
		forms["voc_pl"] = "suēs"

	elseif stem == "ēthos" then
		data.decl = "3"
		insert_if_not(subtitles, glossary_link("irregular"))
		insert_if_not(subtitles, "Greek-type")

		forms["nom_sg"] = "ēthos"
		forms["gen_sg"] = "ētheos"
		forms["acc_sg"] = "ēthos"
		forms["voc_sg"] = "ēthos"

		forms["nom_pl"] = {"ēthea", "ēthē"}
		forms["dat_pl"] = {"ēthesi", "ēthesin"}
		forms["acc_pl"] = {"ēthea", "ēthē"}
		forms["abl_pl"] = {"ēthesi", "ēthesin"}
		forms["voc_pl"] = {"ēthea", "ēthē"}

	elseif stem == "Athōs" then
		data.decl = "2"
		insert_if_not(subtitles, "highly " .. glossary_link("irregular"))
		insert_if_not(subtitles, "Greek-type")

		forms["nom_sg"] = "Athōs"
		forms["gen_sg"] = "Athō"
		forms["dat_sg"] = "Athō"
		forms["acc_sg"] = {"Athō", "Athōn"}
		forms["abl_sg"] = "Athō"
		forms["voc_sg"] = "Athōs"
		data.num = "sg"

	elseif stem:match("^[uv]ēnum$") then
		data.decl = "4,2"
		local uv = stem:sub(1, 1)
		data.title = "[[Appendix:Latin fourth declension|fourth]]/[[Appendix:Latin second declension|second-declension]] noun"
		insert_if_not(subtitles, glossary_link("defective"))

		forms["dat_sg"] = {uv .. "ēnuī", uv .. "ēnō"}
		forms["acc_sg"] = uv .. "ēnum"
		data.num = "sg"

	elseif stem:match("^[uv]īs$") then
		data.decl = "3"
		local uv = stem:sub(1, 1)
		insert_if_not(subtitles, glossary_link("irregular"))
		insert_if_not(subtitles, glossary_link("defective"))

		forms["nom_sg"] = uv .. "īs"
		forms["gen_sg"] = uv .. "īs"
		forms["dat_sg"] = uv .. "ī"
		forms["acc_sg"] = uv .. "im"
		forms["abl_sg"] = uv .. "ī"
		forms["voc_sg"] = uv .. "īs"

		forms["nom_pl"] = uv .. "īrēs"
		forms["gen_pl"] = uv .. "īrium"
		forms["dat_pl"] = uv .. "īribus"
		forms["acc_pl"] = {uv .. "īrēs", uv .. "īrīs"}
		forms["abl_pl"] = uv .. "īribus"
		forms["voc_pl"] = uv .. "īrēs"

	else
		error("Stem " .. stem .. " not recognized.")
	end
end

return decl

-- For Vim, so we get 4-space tabs
-- vim: set ts=4 sw=4 noet: