Module:sa-verb/data

-- This is a data module for Module:sa-verb.

local conj_data = {}

local sa_utils = require("Module:sa-utilities") local to_IAST = require("Module:sa-utilities/translit/SLP1-to-IAST").tr

local sub = mw.ustring.sub local gsub = mw.ustring.gsub local gasub = string.gsub -- For when byte by byte comparison is good enough. local match = mw.ustring.match local split = mw.text.split

-- Returns { form, stem } if the stem is explicity provided in the form (i.e. form = "rinakti " or form = "rincanti ") local function split_xs(form) if form == nil then return nil end local s = split(form, "<") if s[2] ~= nil then local sanitized_s2 = sub(s[2], 1, -2) return {s[1], sanitized_s2} else return {form, nil} end end

-- Splits "stem1,stem2" into { stem1, stem2 } local function split_stems(form) -- TODO: in the older system, we'd have entries where multiple stems could be supplied and show up side-by-side in the same table. -- I.e. "áricat" and "áraikṣīt" as two aorist variants of "riṇakti". The current system is to make them both separate entries altogether -- so their conjugation systems don't overlap and cause confusion. -- Older entries using the older version of this module need to be updated—right now, any extra stems that are supplied are just ignored -- Note: this doesn't affect manually provided forms, like irregular third-person singular active perfects having long/short-vowel forms return split(form, ",")[1] end

local function apply_ending(args, data, tag, stem, es, is_part) if type(es) == "string" then es = {es} end local forms = data.forms[tag] or {} local i = #forms + 1 for _, e in ipairs(es) do       local note if type(e) == "table" then note = e.note e = e[1] end -- reduce Vedic forms to zero in case of novedic parameter if args.novedic == true and note and match(note, "[vV]edic$") then stem = ""; e = ""; note = "" else args.has_accent = match(stem, sa_utils.accent) local set_stem = stem -- if 'set', add 'i' between consonants, except before 'y' (optative) if args.set == true and match(stem, sa_utils.consonant .. "$") and match(e, "^[tTDmrvshQz]") then set_stem = sa_utils.internal_sandhi({   	            stem = stem,                	ending = "i",            	    has_accent = args.has_accent,        	        non_final = true,    	            mono = args.mono,    	            accent_override = args.accent_override,    	            no_retroflex_root_s = args.no_retroflex_root_s            	}) end if args.auto_sandhi == true then forms[i] = sa_utils.internal_sandhi({               	stem = set_stem,            	    ending = e,					has_accent = args.has_accent,                	non_final = is_part,            	    mono = args.mono,        	        j_to_z = args.j_to_z,                	h_to_g = args.h_to_g,					diaspirate = args.diaspirate,					no_syncope = args.no_syncope,					accent_override = args.accent_override,					no_retroflex_root_s = args.no_retroflex_root_s -- for roots 'pis'/'niṃs'/'hiṃs' and 'tresus' (from 'tras')            	}) else forms[i] = set_stem .. e       	end -- Apply special tagging, currently just Ⓛ. forms[i] = gasub(forms[i],				"a("..sa_utils.accent.."?)("..sa_utils.consonant.."a)Ⓛ", "A%1%2") forms[i] = gasub(forms[i], "Ⓛ", "") -- Clean up. if note then forms["note" .. i] = note end i = i + 1 end end data.forms[tag] = forms end

local function make_forms(args, data, stem, forms) for mood, mood_forms in pairs(forms) do   	if args.tense == "nonf" then local tag = mood apply_ending(args, data, tag, stem, mood_forms, false) else for voice, voice_forms in pairs(mood_forms) do	           if mood == "part" then local tag = mood .. "_" .. voice apply_ending(args, data, tag, stem, voice_forms, true) else for person_number, es in pairs(voice_forms) do local tag = mood .. "_" .. voice .. "_" .. person_number apply_ending(args, data, tag, stem, es, false) end end end end end end

local function validate(stem, lemma) if stem == nil then error("could not detect stem from " .. to_IAST(lemma) .. "; set args.o to fill in values manually") end end

local function detect(t, lemma, match_pattern, oxy_match_pattern, strong) local prefix = "weak_" if strong then prefix = "strong_" end

if not t[prefix .. "did_lemma"] then lemma = split_stems(lemma) local splitted = split_xs(lemma) if splitted == nil then return nil end t[prefix .. "3s"] = splitted[1]

t[prefix .. "stem"] = splitted[2] t[prefix .. "oxy"] = "" t[prefix .. "did_lemma"] = true end

local detected_stem = match(t[prefix .. "3s"], match_pattern) if detected_stem ~= nil then if oxy_match_pattern ~= nil then t[prefix .. "oxy"] = match(t[prefix .. "3s"], oxy_match_pattern) end if t[prefix .. "stem"] == nil then t[prefix .. "stem"] = detected_stem end return true end return false end

local function detect_strong(t, lemma, match_pattern, oxy_match_pattern) return detect(t, lemma, match_pattern, oxy_match_pattern, true) end

local function detect_weak(t, lemma, match_pattern, oxy_match_pattern) return detect(t, lemma, match_pattern, oxy_match_pattern, false) end

local function use_strong_for_weak(t, weak_lemma) if weak_lemma ~= nil then return false end t["weak_stem"] = t["strong_stem"] t["weak_oxy"] = t["strong_oxy"] return true end

-- Only for verbs with 3p on -ati, override with 'class=' parameter. -- Does not detect 'iyāy' and 'alar' (Whitney §1002e). local function detect_intensive(args, t)	-- anchoring detection pattern at the end to allow for prefixes if match(t.strong_stem, sa_utils.consonant.."a/?[nrlv][iI]"..sa_utils.consonant.."+"..sa_utils.vowel.."M?"..sa_utils.consonant.."*$") then if match(t.strong_stem, "vivy?"..sa_utils.vowel..sa_utils.consonant.."$") then -- prefixed class 3 verb like 'upaviveṣṭi' return false else -- dissyllabic reduplication return true end elseif match(t.strong_stem, sa_utils.consonant.."[Aeo]/?"..sa_utils.consonant.."+"..sa_utils.vowel_with_accent.."M?"..sa_utils.consonant.."*$") or match(t.strong_stem, sa_utils.consonant.."a/?[rlNYRnmMd]"..sa_utils.consonant.."+[aiufx]M?"..sa_utils.consonant.."*$") -- avoiding 'saṃśās' or args.class == "int" then t["intensive"] = "1" return true end end

conj_data["pres"] = {} setmetatable(conj_data["pres"], {   __call = function (self, args, data)        local make_thematic_forms = function (oxy)            return {                ["indic"] = {                    ["av"] = {                        ["1_s"] = "A" .. oxy .. "mi",                        ["2_s"] = "a" .. oxy .. "si",                        ["3_s"] = "a" .. oxy .. "ti",                        ["1_d"] = "A" .. oxy .. "vas",                        ["2_d"] = "a" .. oxy .. "Tas",                        ["3_d"] = "a" .. oxy .. "tas",                        ["1_p"] = "A" .. oxy .. "mas",                        ["2_p"] = "a" .. oxy .. "Ta",                        ["3_p"] = "a" .. oxy .. "nti"                    },                    ["mv"] = {                        ["1_s"] = "e" .. oxy .. "",                        ["2_s"] = "a" .. oxy .. "se",                        ["3_s"] = "a" .. oxy .. "te", ["1_d"] = "A" .. oxy .. "vahe", ["2_d"] = "e" .. oxy .. "Te", ["3_d"] = "e" .. oxy .. "te", ["1_p"] = "A" .. oxy .. "mahe", ["2_p"] = "a" .. oxy .. "Dve", ["3_p"] = "a" .. oxy .. "nte" }               },                ["imper"] = { ["av"] = { ["1_s"] = "A" .. oxy .. "ni", --                       ["2_s"] = {"a" .. oxy, "a" .. oxy .. "tAt"}, ["2_s"] = "a" .. oxy, ["3_s"] = "a" .. oxy .. "tu", ["1_d"] = "A" .. oxy .. "va", ["2_d"] = "a" .. oxy .. "tam", ["3_d"] = "a" .. oxy .. "tAm", ["1_p"] = "A" .. oxy .. "ma", ["2_p"] = "a" .. oxy .. "ta", ["3_p"] = "a" .. oxy .. "ntu" },                   ["mv"] = { ["1_s"] = "E" .. oxy .. "",                       ["2_s"] = "a" .. oxy .. "sva", ["3_s"] = "a" .. oxy .. "tAm", ["1_d"] = "A" .. oxy .. "vahE", ["2_d"] = "e" .. oxy .. "TAm", ["3_d"] = "e" .. oxy .. "tAm", ["1_p"] = "A" .. oxy .. "mahE", ["2_p"] = "a" .. oxy .. "Dvam", ["3_p"] = "a" .. oxy .. "ntAm" },               },                ["optat"] = { ["av"] = { ["1_s"] = "e" .. oxy .. "yam", ["2_s"] = "e" .. oxy .. "s", ["3_s"] = "e" .. oxy .. "t", ["1_d"] = "e" .. oxy .. "va", ["2_d"] = "e" .. oxy .. "tam", ["3_d"] = "e" .. oxy .. "tAm", ["1_p"] = "e" .. oxy .. "ma", ["2_p"] = "e" .. oxy .. "ta", ["3_p"] = "e" .. oxy .. "yus" },                   ["mv"] = { ["1_s"] = "e" .. oxy .. "ya", ["2_s"] = "e" .. oxy .. "TAs", ["3_s"] = "e" .. oxy .. "ta", ["1_d"] = "e" .. oxy .. "vahi", ["2_d"] = "e" .. oxy .. "yATAm", ["3_d"] = "e" .. oxy .. "yAtAm", ["1_p"] = "e" .. oxy .. "mahi", ["2_p"] = "e" .. oxy .. "Dvam", ["3_p"] = "e" .. oxy .. "ran" },               },                ["part"] = { ["av"] = "a" .. oxy .. "t", ["mv"] = "a" .. oxy .. "mAna" }           }        end

local make_athematic_strong_forms_cons = function return { ["indic"] = { ["av"] = { ["1_s"] = "mi", ["2_s"] = "si", ["3_s"] = "ti", },               },                ["imper"] = { ["av"] = { ["3_s"] = "tu", }               }            }        end local make_athematic_strong_forms_vow = function return { ["imper"] = { ["av"] = { ["1_s"] = "Ani", ["1_d"] = "Ava", ["1_p"] = "Ama", },                   ["mv"] = { ["1_s"] = "E", ["1_d"] = "AvahE", ["1_p"] = "AmahE", }               }            }		end local make_athematic_weak_forms_cons = function (oxy) -- endings starting with consonant not m/v/y return { ["indic"] = { ["av"] = { ["2_d"] = "Ta" .. oxy .. "s", ["3_d"] = "ta" .. oxy .. "s", ["2_p"] = "Ta" .. oxy, },                   ["mv"] = { ["2_s"] = "se" .. oxy, ["3_s"] = "te" .. oxy, ["2_p"] = "Dve" .. oxy, }               },                ["imper"] = { ["av"] = { --                       ["2_s"] = {"Di" .. oxy, "tA" .. oxy .. "t"}, ["2_d"] = "ta" .. oxy .. "m", ["3_d"] = "tA" .. oxy .. "m", ["2_p"] = "ta" .. oxy .. "",                   },                    ["mv"] = { ["2_s"] = "sva" .. oxy, ["3_s"] = "tA" .. oxy .. "m", ["2_p"] = "Dva" .. oxy .. "m", }               }            }        end local make_athematic_weak_forms_mvy = function (oxy) -- endings starting with m/v/y return { ["indic"] = { ["av"] = { ["1_d"] = "va" .. oxy .. "s", ["1_p"] = "ma" .. oxy .. "s", },                   ["mv"] = { ["1_d"] = "va" .. oxy .. "he", ["1_p"] = "ma" .. oxy .. "he", }               },                ["optat"] = { ["av"] = { ["1_s"] = "yA" .. oxy .. "m", ["2_s"] = "yA" .. oxy .. "s", ["3_s"] = "yA" .. oxy .. "t", ["1_d"] = "yA" .. oxy .. "va", ["2_d"] = "yA" .. oxy .. "tam", ["3_d"] = "yA" .. oxy .. "tAm", ["1_p"] = "yA" .. oxy .. "ma", ["2_p"] = "yA" .. oxy .. "ta", ["3_p"] = "yu" .. oxy .. "s" }               }            }        end local make_athematic_weak_forms_vow = function (oxy) -- endings starting with vowels return { ["indic"] = { ["av"] = { ["3_p"] = "a" .. oxy .. "nti" },                   ["mv"] = { ["1_s"] = "e" .. oxy, ["2_d"] = "A" .. oxy .. "Te", ["3_d"] = "A" .. oxy .. "te", ["3_p"] = "a" .. oxy .. "te" }               },                ["imper"] = { ["av"] = { ["3_p"] = "a" .. oxy .. "ntu" },                   ["mv"] = { ["2_d"] = "A" .. oxy .. "TAm", ["3_d"] = "A" .. oxy .. "tAm", ["3_p"] = "a" .. oxy .. "tAm" }               },                ["optat"] = { ["mv"] = { ["1_s"] = "Iya" .. oxy, ["2_s"] = "ITA" .. oxy .. "s", ["3_s"] = "Ita" .. oxy, ["1_d"] = "Iva" .. oxy .. "hi", ["2_d"] = "IyA" .. oxy .. "TAm", ["3_d"] = "IyA" .. oxy .. "tAm", ["1_p"] = "Ima" .. oxy .. "hi", ["2_p"] = "IDva" .. oxy .. "m", ["3_p"] = "Ira" .. oxy .. "n" }               },                ["part"] = { ["av"] = "a" .. oxy .. "t", ["mv"] = "Ana" .. oxy, }           }        end local make_athematic_class_3_forms_vow = function -- endings starting with vowel for class 3 (no oxy) return { ["indic"] = { ["av"] = { ["3_p"] = "ati" },                   ["mv"] = { ["1_s"] = "e", ["2_d"] = "ATe", ["3_d"] = "Ate", ["3_p"] = "ate" }               },                ["imper"] = { ["av"] = { ["3_p"] = "atu" },                   ["mv"] = { ["2_d"] = "ATAm", ["3_d"] = "AtAm", ["3_p"] = "atAm" }               },                ["optat"] = { ["mv"] = { ["1_s"] = "Iya", ["2_s"] = "ITAs", ["3_s"] = "Ita", ["1_d"] = "Ivahi", ["2_d"] = "IyATAm", ["3_d"] = "IyAtAm", ["1_p"] = "Imahi", ["2_p"] = "IDvam", ["3_p"] = "Iran" }               },                ["part"] = { ["av"] = "at", ["mv"] = "Ana", }       	}        end local make_extra_class_5_8_forms = function(oxy) return { ["indic"] = { ["av"] = { ["1_d"] = "va" .. oxy .. "s", ["1_p"] = "ma" .. oxy .. "s", },          			["mv"] = { ["1_d"] = "va" .. oxy .. "he", ["1_p"] = "ma" .. oxy .. "he", }          		},           		["imper"] = { ["av"] = { ["2_s"] = {"u" .. oxy, {"uhi" .. oxy, note = "Vedic"}} }              	}           	}        end local make_intensive_weak_forms_extra = function -- not in case of dissyllabic reduplication (Whitney §1007a) return { ["indic"] = { ["av"] = { ["1_s"] = "Imi", ["2_s"] = "Izi", ["3_s"] = "Iti", }              	},                ["imper"] = { ["av"] = { ["3_s"] = "Itu", }               }            	}        end local make_athematic_imper_2s_Di = function(oxy) return { ["imper"] = { ["av"] = { ["2_s"] = "Di" .. oxy }               }			}		end local make_athematic_imper_2s_hi = function(oxy) return { ["imper"] = { ["av"] = { ["2_s"] = "hi" .. oxy }               }			}		end local make_class_9_cons_imper_2s = function(oxy) return { ["imper"] = { ["av"] = { ["2_s"] = "Ana" .. oxy }               }			}		end local t = {} local is_thematic = args.weak_lemma == nil if is_thematic then if not detect_strong(t, args.strong_lemma, "(.+)a" .. sa_utils.accent .. "?ti$", "a(" .. sa_utils.accent .. "?)ti$") then if not detect_strong(t, args.strong_lemma, "(.+)a" .. sa_utils.accent .. "?te$", "a(" .. sa_utils.accent .. "?)te$") then validate(t["strong_stem"], args.strong_lemma) else args.n = "m" -- deponent end end make_forms(args, data, t["strong_stem"], make_thematic_forms(t["strong_oxy"])) -- class 10 (Whitney §1043f) if (args.class == "10" or not args.class) and match(t.strong_stem, sa_utils.vowel           	.."M?"..sa_utils.consonant.."+a" .. sa_utils.accent .. "?y$") then args.accent_override = true make_forms(args, data, t["strong_stem"], {					["part"] = {						["mv"] = ,					}       		}) end -- active athematic verbs elseif detect_strong(t, args.strong_lemma, "(.+)[tDwQ]i$") or match(args.strong_lemma, "^<.+>$") then if not detect_weak(t, args.weak_lemma, "(.+)a" .. sa_utils.accent .. "?nti$", "a(" .. sa_utils.accent .. "?)nti$") then if not detect_weak(t, args.weak_lemma, "(.+A)" .. sa_utils.accent .. "?nti$", "A(" .. sa_utils.accent .. "?)nti$") then if not detect_weak(t, args.weak_lemma, "(.+)ati$", sa_utils.vowel .. "(" .. sa_utils.accent .. "?).+ati$") then validate(t["weak_stem"], args.weak_lemma) else t.ati_3p = true end end end -- if no strong stem supplied, check weak stem in case of possible sandhi if match(args.strong_lemma, "[ktp]ti$")	then t.strong_stem = gasub(t.strong_stem, ".$", gasub(t.weak_stem, ".+(.)$", "%1")) -- if 3s ends on -dhi/-ṭi elseif match(args.strong_lemma, "[Dw]i$") then if match(t.weak_stem, "kz$") then t.strong_stem = gasub(t.strong_stem, "z$", "kz") else t.strong_stem = gasub(t.strong_stem, ".$", gasub(t.weak_stem, ".+(.)$", "%1")) if match(t.strong_stem, "h$") then args.h_to_g = true elseif match(t.strong_stem, "j$") then args.j_to_z = true end end -- if 3s ends on -ḍhi elseif match(args.strong_lemma, "Qi$") then t.strong_stem = gasub(t.strong_stem, "^(.*)$", "%1h") -- error for roots on -i/ī/u/ū when no weak stem provided elseif match(args.weak_lemma, sa_utils.consonant.."i?ya/?n?ti$") or ( match(args.weak_lemma, "uva/?n?ti$") and not match(t.strong_stem, "[nR]o/?")) then error("Please add weak stem for roots on -i/-ī and -u/-ū.") end make_forms(args, data, t["strong_stem"], make_athematic_strong_forms_cons) if t.ati_3p == true and match (t.strong_stem, "I$") then -- assuming 3s on -īti is intensive (as a normal class 3 root on -ī would have -eti) args.n = "a" make_forms(args, data, t["weak_stem"], make_athematic_strong_forms_vow) -- using weak stem with (normally) strong endings elseif t.ati_3p == true and (args.class == "int" or not args.class) and detect_intensive(args, t) then -- intensive verbs args.n = "a"	-- no middle (maybe add middle participle?) make_forms(args, data, t["weak_stem"], make_athematic_strong_forms_vow) if t.intensive == "1" then	-- no dissyllabic reduplication if match(t.strong_stem, sa_utils.vowel_with_accent.."$") then -- Whitney §1004a make_forms(args, data, t["strong_stem"], make_intensive_weak_forms_extra) else make_forms(args, data, t["weak_stem"], make_intensive_weak_forms_extra) end end else if match(t.strong_stem, "O/?$") and match(t.weak_stem, "u$") then -- Whitney §626 t.strong_stem = gasub(t.strong_stem, "O(/?)$", "a%1v") elseif match(t.strong_stem, "a/?vI$") and match(t.weak_stem, "[uU]v?$") then -- e.g. 'brū', see Whitney §632-3 t.strong_stem = gasub(t.strong_stem, "I$", "") elseif match(t.strong_stem, "i$") and match(t.weak_stem, "[^iy]$") then -- for 'set' verbs (Whitney §631) t.strong_stem = gasub(t.strong_stem, "i$", "") end make_forms(args, data, t["strong_stem"], make_athematic_strong_forms_vow) end if match(args.weak_lemma, "ati$") then -- if 3p on -ati and no weak stem provided args.accent_override = true -- for class 5/8 verbs on vowel + -noti elseif match(t.strong_stem, sa_utils.vowel .. "[nR]o/?$") then t.temp_stem = gasub(t.strong_stem, "o/?$", "") make_forms(args, data, t["temp_stem"], make_extra_class_5_8_forms(t["weak_oxy"])) -- includes active imper. 2s t.imper_2s_created = true -- for verbs like āpnoti elseif match(t.strong_stem, sa_utils.consonant .. "[nR]o/?$") then args.no_syncope = true t.weak_stem = gasub(t.weak_stem, "uv$", "u") -- class 9 elseif match(t.strong_stem, "[nR]A/?$") and match(t.weak_stem, "[nR]$") then t.weak_stem = gasub(t.weak_stem, "^.*$", "%1I") end if t.imper_2s_created == true then -- do nothing elseif match(t.weak_stem, sa_utils.consonant .."[nR]I$") then -- Whitney §722 t.temp_stem = gasub(t.weak_stem, "[nR]I$", "") make_forms(args, data, t["temp_stem"], make_class_9_cons_imper_2s(t["weak_oxy"])) elseif match(t.weak_stem, sa_utils.vowel .. "$") or match(t.weak_stem, sa_utils.consonant.."[yrv]$") or match(t.weak_stem, "^y$") then make_forms(args, data, t["weak_stem"], make_athematic_imper_2s_hi(t["weak_oxy"])) else make_forms(args, data, t["weak_stem"], make_athematic_imper_2s_Di(t["weak_oxy"])) end make_forms(args, data, t["weak_stem"], make_athematic_weak_forms_cons(t["weak_oxy"])) if args.extra_1p_stem then -- optional extra stem for endings starting with m/v/y t.weak_stem = args.extra_1p_stem end make_forms(args, data, t["weak_stem"], make_athematic_weak_forms_mvy(t["weak_oxy"])) if match(args.weak_lemma, ".<.*>$") then t.weak_stem = gasub(args.weak_lemma, "a?" .. sa_utils.accent .. "?n?ti<.*>$", "") elseif args.extra_1p_stem or match(t.weak_stem, "[nR]I$") then t.weak_stem = gasub(args.weak_lemma, "a?" .. sa_utils.accent .. "?nti$", "") end if t.ati_3p == true then args.accent_override = false make_forms(args, data, t["weak_stem"], make_athematic_class_3_forms_vow) else make_forms(args, data, t["weak_stem"], make_athematic_weak_forms_vow(t["weak_oxy"])) end -- deponent verbs elseif detect_strong(t, args.strong_lemma, "(.+)[tDwQ]e/?$", "[tDwQ]e(/?)$") then args.n = "m" -- deponent if not detect_weak(t, args.weak_lemma, "(.+"..sa_utils.accent..".+)ate$", sa_utils.vowel.."("..sa_utils.accent..").+ate$") then if not detect_weak(t, args.weak_lemma, "(.+)a"..sa_utils.accent.."?te$", "a("..sa_utils.accent.."?)te$") then if not detect_weak(t, args.weak_lemma, "(.+A/?)te$") then validate(t["weak_stem"], args.weak_lemma) end end elseif t.strong_oxy ~= "" then t.accented_class_3 = true end -- for class 5/8 verbs on vowel + -nute (+ tarute) -- adding '-no' for detection as this might be the strong stem supplied to form 1st person imperative if match(t.strong_stem, sa_utils.vowel .. "[nRr][uo]/?$") and (not args.class or match(args.class, "^[58]$")) and not args.extra_1p_stem then t.temp_stem = gasub(t.strong_stem, "[uo]/?$", "") make_forms(args, data, t["temp_stem"], make_extra_class_5_8_forms(t["weak_oxy"])) -- for verbs like āpnoti, but middle (the regex also includes hnute, but this is ok) elseif match(t.strong_stem, sa_utils.consonant .. "[nR][uo]/?$") then args.no_syncope = true end -- produce 1st person imperative if strong stem is supplied with 3sg if match(args.strong_lemma, "<.*>$") then make_forms(args, data, t["strong_stem"], make_athematic_strong_forms_vow) -- or if root has 'a/ā' (when guṇa would be the same), -- and not accented class 3 (accent on strong stem unpredictable) or potentially class 7 elseif match(t.strong_stem, "[aA]"..sa_utils.accent.."?"..sa_utils.consonant.."*$") and not t.accented_class_3 == true and not match(t.strong_stem, "[NYRnm]"..sa_utils.consonant.."$") then -- look at 3p to avoid possible sandhi before 3s -te t.strong_stem = gasub(t.weak_stem, "([aA])("..sa_utils.consonant.."*)$", "%1"..t.strong_oxy.."%2") make_forms(args, data, t["strong_stem"], make_athematic_strong_forms_vow) -- or if stem ends on -[nṇ]u (including hnu/snu is ok) elseif match(t.strong_stem, "[nR]u$") then t.strong_stem = gasub(t.strong_stem, "u$", "o"..t.strong_oxy) make_forms(args, data, t["strong_stem"], make_athematic_strong_forms_vow) -- or class 9 elseif match(t.strong_stem, "[nR]I$") and match(t.weak_stem, "[nR]$") then t.strong_stem = gasub(t.strong_stem, "I$", "A"..t.strong_oxy) make_forms(args, data, t["strong_stem"], make_athematic_strong_forms_vow) end if match(args.strong_lemma, sa_utils.vowel_with_accent .. "te/?$") then t.weak_stem_before_cons = gasub(args.strong_lemma, "te/?$", "") elseif match(args.strong_lemma, sa_utils.vowel_with_accent .. "te/?<.*>$") then t.weak_stem_before_cons = gasub(args.strong_lemma, "te/?<.*>$", "") else t.weak_stem_before_cons = t.weak_stem end if t.accented_class_3 == true then args.accent_override = true -- no accent on class 3 stem if ending starts with consonant end make_forms(args, data, t["weak_stem_before_cons"], make_athematic_weak_forms_cons(t["strong_oxy"])) if args.extra_1p_stem then t.weak_stem_before_cons = args.extra_1p_stem end make_forms(args, data, t["weak_stem_before_cons"], make_athematic_weak_forms_mvy(t["strong_oxy"])) if match(args.weak_lemma, ".<.*>$") then t.weak_stem = gasub(args.weak_lemma, "a?" .. sa_utils.accent .. "?te<.*>$", "") end if t.accented_class_3 == true then args.accent_override = false make_forms(args, data, t["weak_stem"], make_athematic_class_3_forms_vow) else make_forms(args, data, t["weak_stem"], make_athematic_weak_forms_vow(t["weak_oxy"])) end else validate(t["strong_stem"], args.strong_lemma) end end })

conj_data["impf"] = {} setmetatable(conj_data["impf"], {   __call = function (self, args, data)    	-- accent for augmentless forms    	local make_thematic_impf_forms = function(oxy)     		return {               	["indic"] = {                   	["av"] = {                       	["1_s"] = "a" .. oxy .. "m",                       	["2_s"] = "a" .. oxy .. "s",               	        ["3_s"] = "a" .. oxy .. "t",                   	    ["1_d"] = "A" .. oxy .. "va",                       	["2_d"] = "a" .. oxy .. "tam",                        ["3_d"] = "a" .. oxy .. "tAm",               	        ["1_p"] = "A" .. oxy .. "ma",                   	    ["2_p"] = "a" .. oxy .. "ta",                       	["3_p"] = "a" .. oxy .. "nt"                   	},                   	["mv"] = {                       	["1_s"] = "e" .. oxy,                       	["2_s"] = "a" .. oxy .. "TAs",                       	["3_s"] = "a" .. oxy .. "ta", ["1_d"] = "A" .. oxy .. "vahi", ["2_d"] = "e" .. oxy .. "TAm", ["3_d"] = "e" .. oxy .. "tAm", ["1_p"] = "A" .. oxy .. "mahi", ["2_p"] = "a" .. oxy .. "Dvam", ["3_p"] = "a" .. oxy .. "nta" },              	}            }    	end local athematic_impf_strong_endings_cons = { ["indic"] = { ["av"] = { ["2_s"] = "s", ["3_s"] = "t", },           },        }    	local athematic_impf_strong_endings_vow = { ["indic"] = { ["av"] = { ["1_s"] = "am", },           },        }    	-- accent for augmentless forms local make_athematic_impf_weak_forms_cons = function(oxy) -- endings starting with consonants not m/v/y return { ["indic"] = { ["av"] = { ["2_d"] = "ta" .. oxy .. "m", ["3_d"] = "tA" .. oxy .. "m", ["2_p"] = "ta" .. oxy, },   	            ["mv"] = { ["2_s"] = "TA" .. oxy .. "s", ["3_s"] = "ta" .. oxy, ["2_p"] = "Dva" .. oxy .. "m", }           	}        	}    	end local make_athematic_impf_weak_forms_mvy = function(oxy) -- endings starting with m/v/y return { ["indic"] = { ["av"] = { ["1_d"] = "va" .. oxy, ["1_p"] = "ma" .. oxy, },   	            ["mv"] = { ["1_d"] = "va" .. oxy .. "hi", ["1_p"] = "ma" .. oxy .. "hi", }           	}        	}    	end local make_athematic_impf_weak_forms_vow = function(oxy) -- endings starting with vowels (without active 3p) return { ["indic"] = { ["av"] = { --                   	["3_p"] = "a" .. oxy .. "n", },   	            ["mv"] = { ["1_s"] = "i" .. oxy, ["2_d"] = "A" .. oxy .. "TAm", ["3_d"] = "A" .. oxy .. "tAm", ["3_p"] = "a" .. oxy .. "ta" }           	}        	}    	end local make_athematic_impf_3p_an = function(oxy) return { ["indic"] = { ["av"] = { ["3_p"] = "a" .. oxy .. "n" }       		}        	}    	end local make_athematic_impf_3p_us = function(oxy) return { ["indic"] = { ["av"] = { ["3_p"] = "u" .. oxy .. "s" }       		}        	}    	end local intensive_impf_weak_endings_extra = { ["indic"] = { ["av"] = { ["2_s"] = "Is", ["3_s"] = "It", },           },        }    	local t = {} local is_thematic = args.weak_lemma == nil if is_thematic then if not detect_strong(t, args.strong_lemma, "(.+)a/?t$", "a(/?)t$") then if not detect_strong(t, args.strong_lemma, "(.+)a/?ta$", "a(/?)ta$") then validate(t["strong_stem"], args.strong_lemma) else args.n = "m" -- deponent end end make_forms(args, data, t["strong_stem"], make_thematic_impf_forms(t["strong_oxy"])) -- active verbs elseif detect_strong(t, args.strong_lemma, "(.*" .. sa_utils.vowel_with_accent .. ")t$") or detect_strong(t, args.strong_lemma, "(.+[kNwRtnprlsH])$") or match(args.strong_lemma, "^<.+>$") then if not detect_weak(t, args.weak_lemma, "(.+)a/?n$", "a(/?)n$") then if not detect_weak(t, args.weak_lemma, "(.+A)/?n$", "A(/?)n$") then if not detect_weak(t, args.weak_lemma, "(.+)u[Hs]$") then validate(t["weak_stem"], args.weak_lemma) else t.us_3p = true end end end -- look at weak stem if 3s '-t' disappeared and no strong stem is supplied if match(args.strong_lemma, "[kwpH]$") then if args.diaspirate == true then t.strong_stem = gasub(t.strong_stem, "([GDB])(.+)$", function(cons, post) return sa_utils.deaspirate[cons] .. post end) end if match(args.strong_lemma, "k$") then t.strong_stem = gasub(t.strong_stem, ".$", gasub(t.weak_stem, ".+(.)$", "%1")) if match(t.strong_stem, "h$") then args.h_to_g = true end elseif match(t.weak_stem, "kz$") then t.strong_stem = gasub(t.strong_stem, ".$", "kz") else t.strong_stem = gasub(t.strong_stem, ".$", gasub(t.weak_stem, ".+(.)$", "%1")) if match(t.strong_stem, "j$") then args.j_to_z = true elseif match(t.strong_stem, "f$") then t.strong_stem = gasub(t.strong_stem, ".$", "r") end end elseif match(t.weak_stem, "[tTdD]$") and match(args.strong_lemma, "[^tTdD]" .. sa_utils.vowel_with_accent.."t$") then t.strong_stem = gasub(t.strong_stem, "^(.+)$", "%1" .. gasub(t.weak_stem, ".+(.)$", "%1")) -- error for roots on -i/ī/u/ū when no weak stem provided elseif match(args.weak_lemma, sa_utils.consonant.."i?ya/?n$") or ( match(args.weak_lemma, "uva/?n$") and not match(t.strong_stem, "[nR]o/?")) then error("Please add weak stem for roots on -i/-ī and -u/-ū.") end -- intensive verbs if t.us_3p == true and match(t.strong_stem, "I$") then -- assuming 3s on -īt is intensive (as a normal class 3 root on -ī would have -et) args.n = "a" make_forms(args, data, t["weak_stem"], athematic_impf_strong_endings_vow) -- using weak stem with (normally) strong ending elseif t.us_3p == true and (args.class == "int" or not args.class) and detect_intensive(args, t) then args.n = "a" -- no middle make_forms(args, data, t["weak_stem"], athematic_impf_strong_endings_vow) else -- non-intensive if match(args.strong_lemma, "O/?t$") and match(t.weak_stem, "u$") then -- Whitney §626 t.strong_stem_before_vow = gasub(t.strong_stem, "O(/?)$", "a%1v") -- verbs with inserted 'ī' in 2/3 sg., see Whitney §631-3 (roots on -ī should have -e in strong stem) elseif match(args.strong_lemma, "It$") then t.strong_stem_before_vow = gasub(t.strong_stem, "I$", "") else t.strong_stem_before_vow = t.strong_stem end make_forms(args, data, t["strong_stem_before_vow"], athematic_impf_strong_endings_vow) end -- use 3s form for 2s and 3s (if appropriate) local syllable = sa_utils.vowel_with_accent..sa_utils.consonant.."+" if match(args.strong_lemma, "^"..syllable..sa_utils.vowel_with_accent   		.."t<"..syllable..sa_utils.vowel_with_accent.."[tTdD]>$") or match(args.strong_lemma, "^"..syllable..syllable..sa_utils.vowel_with_accent.."t<"   		..syllable..syllable..sa_utils.vowel_with_accent.."[tTdD]>$") then -- do nothing elseif match(args.strong_lemma, sa_utils.vowel_with_accent.."t<.+>$") then t.strong_stem = gasub(args.strong_lemma, "t<.+>$", "") end make_forms(args, data, t["strong_stem"], athematic_impf_strong_endings_cons) -- if intensive without dissyllabic reduplication if t.intensive == "1" then if match(t.strong_stem, sa_utils.vowel_with_accent.."$") then -- Whitney §1004a make_forms(args, data, t["strong_stem"], intensive_impf_weak_endings_extra) else make_forms(args, data, t["weak_stem"], intensive_impf_weak_endings_extra) end end -- e.g. āpnot if match(t.strong_stem, sa_utils.consonant .. "[nR]o/?$") then args.no_syncope = true t.weak_stem = gasub(t.weak_stem, "uv$", "u") -- extra forms for verbs on vowel + -noti elseif match(t.strong_stem, sa_utils.vowel .. "[nR]o/?$") then t.temp_stem = gasub(t.strong_stem, "o/?$", "") make_forms(args, data, t["temp_stem"], make_athematic_impf_weak_forms_mvy(t["weak_oxy"])) -- class 9 elseif match(t.strong_stem, "[nR]A/?$") and match(t.weak_stem, "[nR]$") then t.weak_stem = gasub(t.weak_stem, "^.*$", "%1I") -- class 3 roots on -ṛ elseif match(args.weak_lemma, ".aru[Hs]$") and not match(t.strong_stem, "A/?$") then t.weak_stem = gasub(t.weak_stem, "ar$", "f") -- class 3 roots on -i/ī/u/ū with no weak stem provided elseif match(args.weak_lemma, ".a[vy]u[Hs]$") and not match(t.strong_stem, "A/?$") then error("Please add weak stem for class 3 roots on -i/-ī and -u/-ū.") end make_forms(args, data, t["weak_stem"], make_athematic_impf_weak_forms_cons(t["weak_oxy"])) if args.extra_1p_stem then t.weak_stem = args.extra_1p_stem end make_forms(args, data, t["weak_stem"], make_athematic_impf_weak_forms_mvy(t["weak_oxy"])) if match(args.weak_lemma, "n<.*>$") then t.weak_stem = gasub(args.weak_lemma, "a?/?n<.*>$", "") -- class 3 verbs on -ā with weak stem supplied elseif match(args.weak_lemma, "u[Hs]<.*>$") and match(t.strong_stem, "A$") then t.weak_stem = gasub(args.weak_lemma, "u[Hs]<.*>$", "") elseif args.extra_1p_stem or match(t.weak_stem, "[nR]I$") then t.weak_stem = gasub(args.weak_lemma, "a/?n$", "") end make_forms(args, data, t["weak_stem"], make_athematic_impf_weak_forms_vow(t["weak_oxy"])) if t.us_3p == true then -- active 3p for class 3 verbs is often not from the weak stem if match(args.weak_lemma, ".<.*>$") then t.weak_stem = gasub(args.weak_lemma, 'u[Hs]<.*>$', '') else t.weak_stem = gasub(t.weak_stem, "f$", "ar") end make_forms(args, data, t["weak_stem"], make_athematic_impf_3p_us(t["weak_oxy"])) else if match(t.strong_stem, "A$") and match(t.weak_stem, "A$") then	-- Whitney §621a t.temp_stem = gasub(t.weak_stem, "A$", "") make_forms(args, data, t["temp_stem"], make_athematic_impf_3p_us(t["weak_oxy"])) end make_forms(args, data, t["weak_stem"], make_athematic_impf_3p_an(t["weak_oxy"])) end -- deponent verbs elseif detect_strong(t, args.strong_lemma, "(.+)[tDwQ]a/?$") then if detect_weak(t, args.weak_lemma, "(.+)a/?ta$", "a(/?)ta$") or detect_weak(t, args.weak_lemma, "(.+A/?)ta$") then args.n = "m" -- deponent -- for verbs on vowel + -nuta (+ impf. of tarute) if match(t.strong_stem, sa_utils.vowel .. "[nRr]u$") and (not args.class or match(args.class, "^[58]$")) and not args.extra_1p_stem then t.temp_stem = gasub(t.strong_stem, "u$", "") make_forms(args, data, t["temp_stem"], make_athematic_impf_weak_forms_mvy(t["weak_oxy"])) -- e.g. āpnot, but middle elseif match(t.strong_stem, sa_utils.consonant .. "[nR]u?$") then args.no_syncope = true end if match(args.strong_lemma, sa_utils.vowel_with_accent .. "ta$") then t.weak_stem_before_cons = gasub(args.strong_lemma, "ta$", "") else t.weak_stem_before_cons = t.weak_stem end make_forms(args, data, t["weak_stem_before_cons"], make_athematic_impf_weak_forms_cons(t["weak_oxy"])) if args.extra_1p_stem then t.weak_stem_before_cons = args.extra_1p_stem end make_forms(args, data, t["weak_stem_before_cons"], make_athematic_impf_weak_forms_mvy(t["weak_oxy"])) if match(args.weak_lemma, ".<.*>$") then t.weak_stem = gasub(args.weak_lemma, "a?/?ta<.*>$", "") end make_forms(args, data, t["weak_stem"], make_athematic_impf_weak_forms_vow(t["weak_oxy"])) else validate(t["weak_stem"], args.weak_lemma) end else validate(t["strong_stem"], args.strong_lemma) end end })

conj_data["fut"] = {} setmetatable(conj_data["fut"], {   __call = function (self, args, data)        local make_strong_forms = function (oxy)            return {                ["indic"] = {                    ["av"] = {                        ["1_s"] = "syA" .. oxy .. "mi",                        ["2_s"] = "sya" .. oxy .. "si",                        ["3_s"] = "sya" .. oxy .. "ti",                        ["1_d"] = "syA" .. oxy .. "vas",                        ["2_d"] = "sya" .. oxy .. "Tas",                        ["3_d"] = "sya" .. oxy .. "tas",                        ["1_p"] = "syA" .. oxy .. "mas",                        ["2_p"] = "sya" .. oxy .. "Ta",                        ["3_p"] = "sya" .. oxy .. "nti"                    },                    ["mv"] = {                        ["1_s"] = "sye" .. oxy,                        ["2_s"] = "sya" .. oxy .. "se",                        ["3_s"] = "sya" .. oxy .. "te", ["1_d"] = "syA" .. oxy .. "vahe", ["2_d"] = "sye" .. oxy .. "Te", ["3_d"] = "sye" .. oxy .. "te", ["1_p"] = "syA" .. oxy .. "mahe", ["2_p"] = "sya" .. oxy .. "Dve", ["3_p"] = "sya" .. oxy .. "nte" }               },                ["part"] = { ["av"] = "sya" .. oxy .. "t", ["mv"] = "sya" .. oxy .. "mAna" }           }        end local t = {} if not detect_strong(t, args.strong_lemma, "(.+).ya" .. sa_utils.accent .. "?ti$", "(" .. sa_utils.accent .. "?)ti$") then if not detect_strong(t, args.strong_lemma, "(.+).ya" .. sa_utils.accent .. "?te$", "(" .. sa_utils.accent .. "?)te$") then validate(t["strong_stem"], args.strong_lemma) else args.n = "m" -- deponent end end make_forms(args, data, t["strong_stem"], make_strong_forms(t["strong_oxy"])) table.insert(data.categories, "Sanskrit verbs with s-future") end })

conj_data["pfut"] = {} setmetatable(conj_data["pfut"], {	__call = function (self, args, data)		local make_perph_forms = function (oxy)           return {                ["indic"] = {                    ["av"] = {                        ["1_s"] = "tA" .. oxy .. "smi",                        ["2_s"] = "tA" .. oxy .. "si",                        ["3_s"] = "tA" .. oxy,                        ["1_d"] = "tA" .. oxy .. "svas",                        ["2_d"] = "tA" .. oxy .. "sTas",                        ["3_d"] = {"tA" .. oxy .. "rO", {"tA" .. oxy .. "rA", note = "Vedic"}}, -- 'gantārā' occurs in Rigveda 8.13.10                        ["1_p"] = "tA" .. oxy .. "smas",                        ["2_p"] = "tA" .. oxy .. "sTa",                        ["3_p"] = "tA" .. oxy .. "ras"                    },                    ["mv"] = {                        ["1_s"] = "tA" .. oxy .. "he",                        ["2_s"] = "tA" .. oxy .. "se", ["3_s"] = "tA" .. oxy, ["1_d"] = "tA" .. oxy .. "svahe", ["2_d"] = "tA" .. oxy .. "sATe", ["3_d"] = "tA" .. oxy .. "rO", ["1_p"] = "tA" .. oxy .. "smahe", ["2_p"] = "tA" .. oxy .. "Dve", ["3_p"] = "tA" .. oxy .. "ras" }               },            }		end local t = {} if not detect_strong(t, args.strong_lemma, "(.+)tA" .. sa_utils.accent .. "?$", "(" .. sa_utils.accent .. "?)$") then validate(t["strong_stem"], args.strong_lemma) -- for the periphrastic future, there is no way to tell if the verb is deponent from the lemma (third-person singular form) -- atmanepada verbs require the "n=m" argument to avoid showing the active forms end make_forms(args, data, t["strong_stem"], make_perph_forms(t["strong_oxy"])) table.insert(data.categories, "Sanskrit verbs with periphrastic future") end })

conj_data["cond"] = {} setmetatable(conj_data["cond"], {   __call = function (self, args, data)        local t = {}        if not detect_strong(t, args.strong_lemma, "(.+).yat$") then            if not detect_strong(t, args.strong_lemma, "(.+).yata$") then                validate(t["strong_stem"], args.strong_lemma)            else                args.n = "m" -- deponent            end        end        make_forms(args, data, t["strong_stem"], { ["indic"] = { ["av"] = { ["1_s"] = "syam", ["2_s"] = "syas", ["3_s"] = "syat", ["1_d"] = "syAva", ["2_d"] = "syatam", ["3_d"] = "syatAm", ["1_p"] = "syAma", ["2_p"] = "syata", ["3_p"] = "syant" },               ["mv"] = { ["1_s"] = "sye", ["2_s"] = "syaTAs", ["3_s"] = "syata", ["1_d"] = "syAvahi", ["2_d"] = "syeTAm", ["3_d"] = "syetAm", ["1_p"] = "syAmahi", ["2_p"] = "syaDvam", ["3_p"] = "syanta" }           }        })    end })

conj_data["aor"] = {} setmetatable(conj_data["aor"], {   __call = function (self, args, data)        -- there is some added complexity here compared to the other tenses due to the number of aorist types in Sanskrit        local strong_is_endings = {            ["indic"] = {                ["av"] = {                    ["1_s"] = "izam",                    ["2_s"] = "Is",                    ["3_s"] = "It",                    ["1_d"] = "izva",                    ["2_d"] = "izwam",                    ["3_d"] = "izwAm",                    ["1_p"] = "izma",                    ["2_p"] = "izwa",                    ["3_p"] = "izus"                },            }        }

local weak_is_endings = { ["indic"] = { ["mv"] = { ["1_s"] = "izi", ["2_s"] = "izWAs", ["3_s"] = "izwa", ["1_d"] = "izvahi", ["2_d"] = "izATAm", ["3_d"] = "izAtAm", ["1_p"] = "izmahi", ["2_p"] = "iQvam", ["3_p"] = "izata" },           }        }

local strong_s_endings = { ["indic"] = { ["av"] = { ["1_s"] = "sam", ["2_s"] = {"sIs", {"s", note = "Vedic"}}, ["3_s"] = {"sIt", {"s", note = "Vedic"}}, ["1_d"] = "sva", ["2_d"] = "stam", ["3_d"] = "stAm", ["1_p"] = "sma", ["2_p"] = "sta", ["3_p"] = "sus" },           }        }

local weak_s_endings = { ["indic"] = { ["mv"] = { ["1_s"] = "si", ["2_s"] = "sTAs", ["3_s"] = "sta", ["1_d"] = "svahi", ["2_d"] = "sATAm", ["3_d"] = "sAtAm", ["1_p"] = "smahi", ["2_p"] = "sDvam", -- further treated by sandhi module ["3_p"] = "sata" },           }        }        -- accent for augmentless forms local make_strong_sa_forms = function(oxy) return { ["indic"] = { ["av"] = { ["1_s"] = "sa" .. oxy .. "m", ["2_s"] = "sa" .. oxy .. "s", ["3_s"] = "sa" .. oxy .. "t", ["1_d"] = "sA" .. oxy .. "va", ["2_d"] = "sa" .. oxy .. "tam", ["3_d"] = "sa" .. oxy .. "tAm", ["1_p"] = "sA" .. oxy .. "ma", ["2_p"] = "sa" .. oxy .. "ta", ["3_p"] = "sa" .. oxy .. "n" },           	}        	}        end local make_weak_sa_forms = function (oxy) return { ["indic"] = { ["mv"] = { ["1_s"] = "si" .. oxy, ["2_s"] = "sa" .. oxy .. "TAs", ["3_s"] = "sa" .. oxy .. "ta", ["1_d"] = "sA" .. oxy .. "vahi", ["2_d"] = "sA" .. oxy .. "TAm", ["3_d"] = "sA" .. oxy .. "tAm", ["1_p"] = "sA" .. oxy .. "mahi", ["2_p"] = "sa" .. oxy .. "Dvam", ["3_p"] = "sa" .. oxy .. "nta" },           	}        	}        end -- accent for augmentless forms local make_strong_a_forms = function(oxy) return { ["indic"] = { ["av"] = { ["1_s"] = "a" .. oxy .. "m", ["2_s"] = "a" .. oxy .. "s", ["3_s"] = "a" .. oxy .. "t", ["1_d"] = "A" .. oxy .. "va", ["2_d"] = "a" .. oxy .. "tam", ["3_d"] = "a" .. oxy .. "tAm", ["1_p"] = "A" .. oxy .. "ma", ["2_p"] = "a" .. oxy .. "ta", ["3_p"] = "a" .. oxy .. "nt" },           	}        	}        end local make_weak_a_forms = function(oxy) return { ["indic"] = { ["mv"] = { ["1_s"] = "e" .. oxy, ["2_s"] = "a" .. oxy .. "TAs", ["3_s"] = "a" .. oxy .. "ta", ["1_d"] = "A" .. oxy .. "vahi", ["2_d"] = "e" .. oxy .. "TAm", ["3_d"] = "e" .. oxy .. "tAm", ["1_p"] = "A" .. oxy .. "mahi", ["2_p"] = "a" .. oxy .. "Dvam", ["3_p"] = "a" .. oxy .. "nta" },           	}        	}        end

local strong_root_endings = { -- without 3p ["indic"] = { ["av"] = { ["1_s"] = "am", ["2_s"] = "s", ["3_s"] = "t", ["1_d"] = "va", ["2_d"] = "tam", ["3_d"] = "tAm", ["1_p"] = "ma", ["2_p"] = "ta", --             	["3_p"] = "us" -- for bhū: -an (abhūvan) }           }        }        -- only for some Vedic forms, the root-aorist can only be in active voice in Classical Sanskrit -- to some extent speculative local weak_root_endings = { ["indic"] = { ["mv"] = { ["1_s"] = "i", ["2_s"] = "TAs", ["3_s"] = "ta", ["1_d"] = "vahi", ["2_d"] = "ATAm", ["3_d"] = "AtAm", -- 'akrātām' (Whitney §834a) ["1_p"] = "mahi", ["2_p"] = "Dvam", ["3_p"] = "ata" -- but '-ran' frequently occurs, see Whitney §834b },           }        }        local t = {} local weak_lemma = args.weak_lemma or args.passive_lemma -- detection of oxytone accent in case of injunctive if (not args.aor or args.aor == "sa") and detect_strong(t, args.strong_lemma, "(.+k)za/?t$", "kza(/?)t$") then table.insert(data.categories, "Sanskrit verbs with sa-aorist") make_forms(args, data, t["strong_stem"], make_strong_sa_forms(t["strong_oxy"])) if use_strong_for_weak(t, weak_lemma) then make_forms(args, data, t["weak_stem"], make_weak_sa_forms(t["weak_oxy"])) end elseif (not args.aor or args.aor == "s" or args.aor == "ṣ") and detect_strong(t, args.strong_lemma, "(.+)[sz]It$") then table.insert(data.categories, "Sanskrit verbs with s-aorist") make_forms(args, data, t["strong_stem"], strong_s_endings) if use_strong_for_weak(t, weak_lemma) then make_forms(args, data, t["weak_stem"], weak_s_endings) end elseif (not args.aor or args.aor == "iṣ" or args.aor == "siṣ") and detect_strong(t, args.strong_lemma, "(.+)It$") then if args.aor == "siṣ" then table.insert(data.categories, "Sanskrit verbs with siṣ-aorist") make_forms(args, data, t["strong_stem"], strong_is_endings) -- middle forms for siṣ-aorist are not allowed by the grammarians (but might have existed: Whitney §915) else table.insert(data.categories, "Sanskrit verbs with iṣ-aorist") make_forms(args, data, t["strong_stem"], strong_is_endings) if use_strong_for_weak(t, weak_lemma) then make_forms(args, data, t["weak_stem"], weak_is_endings) end end elseif (not args.aor or args.aor == "a") and detect_strong(t, args.strong_lemma, "(.+)a/?t$", "a(/?)t$") then table.insert(data.categories, "Sanskrit verbs with a-aorist") make_forms(args, data, t["strong_stem"], make_strong_a_forms(t["strong_oxy"])) if use_strong_for_weak(t, weak_lemma) then make_forms(args, data, t["weak_stem"], make_weak_a_forms(t["weak_oxy"])) end -- the 't' of 'avart' should be detected as part of the stem elseif (not args.aor or args.aor == "root") and (detect_strong(t, args.strong_lemma, "(.+" .. sa_utils.vowel .. ")t$")       or detect_strong(t, args.strong_lemma, "(.+[kNwRtnprlsH])$") ) then table.insert(data.categories, "Sanskrit verbs with root-aorist") make_forms(args, data, t["strong_stem"], strong_root_endings) -- for active 3p, remove final ā from stem if match(t.strong_stem, "A$") then t.strong_stem = gasub(t.strong_stem, "A$", "") make_forms(args, data, t["strong_stem"], { 					["indic"] = {          				["av"] = {           					["3_p"] = "us"           				}           			}           		}) else make_forms(args, data, t["strong_stem"], { 					["indic"] = {       				["av"] = {        					["3_p"] = "an"        				}           			}           		}) end elseif args.strong_lemma ~= "-" then error("Could not detect aorist type from " .. to_IAST(args.strong_lemma)) -- failed to recognize an aorist type end if weak_lemma then -- if ends on -gdha, -ddha or -bdha, then the stem necessarily ends on resp. -h/dh/bh local aspirate = { ['g'] = 'h', ['d'] = 'D', ['b'] = 'B' } weak_lemma = gasub(weak_lemma, '(.+)([gdb])(Da)$', function(a,b,c) return a .. aspirate[b].. c end) if match(weak_lemma, "hDa$") then args.h_to_g = true end if (not args.aor or args.aor == "iṣ") and detect_weak(t, weak_lemma, "(.+)izwa$") then table.insert(data.categories, "Sanskrit verbs with iṣ-aorist") make_forms(args, data, t["weak_stem"], weak_is_endings) elseif (not args.aor or args.aor == "sa") and detect_weak(t, weak_lemma, "(.+k)za/?ta$", "kza(/?)ta$") then table.insert(data.categories, "Sanskrit verbs with sa-aorist") make_forms(args, data, t["weak_stem"], make_weak_sa_forms(t["weak_oxy"])) elseif (not args.aor or args.aor == "[sṣ]") and (detect_weak(t, weak_lemma, "(.+)sta$") or detect_weak(t, weak_lemma, "(.+)zwa$")           or detect_weak(t, weak_lemma, "(.+[ktp])ta$") or detect_weak(t, weak_lemma, "(.+[ghdDbB])Da$")) then table.insert(data.categories, "Sanskrit verbs with s-aorist") make_forms(args, data, t["weak_stem"], weak_s_endings) elseif (not args.aor or args.aor == "a") and detect_weak(t, weak_lemma, "(.+)a/?ta$", "a(/?)ta$") then table.insert(data.categories, "Sanskrit verbs with a-aorist") make_forms(args, data, t["weak_stem"], make_weak_a_forms(t["weak_oxy"])) elseif (not args.aor or args.aor == "root") and (detect_weak(t, weak_lemma, "(.+)ta$")            or detect_weak(t, weak_lemma, "(.+[ghdDbB])Da$")) then table.insert(data.categories, "Sanskrit verbs with root-aorist") make_forms(args, data, t["weak_stem"], weak_root_endings) else error("Could not detect aorist type from " .. to_IAST(weak_lemma)) -- failed to recognize an aorist type end end end })

conj_data["bene"] = {} setmetatable(conj_data["bene"], {   __call = function (self, args, data)        local make_strong_forms = function (oxy)            return {                ["optat"] = {                    ["av"] = {                        ["1_s"] = "yA" .. oxy .. "sam",                        ["2_s"] = "yA" .. oxy .. "s",                        ["3_s"] = "yA" .. oxy .. "t",                        ["1_d"] = "yA" .. oxy .. "sva",                        ["2_d"] = "yA" .. oxy .. "stam",                        ["3_d"] = "yA" .. oxy .. "stAm",                        ["1_p"] = "yA" .. oxy .. "sma",                        ["2_p"] = "yA" .. oxy .. "sta",                        ["3_p"] = "yA" .. oxy .. "sus"                    },                }            }        end

local make_weak_forms = function (oxy) return { ["optat"] = { ["mv"] = { ["1_s"] = "sIya" .. oxy, ["2_s"] = "sIzWA" .. oxy .. "s", ["3_s"] = "sIzwa" .. oxy, ["1_d"] = "sIva" .. oxy .. "hi", ["2_d"] =, -- Whitney §924a: "of very questionable value" ["3_d"] = , ["1_p"] = "sIma" .. oxy .. "hi", ["2_p"] = "sIQva" .. oxy .. "m", ["3_p"] = "sIra" .. oxy .. "nt" },               }            }        end local t = {} if detect_strong(t, args.strong_lemma, "(.+)yA" .. sa_utils.accent .. "?t$", "yA(" .. sa_utils.accent .. "?)t$") then make_forms(args, data, t["strong_stem"], make_strong_forms(t["strong_oxy"])) elseif args.strong_lemma ~= "-" then validate(t["strong_stem"], args.strong_lemma) end local weak_lemma = args.weak_lemma or args.passive_lemma if use_strong_for_weak(t, weak_lemma) then make_forms(args, data, t["weak_stem"], make_weak_forms(t["weak_oxy"])) elseif detect_weak(t, weak_lemma, "(.+)[sz]Izwa" .. sa_utils.accent .. "?$", "[sz]Izwa(" .. sa_utils.accent .. "?)$") then make_forms(args, data, t["weak_stem"], make_weak_forms(t["weak_oxy"])) else validate(t["weak_stem"], weak_lemma) end end })

conj_data["perf"] = {} setmetatable(conj_data["perf"], {   __call = function (self, args, data)        local make_weak_forms_cons = function (oxy)   -- endings starting with consonant            return {                ["indic"] = {                    ["av"] = {                        ["1_d"] = "va" .. oxy,                        ["1_p"] = "ma" .. oxy,                    },                    ["mv"] = {                        ["2_s"] = "se" .. oxy,                        ["1_d"] = "va" .. oxy .. "he",                        ["1_p"] = "ma" .. oxy .. "he",                        ["2_p"] = "Dve" .. oxy,                    }                },                ["part"] = { --                    ["av"] = "vA" .. oxy .. "Ms",                }            }        end        local make_weak_forms_vow = function (oxy)		-- endings starting with vowel            return {                ["indic"] = {                    ["av"] = { ["2_d"] = "a" .. oxy .. "Tus", ["3_d"] = "a" .. oxy .. "tus", ["2_p"] = "a" .. oxy, ["3_p"] = "u" .. oxy .. "s" },                   ["mv"] = { ["1_s"] = "e" .. oxy, ["3_s"] = "e" .. oxy, ["2_d"] = "A" .. oxy .. "Te", ["3_d"] = "A" .. oxy .. "te", ["3_p"] = "ire" .. oxy }               },                ["part"] = { ["mv"] = "Ana" .. oxy }           }        end local make_vedic_anit_forms = function (oxy) return { ["indic"] = { ["av"] = { ["1_d"] = , ["1_p"] = , },                   ["mv"] = { ["2_s"] = , ["1_d"] = , ["1_p"] = , ["2_p"] = , ["3_p"] = , }               }            }        end local make_anit_perf_participle = function(oxy) return { ["part"] = { ["av"] = "vA" .. oxy .. "Ms" } } end local make_set_perf_participle = function(oxy) return { ["part"] = { ["av"] = "ivA" .. oxy .. "Ms" } } end local make_strong_au_forms = function(oxy) return { ["indic"] = { ["av"] = { ["1_s"] = "O" .. oxy, ["2_s"] = {"A" .. oxy .. "Ta", {"iTa" .. oxy, note = "Later Sanskrit"}}, ["3_s"] = "O" .. oxy, },				}      		}        end local anit_perf_2s_ending = { ["indic"] = { ["av"] = { ["2_s"] = "Ta" }           }        }        local set_perf_2s_ending = { ["indic"] = { ["av"] = { ["2_s"] = "iTa" }           }        }        local make_weak_perf_2s = function(oxy) return { ["indic"] = { ["av"] = { ["2_s"] = }           	}        	}        end local t = {} if detect_strong(t, args.strong_lemma, "(.+)O/?$", "O(/?)$") then make_forms(args, data, t["strong_stem"], make_strong_au_forms(t["strong_oxy"])) args.set = true make_forms(args, data, t["strong_stem"], make_weak_forms_cons(t["strong_oxy"])) make_forms(args, data, t["strong_stem"], make_set_perf_participle(t["strong_oxy"])) make_forms(args, data, t["strong_stem"], make_weak_forms_vow(t["strong_oxy"])) else if not detect_strong(t, args.strong_lemma, "(.+)a$") then if not detect_strong(t, args.strong_lemma, "(.+)e" .. sa_utils.accent .. "?$", "e(" .. sa_utils.accent .. "?)$") then validate(t["strong_stem"], args.strong_lemma) else args.n = "m" -- deponent end end local weak_lemma = args.weak_lemma or args.passive_lemma if not use_strong_for_weak(t, weak_lemma) then if not detect_weak(t, weak_lemma, "(.+)u" .. sa_utils.accent .. "?[Hs]$", "u(" .. sa_utils.accent .. "?)[Hs]$") then validate(t["weak_stem"], weak_lemma) end end -- if no strong stem supplied in case of e.g. cakāra, look at weak stem if match(args.strong_lemma, "A"..sa_utils.accent.."?"..sa_utils.consonant.."a$") and not match(t.weak_stem, "A"..sa_utils.accent.."?"..sa_utils.consonant.."$") then t.strong_stem = gasub(t.strong_stem, "A("..sa_utils.accent.."?.)$", "a%1") end -- if Brugmann's law is applicable if match(t.strong_stem, "a"..sa_utils.accent.."?"..sa_utils.consonant.."$") or match(t.strong_stem, "[eo]"..sa_utils.accent.."?$") then make_forms(args, data, t["strong_stem"], {					["indic"] = {               		["av"] = {                    		["1_s"] = {"a", {"aⓁ", note = "Later Sanskrit"}}, -- only 3 verbs with vriddhi-form in Vedic (Whitney §793d)                			["3_s"] = "aⓁ",                		},            		}            	}) else make_forms(args, data, t["strong_stem"], {					["indic"] = {						["av"] = {							["1_s"] = "a",							["3_s"] = "a",						},					}       		}) end if args.weak_lemma and ( match(args.weak_lemma, sa_utils.consonant.."i?yu/?[Hs]$") or match(args.weak_lemma, "uvu/?[Hs]$") ) then error("Please add weak stem for active participle for roots on -i/-ī and -u/-ū.") elseif match(t.weak_stem, sa_utils.consonant .. 'r$') then t.weak_stem = gasub(t.weak_stem, 'r$', 'f') -- change -r of weak stem to -ṛ if after consonant elseif match(t.weak_stem, "[uU]$") or match(t.weak_stem, sa_utils.consonant..sa_utils.consonant.."[iI]$") then args.no_syncope = true end -- anit roots (on -ṛ or -u) if match(t.weak_stem, "[uf]$") and not args.set == true then make_forms(args, data, t["strong_stem"], anit_perf_2s_ending) make_forms(args, data, t["weak_stem"], make_weak_forms_cons(t["weak_oxy"])) make_forms(args, data, t["weak_stem"], make_anit_perf_participle(t["weak_oxy"])) if match(args.weak_lemma, ".<.*>$") then t.weak_stem = gasub(args.weak_lemma, "u/?[Hs]<.*>$", "") end make_forms(args, data, t["weak_stem"], make_weak_forms_vow(t["weak_oxy"])) else args.set = false -- as this interferes with adding -tha -- rules for 2s if (match(t.strong_stem, "uva/?.$") and match(t.weak_stem, "U.$")) -- e.g. uvac- or (match(t.strong_stem, "iya/?.$") and match(t.weak_stem, "I.$")) -- iyaj- or (match(t.strong_stem, "[aA]/?[NYRnmM]?[^yrv]$") and (match(t.weak_stem, "e.$")	-- e.g. tatan- / ten- or match(t.weak_stem, sa_utils.consonant..sa_utils.consonant.."$"))) -- e.g. jajan- / jajñ- or match(t.strong_stem, "U/?v$") -- babhūv- or match(t.strong_stem, "a/?[yvr]$") or match(t.strong_stem, "[eo]/?$") then -- e.g. ninay-, dadhar- make_forms(args, data, t["strong_stem"], anit_perf_2s_ending) -- add -tha t["Ta_added"] = true end if match(t.strong_stem, "a/?[^yrlv]$") and match(t.weak_stem, "e.$") then --				or match(t.weak_stem, sa_utils.consonant..sa_utils.consonant.."$")) then -- this specific line might be wrong					make_forms(args, data, t["weak_stem"], make_weak_perf_2s(t["weak_oxy"]))				else					make_forms(args, data, t["strong_stem"], set_perf_2s_ending)  -- add -itha				end				if match(t.strong_stem, "a"..sa_utils.accent.."?"..sa_utils.consonant.."$") and not t.Ta_added then					make_forms(args, data, t["strong_stem"], { ["indic"] = { ["av"] = { ["2_s"] = }               		}            		})				end				-- use (supplied) weak stem for participle				if sa_utils.is_monosyllabic(t.weak_stem) or args.mono == true then	-- not accurate for some verbs (Whitney §803a)        			make_forms(args, data, t["weak_stem"], make_set_perf_participle(t["weak_oxy"]))        		else        			make_forms(args, data, t["weak_stem"], make_anit_perf_participle(t["weak_oxy"]))				end				-- change weak stem to form used in 3p				if args.weak_lemma then					if match(args.weak_lemma, ".<.*>$") then						t.weak_stem = gasub(args.weak_lemma, "u/?[Hs]<.*>$", "")					else 						t.weak_stem = gasub(t.weak_stem, "("..sa_utils.consonant..")f$", "%1r")						t.weak_stem = gasub(t.weak_stem, "[uU]$", "uv")						t.weak_stem = gasub(t.weak_stem, "("..sa_utils.vowel..sa_utils.consonant..")[iI]$", "%1y")						t.weak_stem = gasub(t.weak_stem, "("..sa_utils.consonant..sa_utils.consonant..")[iI]$", "%1iy") end end args.set = true make_forms(args, data, t["weak_stem"], make_weak_forms_cons(t["weak_oxy"])) make_forms(args, data, t["weak_stem"], make_weak_forms_vow(t["weak_oxy"])) -- Vedic rules from Whitney §798a (omitting y/r/l/v from the consonants 				-- as r+r is not allowed and none of them are among Wh.'s examples) if match(t.weak_stem, "[aiufx][kKgGNcCjJYwWqQRtTdDnpPbBmLSzsh]$") then args.set = false if args.weak_lemma and match(args.weak_lemma, "<.*>$") then t.weak_stem = gasub(args.weak_lemma, "^.*<(.*)>$", "%1") end make_forms(args, data, t["weak_stem"], make_vedic_anit_forms(t["weak_oxy"])) end end end end })

local function legacy_split_stems(form) return split(form, ",") end

-- Gets stems for COMPLEX_FORM given a pattern in MATCH_RE local function legacy_get_stem(complex_form, match_re) local s = split_xs(complex_form) if s[2] ~= nil then return s[2] end return match(s[1], match_re) end

-- Returns { stems, accents } local function legacy_get_stems_from_lemmas(lemma, match_pattern, oxy_match_pattern) local strong_lemmas = legacy_split_stems(lemma) local strong_stems = {} local oxys = nil if oxy_match_pattern ~= nil then oxys = {} end for i, strong_lemma in ipairs(strong_lemmas) do       local prov = split_xs(strong_lemma)[1] if oxy_match_pattern ~= nil then oxys[i] = match(prov, oxy_match_pattern) end strong_stems[i] = legacy_get_stem(strong_lemma, match_pattern) validate(strong_stems[i], strong_lemma) end return { strong_stems, oxys } end

conj_data["nonf"] = {} setmetatable(conj_data["nonf"], {   -- TODO: this whole system needs to be removed    -- it's kept just so as to not break verbal entries which use this module, but non-finite forms    -- should now be part of the root derivations and not tied to the verbal conjugation    __call = function (self, args, data)        local make_strong_forms = function (oxy)            return {                ["gerundive_mn"] = { "ya", "tavya" .. oxy, "anI" .. oxy .. "ya" },                ["gerundive_f"] = { "yA", "tavyA" .. oxy, "anI" .. oxy .. "yA" }             }        end

local make_weak_forms = function (oxy) return { ["gerund"] = "tvA" .. oxy, ["part_mn"] = "ta" .. oxy, ["part_f"] = "tA" .. oxy }       end local strong_stems = legacy_get_stems_from_lemmas(       	args.strong_lemma,        	"(.+)ya$",        	"(" .. sa_utils.accent .. "?)"       )        for i, strong_stem in ipairs(strong_stems[1]) do        	make_forms(args, data, strong_stem, {	        	["inf"] = "tum"	        }) strong_stem = gsub(strong_stem, sa_utils.accent, "") make_forms(args, data, strong_stem, make_strong_forms(strong_stems[2][i])) local ya_form = #(data.forms["gerundive_mn"]) - 2 -- TODO: This is not a great way of doing this local prov = split_xs(legacy_split_stems(args.strong_lemma)[i])[1] data.forms["gerundive_mn"][1] = prov data.forms["gerundive_f"][1] = match(prov, "(.+)a$") .. "A" end

local weak_lemma = args.weak_lemma or args.passive_lemma if weak_lemma == nil then for i, strong_stem in ipairs(strong_stems[1]) do           	make_forms(args, data, gsub(strong_stem, sa_utils.accent, ""), make_weak_forms(strong_stems[2][i])) end else local weak_stems = legacy_get_stems_from_lemmas(       		weak_lemma,        		"(.+).a" .. sa_utils.accent .. "?$",        		"a(" .. sa_utils.accent .. "?)$"       	)        	for i, weak_stem in ipairs(weak_stems[1]) do        		make_forms(args, data, weak_stem, make_weak_forms(weak_stems[2][i])) end end end })

return conj_data