Module:sa-verb/data

From Wiktionary, the free dictionary
Jump to navigation Jump to search

-- 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<rinac>" or form = "rincanti<rinc>")
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 class 3 verbs (with 3p -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.."[MH]?"..sa_utils.consonant.."*$") then
		-- dissyllabic reduplication
		return true
	elseif match(t.strong_stem, sa_utils.consonant.."[Aeo]/?"..sa_utils.consonant.."+"..sa_utils.vowel.."[MH]?"..sa_utils.consonant.."*$") 
	or match(t.strong_stem, sa_utils.consonant.."a/?[rlNYRnmMd]"..sa_utils.consonant.."+"..sa_utils.vowel.."[MH]?"..sa_utils.consonant.."?$") 
	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"] = {{ "Ana", note = "Later Sanskrit" }},
					}
        		})
            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<.*>$", "")
    		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"] = {{"sIyA" .. oxy .. "sTAm", note = "Uncertain"}}, -- Whitney §924a: "of very questionable value"
                        ["3_d"] = {{"sIyA" .. oxy .. "stAm", note = "Uncertain"}},
                        ["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"] = {{"va" .. oxy, note = "Vedic"}},
                        ["1_p"] = {{"ma" .. oxy, note = "Vedic"}},
                    },
                    ["mv"] = {
                        ["2_s"] = {{"se" .. oxy, note = "Vedic"}},
                        ["1_d"] = {{"va" .. oxy .. "he", note = "Vedic"}},
                        ["1_p"] = {{"ma" .. oxy .. "he", note = "Vedic"}},
                        ["2_p"] = {{"Dve" .. oxy, note = "Vedic"}},
                        ["3_p"] = {{"re" .. oxy, note = "Vedic"}},
                    }
                }
            }
        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"] = {{"iTa" .. oxy, note = "Later Sanskrit"}}
                	}
            	}
        	}
        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"] = {{"Ta", note = "Vedic"}}
                    		}
                		}
            		})
				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