Bước tới nội dung

Mô đun:sa-decl/data

Từ điển mở Wiktionary
local decl_data = {}

local sa_utils = require("Module:sa-utilities")
local SLP_to_IAST = require("Module:sa-utilities/translit/SLP1-to-IAST")
local IAST_to_SLP = require("Module:sa-utilities/translit/IAST-to-SLP1")

local match = mw.ustring.match

-- Make a detection function for ARGS that fetches the stem according to MATCH_RE (which is matched against
-- args.lemma and should have the stem in the first capture). ADDL_CONDITION is an optional function of one
-- argument (ARGS) that must return true for the detection to happen.
local function make_detect(match_re, addl_condition)
	return function(args)
		if addl_condition and not addl_condition(args) then
			return false
		end
		local stem = match(args.lemma, match_re)
		if stem then
			args.stem = stem
			return true
		else
			return false
		end
	end
end

-- Construct all or part of a given noun's declension. Each of SG, DU and PL is a table, whose keys are
-- as follows:
--
-- n = nominative
-- a = accusative
-- v = vocative
-- i = instrumental
-- d = dative
-- ab = ablative
-- g = genitive
-- l = locative
--
-- The corresponding value is one of the following:
-- 1. a "copy spec" such as "[ins]", meaning to copy from the instrumental of the same number;
-- 2. a single string (specifying an ending); or
-- 3. a list of specs, where a spec is either a string (an ending) or a table of the form
--    {"ENDING", stem = "STEM", mono = TRUE/FALSE, note = "NOTE"}. The latter format lets you explicitly specify what
--    the stem is, whether the form is monosyllabic, and what the footnote is. All named keys are optional.
--
-- In forms 2 and 3, if the ending begins with +, the stem defaults to args.lemma; otherwise it defaults to args.stem.
local function decline(args, data, sg, du, pl)
	local cases = {n="nom", a="acc", v="voc", i="ins", d="dat", ab="abl", g="gen", l="loc"}
	local function process_number(endings, tag)
		if not endings then
			return
		end
		for case, es in pairs(endings) do
			if type(es) == "string" and es:find("^%[") then
				-- copy from another case; skip and handle later
			else
				if type(es) == "string" then
					es = {es}
				end
				local forms = {}
				for i, e in ipairs(es) do
					local stem, mono, note
					if type(e) == "table" then
						stem = e.stem
						mono = e.mono
						note = e.note
						e = e[1]
					end
					if e:find("^%+") then
						if stem then
							error("Internal error: Can't use + in an ending when stem is explicitly given")
						end
						e = e:gsub("^%+", "")
						stem = args.lemma
					elseif not stem then
						stem = args.stem
					end
					forms[i] = sa_utils.internal_sandhi({
						stem = stem, ending = e, has_accent = args.has_accent, recessive = case == "v", mono = mono
					})
					if note then
						forms["note" .. i] = note
					end
				end
				data.forms[cases[case] .. "_" .. tag] = forms
			end
		end

		-- Now handle cases copied from another.
		for case, es in pairs(endings) do
			if type(es) == "string" and es:find("^%[") then
				-- copy from another case; skip and handle later
				local other_case = es:match("^%[(.*)%]$")
				if not other_case then
					error("Internal error: Unrecognized copy case spec " .. es)
				end
				local other_slot = other_case .. "_" .. tag
				local value = data.forms[other_slot]
				if not value then
					error("Internal error: Slot '" .. other_slot .. "' to copy from is empty")
				end
				local this_slot = cases[case] .. "_" .. tag
				if data.forms[this_slot] then
					error("Internal error: A value already exists for slot '" .. this_slot ..
						"' when copying from '" .. other_slot .. "'")
				end
				data.forms[cases[case] .. "_" .. tag] = value
			end
		end
	end

	process_number(sg, "s")
	process_number(du, "d")
	process_number(pl, "p")
end


decl_data["a"] = {
	detect = make_detect("(.+)a" .. sa_utils.accent .. "?$",
		function(args) return args.g == "m" or args.g == "n" end)
}

setmetatable(decl_data["a"], {
	__call = function(self, args, data)
		local oxy = match(args.lemma, "(" .. sa_utils.accent .. "?)$")

		data.decl_type = "thân từ a"

		if args.g == "m" then
			decline(args, data, {
				n="a" .. oxy .. "s",
				a="a" .. oxy .. "m",
				v="a"
			}, {
				n="O" .. oxy,
				a="[nom]",
				v="O"
			}, {
				n={"A" .. oxy .. "s", {"A" .. oxy .. "sas", note="Vệ Đà"}},
				a="A" .. oxy .. "n",
				v={"As", {"Asas", note="Vệ Đà"}}
			})
		else
			decline(args, data, {
				n="a" .. oxy .. "m",
				a="[nom]",
				v="a"
			}, {
				n="e" .. oxy,
				a="[nom]",
				v="e"
			}, {
				n={"A" .. oxy .. "ni", {"A" .. oxy, note="Vệ Đà"}},
				a="[nom]",
				v={"Ani", {"A", note="Vệ Đà"}}
			})
		end

		decline(args, data, {
			i="e" .. oxy .. "na",
			d="A" .. oxy .. "ya",
			ab="A" .. oxy .. "t",
			g="a" .. oxy .. "sya",
			l="e" .. oxy
		}, {
			i="A" .. oxy .. "ByAm",
			d="[ins]",
			ab="[ins]",
			g="a" .. oxy .. "yos",
			l="[gen]"
		}, {
			i={ "E" .. oxy .. "s", { "e" .. oxy .. "Bis", note = "Vệ Đà" } },
			d="e" .. oxy .. "Byas", ab="[dat]",
			g="A" .. oxy .. "nAm", l="e" .. oxy .. "zu"
		})
		table.insert(data.categories, "Danh từ tiếng Phạn có thân từ a")
	end
})

decl_data["iu"] = {
	detect = make_detect("(.+)[iu]" .. sa_utils.accent .. "?$")
}

setmetatable(decl_data["iu"], {
	__call = function(self, args, data)
		local oxy = match(args.lemma, "(" .. sa_utils.accent .. "?)$")
		local vowel = match(args.lemma, "([iu])" .. sa_utils.accent .. "?$")

		data.decl_type = "thân từ " .. vowel

		if args.g == "m" then
			decline(args, data, {
				n="+s",
				a="+m",
				i={ "+nA", { "+A", note = "Vệ Đà" } },
				d={ { stem = args.stem .. sa_utils.split_diphthong[sa_utils.up_one_grade[vowel .. oxy]], "e" }, { "+e", note = "Ít phổ biến"} },
				ab={sa_utils.up_one_grade[vowel .. oxy] .. "s", {"+as", note = "Ít phổ biến"}},
				g="[abl]",
				l="O" .. oxy,
				v=sa_utils.up_one_grade[vowel .. oxy],
			}, {
				n="+" .. vowel,
				a="[nom]",
				i="+ByAm",
				d="[ins]",
				ab="[ins]",
				g={{stem = args.stem .. vowel, "o" .. oxy .. "s"}},
				l="[gen]",
				v="+" .. vowel,
			}, {
				n={{stem = args.stem .. sa_utils.up_one_grade[vowel .. oxy], "as"}},
				a="+" .. vowel .. "n",
				i="+Bis",
				d="+Byas",
				ab="[dat]",
				g=sa_utils.lengthen[vowel] .. "nA" .. (oxy ~= "" and "/" or "") .. "m",
				l="+su",
				v={{stem = args.stem .. sa_utils.up_one_grade[vowel], "as"}},
			})
		elseif args.g == "f" then
			decline(args, data, {
				n="+s",
				a="+m",
				i="+A",
				d={ { stem = args.stem .. sa_utils.split_diphthong[sa_utils.up_one_grade[vowel .. oxy]], "e" }, { "+e", note = "Ít phổ biến" }, { "+E", note = "Tiếng Phạn hậu kỳ" } },
				ab={sa_utils.up_one_grade[vowel .. oxy] .. "s", {"+As", note = "Tiếng Phạn hậu kỳ"}},
				g="[abl]",
				l={ "O" .. oxy, { "+Am", note = "Tiếng Phạn hậu kỳ" } },
				v=sa_utils.up_one_grade[vowel .. oxy],
			}, {
				n="+" .. vowel,
				a="[nom]",
				i="+ByAm",
				d="[ins]",
				ab="[ins]",
				g={{stem = args.stem .. vowel, "o" .. oxy .. "s"}},
				l="[gen]",
				v="+" .. vowel,
			}, {
				n={{stem = args.stem .. sa_utils.up_one_grade[vowel .. oxy], "as"}},
				a="+" .. vowel .. "s",
				i="+Bis",
				d="+Byas",
				ab="[dat]",
				g=sa_utils.lengthen[vowel] .. "nA" .. (oxy ~= "" and "/" or "") .. "m",
				l="+su",
				v={{stem = args.stem .. sa_utils.up_one_grade[vowel], "as"}},
			})
		else
			decline(args, data, {
				n="+",
				a="[nom]",
				i={ "+nA", { "+A", note = "Vệ Đà" } },
				d={ { stem = args.stem .. sa_utils.split_diphthong[sa_utils.up_one_grade[vowel .. oxy]], "e" }, { "+e", note = "Ít phổ biến" } },
				ab={ sa_utils.up_one_grade[vowel .. oxy] .. "s", { "+nas", note = "Tiếng Phạn hậu kỳ" }, { "+as", note = "Ít phổ biến" }},
				g="[abl]",
				l={ "+ni" .. oxy, note = "Tiếng Phạn hậu kỳ" },
				v={ "+", sa_utils.up_one_grade[vowel .. oxy] },
			}, {
				n="+nI",
				a="[nom]",
				i="+ByAm",
				d="[ins]",
				ab="[ins]",
				g="+nos",
				l="[gen]",
				v="+nI",
			}, {
				n={ "+" .. vowel, "+", { stem = args.stem .. sa_utils.lengthen[vowel .. oxy], "ni", note = "Tiếng Phạn hậu kỳ" } },
				a="[nom]",
				i="+Bis",
				d="+Byas",
				ab="[dat]",
				g=sa_utils.lengthen[vowel] .. "nA" .. (oxy ~= "" and "/" or "") .. "m",
				l="+su",
				v={ "+" .. vowel, "+", { stem = args.stem .. sa_utils.lengthen[vowel], "ni", note = "Tiếng Phạn hậu kỳ" } },
			})
		end

		table.insert(data.categories, "Sanskrit " .. vowel .. "-stem nouns")
	end
})

decl_data["AIU"] = {
	detect = function(args)
		if make_detect("(.+)[AIU]" .. sa_utils.accent .. "?$")(args) then
			args.true_mono = sa_utils.is_monosyllabic(args.lemma)
			return true
		else
			return false
		end
	end
}

setmetatable(decl_data["AIU"], {
	__call = function(self, args, data)
		local oxy = match(args.lemma, "(" .. sa_utils.accent .. "?)$")
		local vowel = match(args.lemma, "([AIU])" .. sa_utils.accent .. "?$")

		data.decl_type = "thân từ " .. SLP_to_IAST.tr(vowel)

		if not (args.root or args.compound or args.true_mono) then -- derived stem
			if vowel == "A" then
				decline(args, data, {
					n="+",
					i={ "a" .. oxy .. "yA", { "+", note = "Vệ Đà" } },
					d="+yE",
					ab="+yAs",
					g="[abl]",
					l="+yAm",
					v="e",
				}, {
					n="e" .. oxy,
					g="a" .. oxy .. "yos",
					v="e",
				}, {
					n="+s",
					v="+s",
				})
			elseif vowel == "I" then
				decline(args, data, {
					n="+",
					i="+A",
					d="+E",
					ab="+As",
					g="[abl]",
					l="+Am",
					v=sa_utils.shorten[vowel],
				}, {
					 n={ "+O", { "+", note = "Vệ Đà" } },
					 g="+os",
					 v={ "+O", { "+", note = "Vệ Đà" } },
				}, {
					n={ "+as", { "+s", note = "Vệ Đà" } },
					v={ "+as", { "+s", note = "Vệ Đà" } },
				})
			else
				decline(args, data, {
					n="+s",
					i="+A",
					d="+E",
					ab="+As",
					g="[abl]",
					l="+Am",
					v=sa_utils.shorten[vowel],
				}, {
					n={ "+O", { "+", note = "Vệ Đà" } },
					g="+os",
					v={ "+O", { "+", note = "Vệ Đà" } },
				}, {
					n={ "+as", { "+s", note = "Vệ Đà" } },
					v={ "+as", { "+s", note = "Vệ Đà" } },
				})
			end
			decline(args, data, {
				a="+m",
			}, {
				a="[nom]",
				i="+ByAm",
				d="[ins]",
				ab="[ins]",
				l="[gen]",
			}, {
				a="+s",
				i="+Bis",
				d="+Byas",
				ab="[dat]",
				g="+nAm",
				l="+su",
			})
		elseif vowel == "A" then
			decline(args, data, {
				n="+s",
				a="+m",
				i="+",
				d="e" .. oxy,
				ab="a" .. oxy .. "s",
				g="[abl]",
				l="i" .. oxy,
				v="+s",
			}, {
				n="O" .. oxy,
				a="[nom]",
				i="+ByAm",
				d="[ins]",
				ab="[ins]",
				g="o" .. oxy .. "s",
				l="[gen]",
				v="O",
			}, {
				n="+s",
				a={ "+s", { "a" .. oxy .. "s", note = "Perhaps" } },
				i="+Bis",
				d="+Byas",
				ab="[dat]",
				g={ "+" .. sa_utils.lengthen[vowel] .. "nAm", { "+" .. sa_utils.lengthen[vowel] .. "m", note = "Perhaps" } },
				l="+su",
				v="+s",
			})
		elseif args.compound then
			if match(args.stem, sa_utils.consonant .. sa_utils.consonant .. "$") then
				decline(args, data, {
					a={{"+am", mono = true}},
					i={{"+A", mono = true}},
					d={{"+e", mono = true}},
					ab={{"+as", mono = true}},
					l={{"+i", mono = true}},
				}, {
					n={{"+O", mono = true}},
					g={{"+os", mono = true}},
					v={{"+O", mono = true}},
				}, {
					n={{"+as", mono = true}},
					g={ { "+Am", mono = true }, "+nAm" },
					v={{"+as", mono = true}},
				})
			else
				decline(args, data, {
					a={ { "+am", mono = true }, "+am" },
					i={ { "+A", mono = true }, "+A" },
					d={ { "+e", mono = true }, "+e" },
					ab={ { "+as", mono = true }, "+as" },
					l={ { "+i", mono = true }, { stem = args.stem .. sa_utils.semivowel_to_cons[vowel], "i" .. (oxy ~= "" and "\\" or "") } }, -- weird special case
				}, {
					n={ { "+O", mono = true }, "+O" },
					g={ { "+os", mono = true }, "+os" },
					v={ { "+O", mono = true }, "+O" },
				}, {
					n={ { "+as", mono = true }, "+as" },
					g={ { "+Am", mono = true }, "+nAm", "+Am" },
					v={ { "+as", mono = true }, "+as" },
				})
			end
			decline(args, data, {
				n="+s",
				g="[abl]",
				v="+s",
			}, {
				a="[nom]",
				i="+ByAm",
				d="[ins]",
				ab="[ins]",
				l="[gen]",
			}, {
				a="[nom]",
				i="+Bis",
				d="+Byas",
				ab="[dat]",
				l="+su",
			})
		elseif args.true_mono then
			decline(args, data, {
				n="+s",
				a={{"+am", mono = true}},
				i={{"+A/", mono = true}},
				d={ { "+e/", mono = true }, { "+E/", mono = true, note = "Tiếng Phạn hậu kỳ" } },
				ab={ { "+a/s", mono = true }, { "+A/s", mono = true, note = "Tiếng Phạn hậu kỳ" } },
				g="[abl]",
				l={ { "+i/", mono = true }, { "+A/m", mono = true, note = "Tiếng Phạn hậu kỳ" } },
				v="+s",
			}, {
				n={{"+O", mono = true}},
				a="[nom]",
				i={{"+ByA/m", mono = true}},
				d="[ins]",
				ab="[ins]",
				g={{"+o/s", mono = true}},
				l="[gen]",
				v={{"+O", mono = true}},
			}, {
				n={{"+as", mono = true}},
				a="[nom]",
				i={{"+Bi/s", mono = true}},
				d={{"+Bya/s", mono = true}},
				ab="[dat]",
				g={ { "+A/m", mono = true }, { "+nA/m", mono = true, note = "Tiếng Phạn hậu kỳ" } },
				l={{"+su/", mono = true}},
				v={{"+as", mono = true}},
			})
		else
			decline(args, data, {
				n="+s",
				a="+am",
				i="+A",
				d="+e",
				ab="+as",
				g="[abl]",
				l="+i",
				v=sa_utils.shorten[vowel],
			}, {
				n="+A",
				a="[nom]",
				i="+ByAm",
				d="[ins]",
				ab="[ins]",
				g="+os",
				l="[gen]",
				v="+A",
			}, {
				n="+as",
				a="[nom]",
				i="+Bis",
				d="+Byas",
				ab="[dat]",
				g="+nAm",
				l="+su",
				v="+as",
			})
		end

		table.insert(data.categories, "Sanskrit " .. SLP_to_IAST.tr(vowel) .. "-stem nouns")
	end
})

decl_data["f"] = { -- actually for nouns in ṛ
	detect = make_detect("(.+)f" .. sa_utils.accent .. "?$")
}

setmetatable(decl_data["f"], { -- actually for nouns in ṛ
	__call = function(self, args, data)
		local oxy = match(args.lemma, "(" .. sa_utils.accent .. "?)$")

		data.decl_type = SLP_to_IAST.tr("f") .. "-stem"

		if args.g == "n" then
			decline(args, data, {
				n="f" .. oxy,
				a="[nom]",
				i="+nA",
				d="+ne",
				ab="+nas",
				l="+ni",
				v={ "f", "ar" },
			}, {
				n="+nI",
				g="+nos",
				v="+nI",
			}, {
				n="F" .. oxy .. "ni",
				a="[nom]",
				v="Fni",
			})
		else
            if not args.r_stem_a then
            	error('Please specify the length of the accusative singular vowel with r_stem_a = "a" or "ā".')
            else
            	args.r_stem_a = IAST_to_SLP.tr(args.r_stem_a)
            end
			decline(args, data, {
				n="A" .. oxy,
				a=args.r_stem_a .. oxy .. "ram",
				i="rA" .. oxy,
				d="re" .. oxy,
				ab="u" .. oxy .. "r",
				l="a" .. oxy .. "ri",
				v="ar",
			}, {
				n={ args.r_stem_a .. oxy .. "rO", { args.r_stem_a .. oxy .. "rA", note = "Vệ Đà" } },
				g="ro" .. oxy .. "s",
				v={ args.r_stem_a .. "rO", { args.r_stem_a .. "rA", note = "Vệ Đà" } },
			}, {
				n=args.r_stem_a .. oxy .. "ras",
				a=args.g == "f" and "F" .. oxy .. "s" or "F" .. oxy .. "n",
				v=args.r_stem_a .. "ras",
			})
		end
		decline(args, data, {
			g="[abl]",
		}, {
			a="[nom]",
			i="+ByAm",
			d="[ins]",
			ab="[ins]",
			l="[gen]",
		}, {
			i="+Bis",
			d="+Byas",
			ab="[dat]",
			g={{stem = args.stem .. "F", "nA" .. (oxy ~= "" and "/" or "") .. "m"}},
			l="+su",
		})

		table.insert(data.categories, "Sanskrit " .. SLP_to_IAST.tr("f") .. "-stem nouns")
	end
})

decl_data["[aiu]s"] = {
	detect = make_detect("(.+)[aiu]" .. sa_utils.accent .. "?s$")
}

setmetatable(decl_data["[aiu]s"], {
	__call = function(self, args, data)
		local vowel, oxy = match(args.lemma, "([aiu])(" .. sa_utils.accent .. "?)s$")

		data.decl_type = vowel .. "s-stem"

		if args.g == "m" or args.g == "f" then
			if vowel == "a" then
				decline(args, data, {
					n="A" .. oxy .. "s",
					a={ "+am", { "A" .. oxy .. "m", note = "Vệ Đà" } },
				}, nil, {
					n={ "+as", { "A" .. oxy .. "s", note = "Vệ Đà" } },
					v={ "+as", { "A" .. oxy .. "s", note = "Vệ Đà" } },
				})
			else
				decline(args, data, {
					n="+",
					a="+am",
				}, nil, {
					n="+as",
					v="+as",
				})
			end

			decline(args, data, {
				v="+",
			}, {
				n={ "+O", { "+A", note = "Vệ Đà" } },
				v={ "+O", { "+A", note = "Vệ Đà" } },
			})
		else
			decline(args, data, {
				n="+",
				a="[nom]",
				v="+",
			}, {
				n="+I",
				v="+I",
			}, {
				n={{stem = args.stem .. sa_utils.lengthen[vowel] .. oxy .. "n", "si"}},
				v={{stem = args.stem .. sa_utils.lengthen[vowel] .. "n", "si"}},
			})
		end

		decline(args, data, {
			i="+A",
			d="+e",
			ab="+as",
			g="[abl]",
			l="+i",
		}, {
			a="[nom]",
			i="+ByAm",
			d="[ins]",
			ab="[ins]",
			g="+os",
			l="[gen]",
		}, {
			a="[nom]",
			i="+Bis",
			d="+Byas",
			ab="[dat]",
			g="+Am",
			l="+su",
		})

		table.insert(data.categories, "Sanskrit " .. vowel .. "s-stem nouns")
	end
})

decl_data["an"] = {
	detect = make_detect("(.+)a" .. sa_utils.accent .. "?n$")
}

setmetatable(decl_data["an"], {
	__call = function(self, args, data)
		local oxy = match(args.lemma, "a(" .. sa_utils.accent .. "?)n$")

		data.decl_type = "thân từ an"

		if not match(args.stem, sa_utils.consonant .. sa_utils.consonant .. "$") or args.contract then
			decline(args, data, {
				i="nA" .. oxy,
				d="ne" .. oxy,
				ab="na" .. oxy .. "s",
				g="[abl]",
				l={ "ni" .. oxy, "+i" },
			}, {
				g="no" .. oxy .. "s",
			})

			if args.g ~= "m" then
				decline(args, data, nil, {
					n={ "nI" .. oxy, "+I" },
					v={ "nI", "+I" },
				}, {
					a="A" .. oxy .. "ni",
				})
			else
				decline(args, data, nil, {
					n={ "A" .. oxy .. "nO", { "A" .. oxy .. "nA", note = "Vệ Đà" } },
					v={ "AnO", { "AnA", note = "Vệ Đà" } },
				}, {
					a="na" .. oxy .. "s",
				})
			end
			decline(args, data, nil, nil, {
				g="nA" .. oxy .. "m",
			})
		else
			decline(args, data, {
				i="+A",
				d="+e",
				ab="+as",
				g="[abl]",
				l="+i",
			}, {
				g="+os",
			})

			if args.g ~= "m" then
				decline(args, data, nil, {
					n="+I",
					v="+I",
				}, {
					a="A" .. oxy .. "ni",
				})
			else
				decline(args, data, nil, {
					n={ "A" .. oxy .. "nO", { "A" .. oxy .. "nA", note = "Vệ Đà" } },
					v={ "AnO", { "AnA", note = "Vệ Đà" } },
				}, {
					a="+as",
				})
			end
			decline(args, data, nil, nil, {
				g="+Am",
			})
		end

		if args.g ~= "m" then
			decline(args, data, {
				n="a" .. oxy,
				a="[nom]",
				v={ "+", "a" },
			}, nil, {
				n="A" .. oxy .. "ni",
				v="Ani",
			})
		else
			decline(args, data, {
				n="A" .. oxy,
				a="A" .. oxy .. "nam",
				v="+",
			}, nil, {
				n="A" .. oxy .. "nas",
				v="Anas",
			})
		end

		decline(args, data, nil, {
			a="[nom]",
			a="[nom]",
			i="a" .. oxy .. "ByAm",
			d="[ins]",
			ab="[ins]",
			l="[gen]",
		}, {
			i="a" .. oxy .. "Bis",
			d="a" .. oxy .. "Byas",
			ab="[dat]",
			l="a" .. oxy .. "su",
		})

		table.insert(data.categories, "Danh từ tiếng Phạn có thân từ an")
	end
})

decl_data["in"] = {
	detect = make_detect("(.+)i" .. sa_utils.accent .. "?n$")
}

setmetatable(decl_data["in"], {
	__call = function(self, args, data)
		local oxy = match(args.lemma, "i(" .. sa_utils.accent .. "?)n$")

		data.decl_type = "in-stem"

		if args.g ~= "n" then
			decline(args, data, {
				n="I" .. oxy,
				a="i" .. oxy .. "nam",
				v="+",
			}, {
				n={ "+O", { "+A", note = "Vệ Đà" } },
				v={ "+O", { "+A", note = "Vệ Đà" } },
			}, {
				n="+as",
				a="[nom]",
				v="+as",
			})
		else
			decline(args, data, {
				n="i" .. oxy,
				a="[nom]",
				v="+i",
			}, {
				n="+I",
				v="+I",
			}, {
				n="I" .. oxy .. "ni",
				a="[nom]",
				v="Ini",
			})
		end

		decline(args, data, {
			i="+A",
			d="+e",
			ab="+as",
			g="[abl]",
			l="+i",
		}, {
			a="[nom]",
			i="i" .. oxy .. "ByAm",
			d="[ins]",
			ab="[ins]",
			g="+os",
			l="[gen]",
		}, {
			i="i" .. oxy .. "Bis",
			d="i" .. oxy .. "Byas",
			ab="[dat]",
			g="+Am",
			l="i" .. oxy .. "zu",
		})

		table.insert(data.categories, "Sanskrit in-stem nouns")
	end
})

decl_data["c"] = {
	detect = make_detect("(.+)c$")
}

setmetatable(decl_data["c"], {
	__call = function(self, args, data)
		data.decl_type = "c-stem"

		if args.g ~= "n" then
			decline(args, data, {
				n="k",
				a="+am",
				v="k",
			}, {
				n="+O",
				v="+O",
			}, {
				n="+as",
				a="[nom]",
				v="+as",
			})
		else
			decline(args, data, {
				n="k",
				a="[nom]",
				v="k",
			}, {
				n="+I",
				v="+I",
			}, {
				n="Yci",
				a="[nom]",
				v="Yci",
			})
		end

		-- FIXME: We should probably change internal_sandhi to correctly handle c -> g before bh, c -> k before ṣ.
		decline(args, data, {
			i="+A",
			d="+e",
			ab="+as",
			g="[abl]",
			l="+i",
		}, {
			a="[nom]",
			i="gByAm",
			d="[ins]",
			ab="[ins]",
			g="+os",
			l="[gen]",
		}, {
			i="gBis",
			d="gByas",
			ab="[dat]",
			g="+Am",
			l="kzu",
		})

		table.insert(data.categories, "Sanskrit c-stem nouns")
	end
})

decl_data["j"] = {
	detect = make_detect("(.+)j$")
}

setmetatable(decl_data["j"], {
	__call = function(self, args, data)
		data.decl_type = "j-stem"

		if args.g ~= "n" then
			decline(args, data, {
				n="k",
				a="+am",
				v="k",
			}, {
				n="+O",
				v="+O",
			}, {
				n="+as",
				a="[nom]",
				v="+as",
			})
		else
			decline(args, data, {
				n="k",
				a="[nom]",
				v="k",
			}, {
				n="+I",
				v="+I",
			}, {
				n="Yji",
				a="[nom]",
				v="Yji",
			})
		end

		decline(args, data, {
			i="+A",
			d="+e",
			ab="+as",
			g="[abl]",
			l="+i",
		}, {
			a="[nom]",
			i="gByAm",
			d="[ins]",
			ab="[ins]",
			g="+os",
			l="[gen]",
		}, {
			i="gBis",
			d="gByas",
			ab="[dat]",
			g="+Am",
			l="kzu",
		})

		table.insert(data.categories, "Sanskrit j-stem nouns")
	end
})

decl_data["B"] = {
	detect = make_detect("(.+)B$")
}

setmetatable(decl_data["B"], {
	__call = function(self, args, data)
		data.decl_type = "bh-stem"

		if args.g ~= "n" then
			decline(args, data, {
				n="p",
				a="+am",
				v="p",
			}, {
				n="+O",
				v="+O",
			}, {
				n="+as",
				a="[nom]",
				v="+as",
			})
		else
			decline(args, data, {
				n="p",
				a="[nom]",
				v="p",
			}, {
				n="+I",
				v="+I",
			}, {
				n="mBi",
				a="[nom]",
				v="mBi",
			})
		end

		decline(args, data, {
			i="+A",
			d="+e",
			ab="+as",
			g="[abl]",
			l="+i",
		}, {
			a="[nom]",
			i="bByAm",
			d="[ins]",
			ab="[ins]",
			g="+os",
			l="[gen]",
		}, {
			i="bBis",
			d="bByas",
			ab="[dat]",
			g="+Am",
			l="psu",
		})

		table.insert(data.categories, "Sanskrit bh-stem nouns")
	end
})

decl_data["ft"] = {
	detect = make_detect("(.+)ft$")
}

setmetatable(decl_data["ft"], {
	__call = function(self, args, data)
		data.decl_type = "ṛt-stem"

		if args.g ~= "n" then
			decline(args, data, {
				n="ft",
				a="+am",
				v="ft",
			}, {
				n="+O",
				v="+O",
			}, {
				n="+as",
				a="[nom]",
				v="+as",
			})
		else
			decline(args, data, {
				n="ft",
				a="[nom]",
				v="ft",
			}, {
				n="+I",
				v="+I",
			}, {
				n="fnti",
				a="[nom]",
				v="fnti",
			})
		end

		decline(args, data, {
			i="+A",
			d="+e",
			ab="+as",
			g="[abl]",
			l="+i",
		}, {
			a="[nom]",
			i="+ByAm",
			d="[ins]",
			ab="[ins]",
			g="+os",
			l="[gen]",
		}, {
			i="+Bis",
			d="+Byas",
			ab="[dat]",
			g="+Am",
			l="+su",
		})

		table.insert(data.categories, "Sanskrit ṛt-stem nouns")
	end
})

decl_data["ut"] = {
	detect = make_detect("(.+)ut$")
}

setmetatable(decl_data["ut"], {
	__call = function(self, args, data)
		data.decl_type = "ut-stem"

		if args.g ~= "n" then
			decline(args, data, {
				n="ut",
				a="+am",
				v="ut",
			}, {
				n="+O",
				v="+O",
			}, {
				n="+as",
				a="[nom]",
				v="+as",
			})
		else
			decline(args, data, {
				n="ut",
				a="[nom]",
				v="ut",
			}, {
				n="+I",
				v="+I",
			}, {
				n="unti",
				a="[nom]",
				v="unti",
			})
		end

		decline(args, data, {
			i="+A",
			d="+e",
			ab="+as",
			g="[abl]",
			l="+i",
		}, {
			a="[nom]",
			i="+ByAm",
			d="[ins]",
			ab="[ins]",
			g="+os",
			l="[gen]",
		}, {
			i="+Bis",
			d="+Byas",
			ab="[dat]",
			g="+Am",
			l="+su",
		})

		table.insert(data.categories, "Sanskrit ut-stem nouns")
	end
})

decl_data["it"] = {
	detect = make_detect("(.+)it$")
}

setmetatable(decl_data["it"], {
	__call = function(self, args, data)
		data.decl_type = "it-stem"

		if args.g ~= "n" then
			decline(args, data, {
				n="it",
				a="+am",
				v="it",
			}, {
				n="+O",
				v="+O",
			}, {
				n="+as",
				a="[nom]",
				v="+as",
			})
		else
			decline(args, data, {
				n="it",
				a="[nom]",
				v="it",
			}, {
				n="+I",
				v="+I",
			}, {
				n="inti",
				a="[nom]",
				v="inti",
			})
		end

		decline(args, data, {
			i="+A",
			d="+e",
			ab="+as",
			g="[abl]",
			l="+i",
		}, {
			a="[nom]",
			i="+ByAm",
			d="[ins]",
			ab="[ins]",
			g="+os",
			l="[gen]",
		}, {
			i="+Bis",
			d="+Byas",
			ab="[dat]",
			g="+Am",
			l="+su",
		})

		table.insert(data.categories, "Sanskrit it-stem nouns")
	end
})

decl_data["At"] = {
	detect = make_detect("(.+)At$")
}

setmetatable(decl_data["At"], {
	__call = function(self, args, data)
		data.decl_type = "āt-stem"

		if args.g ~= "n" then
			decline(args, data, {
				n="At",
				a="+am",
				v="At",
			}, {
				n="+O",
				v="+O",
			}, {
				n="+as",
				a="[nom]",
				v="+as",
			})
		else
			decline(args, data, {
				n="At",
				a="[nom]",
				v="At",
			}, {
				n="+I",
				v="+I",
			}, {
				n="Anti",
				a="[nom]",
				v="Anti",
			})
		end

		decline(args, data, {
			i="+A",
			d="+e",
			ab="+as",
			g="[abl]",
			l="+i",
		}, {
			a="[nom]",
			i="+ByAm",
			d="[ins]",
			ab="[ins]",
			g="+os",
			l="[gen]",
		}, {
			i="+Bis",
			d="+Byas",
			ab="[dat]",
			g="+Am",
			l="+su",
		})

		table.insert(data.categories, "Sanskrit āt-stem nouns")
	end
})

decl_data["at"] = {
	detect = make_detect("(.+)at$")
}

setmetatable(decl_data["at"], {
	__call = function(self, args, data)
		data.decl_type = "at-stem"

		if args.g ~= "n" then
			decline(args, data, {
				n="An",
				a="antam",
				v="an",
			}, {
				n="antO",
				v="antO",
			}, {
				n="antas",
				a="atas",
				v="antas",
			})
		else
			decline(args, data, {
				n="at",
				a="[nom]",
				v="at",
			}, {
				n="+I",
				v="+I",
			}, {
				n="anti",
				a="[nom]",
				v="anti",
			})
		end

		decline(args, data, {
			i="+A",
			d="+e",
			ab="+as",
			g="[abl]",
			l="+i",
		}, {
			a="[nom]",
			i="adByAm",
			d="[ins]",
			ab="[ins]",
			g="+os",
			l="[gen]",
		}, {
			i="adBis",
			d="adByas",
			ab="[dat]",
			g="+Am",
			l="+su",
		})

		table.insert(data.categories, "Sanskrit at-stem nouns")
	end
})

decl_data["h"] = {
	detect = make_detect("(.+)h$")
}

setmetatable(decl_data["h"], {
	__call = function(self, args, data)
		data.decl_type = "h-stem"

		if args.g ~= "n" then
			decline(args, data, {
				n="w",
				a="+am",
				v="w",
			}, {
				n="+O",
				v="+O",
			}, {
				n="+as",
				a="+as",
				v="+as",
			})
		else
			decline(args, data, {
				n="w",
				a="[nom]",
				v="w",
			}, {
				n="+I",
				v="+I",
			}, {
				n="Mhi",
				a="[nom]",
				v="Mhi",
			})
		end

		decline(args, data, {
			i="+A",
			d="+e",
			ab="+as",
			g="[abl]",
			l="+i",
		}, {
			a="[nom]",
			i="qByAm",
			d="[ins]",
			ab="[ins]",
			g="+os",
			l="[gen]",
		}, {
			i="qBis",
			d="qByas",
			ab="[dat]",
			g="+Am",
			l="wsu",
		})

		table.insert(data.categories, "Sanskrit h-stem nouns")
	end
})

decl_data["o"] = {
	detect = make_detect("(.+)o$")
}

setmetatable(decl_data["o"], {
	__call = function(self, args, data)
		data.decl_type = "o-stem"

		if args.g ~= "n" or "f" or "m" then
			decline(args, data, {
				n="OH",
				a="Am",
				v="[nom]",
			}, {
				n="AvO",
				v="AvO",
			}, {
				n="AvaH",
				a="AH",
				v="[nom]",
			})
		end

		decline(args, data, {
			i="+A",
			d="+e",
			ab="oH",
			g="[abl]",
			l="+i",
		}, {
			a="[nom]",
			i="oByAm",
			d="[ins]",
			ab="[ins]",
			g="avoH",
			l="[gen]",
		}, {
			i="oBiH",
			d="oByaH",
			ab="[dat]",
			g="+Am",
			l="+zu",
		})

		table.insert(data.categories, "Sanskrit o-stem nouns")
	end
})

decl_data["vāṃs"] = {
	detect = make_detect("(.+)vA" .. sa_utils.accent .. "?Ms$",
		function(args) return args.g == "m" or args.g == "n" end)
}

setmetatable(decl_data["vāṃs"], {
	__call = function(self, args, data)
		local oxy = match(args.lemma, "vA(" .. sa_utils.accent .. "?)Ms$")

		data.decl_type = "vāṃs-stem"

		if args.g == "m" then
			decline(args, data, {
				n="vA" .. oxy .. "n",
				a="vA" .. oxy .. "Msam",
				v="an"
			}, {
				n="vA" .. oxy .. "MsO",
				a="[nom]",
				v="[nom]"
			}, {
				n="vA" .. oxy .. "Msas",
				a="u" .. oxy .. "zas",
				v="[nom]"
			})
		else
			decline(args, data, {
				n="a" .. oxy .. "t",
				a="[nom]",
				v="at"
			}, {
				n="u" .. oxy .. "zI",
				a="[nom]",
				v="[nom]"
			}, {
				n="vA" .. oxy .. "MsI",
				a="[nom]",
				v="[nom]"
			})
		end

		decline(args, data, {
			i="u" .. oxy .. "zA",
			d="u" .. oxy .. "ze",
			ab="u" .. oxy .. "zas",
			g="u" .. oxy .. "zas",
			l="u" .. oxy .. "zi"
		}, {
			i="va" .. oxy .. "dByAm",
			d="[ins]",
			ab="[ins]",
			g="u" .. oxy .. "zos",
			l="[gen]"
		}, {
			i="va" .. oxy .. "dBis",
			d="va" .. oxy .. "dByas", 
			ab="u" .. oxy .. "zAm",
			g="u" .. oxy .. "zAm", 
			l="va" .. oxy .. "tsu"
		})
		table.insert(data.categories, "Sanskrit vāṃs-stem nouns")
	end
})

return decl_data