Module:User:Benwing2/sa-decl/data

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 = "a-stem"

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="Vedic"}},				a="A" .. oxy .. "n",				v={"As", {"Asas", note="Vedic"}}			}) 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="Vedic"}},				a="[nom]",				v={"Ani", {"A", note="Vedic"}}			}) 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 = "Vedic" } },			d="e" .. oxy .. "Byas", ab="[dat]",			g="A" .. oxy .. "nAm", l="e" .. oxy .. "zu"		}) table.insert(data.categories, "Sanskrit a-stem nouns") 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 = vowel .. "-stem"

if args.g == "m" then decline(args, data, {				n="+s",				a="+m",				i={ "+nA", { "+A", note = "Vedic" } },				d={ { stem = args.stem .. sa_utils.split_diphthong[sa_utils.up_one_grade[vowel .. oxy]], "e" }, { "+e", note = "Less common"} },				ab={sa_utils.up_one_grade[vowel .. oxy] .. "s", {"+as", note = "Less common"}},				g="[abl]",				l="O" .. oxy,				v=sa_utils.up_one_grade[vowel .. oxy],			}, {				n="+" .. vowel,				a="[nom]",				i="+ByAm",				d="[ins]",				ab="[ins]",				g=,				l="[gen]",				v="+" .. vowel,			}, {				n=,				a="+" .. vowel .. "n",				i="+Bis",				d="+Byas",				ab="[dat]",				g=sa_utils.lengthen[vowel] .. "nA" .. (oxy ~= "" and "/" or "") .. "m",				l="+su",				v=,			}) 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 = "Less common" }, { "+E", note = "Later Sanskrit" } },				ab={sa_utils.up_one_grade[vowel .. oxy] .. "s", {"+As", note = "Later Sanskrit"}},				g="[abl]",				l={ "O" .. oxy, { "+Am", note = "Later Sanskrit" } },				v=sa_utils.up_one_grade[vowel .. oxy],			}, {				n="+" .. vowel,				a="[nom]",				i="+ByAm",				d="[ins]",				ab="[ins]",				g=,				l="[gen]",				v="+" .. vowel,			}, {				n=,				a="+" .. vowel .. "s",				i="+Bis",				d="+Byas",				ab="[dat]",				g=sa_utils.lengthen[vowel] .. "nA" .. (oxy ~= "" and "/" or "") .. "m",				l="+su",				v=,			}) else decline(args, data, {				n="+",				a="[nom]",				i={ "+nA", { "+A", note = "Vedic" } },				d={ { stem = args.stem .. sa_utils.split_diphthong[sa_utils.up_one_grade[vowel .. oxy]], "e" }, { "+e", note = "Less common" } },				ab={ sa_utils.up_one_grade[vowel .. oxy] .. "s", { "+nas", note = "Later Sanskrit" }, { "+as", note = "Less common" }},				g="[abl]",				l={ "+ni" .. oxy, note = "Later Sanskrit" },				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 = "Later Sanskrit" } },				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 = "Later Sanskrit" } }, })		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 = SLP_to_IAST.tr(vowel) .. "-stem"

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 = "Vedic" } },					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 = "Vedic" } },					 g="+os",					 v={ "+O", { "+", note = "Vedic" } },				}, {					n={ "+as", { "+s", note = "Vedic" } },					v={ "+as", { "+s", note = "Vedic" } },				}) else decline(args, data, {					n="+s",					i="+A",					d="+E",					ab="+As",					g="[abl]",					l="+Am",					v=sa_utils.shorten[vowel],				}, {					n={ "+O", { "+", note = "Vedic" } },					g="+os",					v={ "+O", { "+", note = "Vedic" } },				}, {					n={ "+as", { "+s", note = "Vedic" } },					v={ "+as", { "+s", note = "Vedic" } },				}) 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=,					i=,					d=,					ab=,					l=,				}, {					n=,					g=,					v=,				}, {					n=,					g={ { "+Am", mono = true }, "+nAm" },					v=,				}) 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=,				i=,				d={ { "+e/", mono = true }, { "+E/", mono = true, note = "Later Sanskrit" } },				ab={ { "+a/s", mono = true }, { "+A/s", mono = true, note = "Later Sanskrit" } },				g="[abl]",				l={ { "+i/", mono = true }, { "+A/m", mono = true, note = "Later Sanskrit" } },				v="+s",			}, {				n=,				a="[nom]",				i=,				d="[ins]",				ab="[ins]",				g=,				l="[gen]",				v=,			}, {				n=,				a="[nom]",				i=,				d=,				ab="[dat]",				g={ { "+A/m", mono = true }, { "+nA/m", mono = true, note = "Later Sanskrit" } },				l=,				v=,			}) 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 not args.r_stem_a and args.g ~= "n" 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

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 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 = "Vedic" } },				g="ro" .. oxy .. "s",				v={ args.r_stem_a .. "rO", { args.r_stem_a .. "rA", note = "Vedic" } },			}, {				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=,			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 = "Vedic" } },				}, nil, {					n={ "+as", { "A" .. oxy .. "s", note = "Vedic" } },					v={ "+as", { "A" .. oxy .. "s", note = "Vedic" } },				}) else decline(args, data, {					n="+",					a="+am",				}, nil, {					n="+as",					v="+as",				}) end

decline(args, data, {				v="+",			}, {				n={ "+O", { "+A", note = "Vedic" } },				v={ "+O", { "+A", note = "Vedic" } },			}) else decline(args, data, {				n="+",				a="[nom]",				v="+",			}, {				n="+I",				v="+I",			}, {				n=,				v=,			}) 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 = "an-stem"

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 = "Vedic" } },					v={ "AnO", { "AnA", note = "Vedic" } },				}, {					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 = "Vedic" } },					v={ "AnO", { "AnA", note = "Vedic" } },				}, {					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, "Sanskrit an-stem nouns") 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 = "Vedic" } },				v={ "+O", { "+A", note = "Vedic" } },			}, {				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 })

return decl_data