Module:User:Dragonoid76/sa-verb

Basic Usage

edit

If you are unfamiliar with Sanskrit verbs, this, this, and this serve as great guides to get familiar with conjugations.

This template can be called in eight different ways:

  1. {{sa-verb|nonf|...}}: a table with the infinitive, gerund, gerundives, and past passive participle
  2. {{sa-verb|pres|...}}: a table with the present tense (incl. the indicative, optative, imperative, and active participles)
  3. {{sa-verb|impf|...}}: a table with the imperfect tense
  4. {{sa-verb|fut|...}}: a table with the future tense (incl. the simple, peripherastic, and active participles)
  5. {{sa-verb|cond|...}}: a table with the conditional tense
  6. {{sa-verb|aor|...}}: a table with the aorist tense
  7. {{sa-verb|bene|...}}: a table with the benedictive/precative, originally the optative of the aorist
  8. {{sa-verb|perf|...}}: a table with the perfect tense (incl. active participles)

The first argument is always the third-person singular indicative active-voice form (or optative, in the case of the benedictive) of the verb in that tense. For instance, {{sa-verb|pres|arhati}} will produce a table for the present-tense conjugation of अर्हति (arhati). {{sa-verb|impf|ārhat}} will likewise produce a table for the imperfect-tense conjugation of that verb.

If no other non-keyword arguments are passed, the verb is assumed to be thematic, and this is all that is necessary. If a second argument is passed, the verb is assumed to be athematic and the the second argument should be the third-person plural indicative active-voice form (or optative, in the case of the benedictive) of the verb. If a third argument is passed, it should be the third-person singular indicative passive-voice form (or optative, in the case of the benedictive) of the verb. For instance, {{sa-verb|pres|leḍhi<leh>|lihanti|lihyate}} will produce a table for the present-tense athematic conjugation of लेढि (leḍhi). For aorist and benedictive tables, the passive stem must be provided if it is different from the active stem, but the middle/weak stem is unused; hence {{sa-verb|aor|alikṣat||alikṣata}} produces the aorist table for लेढि (leḍhi).

The "<...>" in that example encloses the stem of the verb. In the case of "leḍhi", the stem "leh" cannot be inferred from the third-person tense due to internal sandhi. Hence, we must provide the stem in brackets like that. All non-keyword arguments can take a stem like this, and, if provided, will be used in place of the third-person form (although the third-person form should still be provided so the module can infer the class of the verb). ALSO, the bracketed stem argument must be provided if the third-person form is irregular.

The non-finite forms table is special and only takes a single non-keyword argument: the infinitive form of the verb (with a possible bracketed stem). For लेढि (leḍhi), we would write {{sa-verb|nonf|liḍhum<lih>}}.

Disabling Sandhi

edit

Usually, like in the case of {{sa-verb|pres|leḍhi<leh>|lihanti|lihyate}}, this module is smart and will apply a variety of sandhi rules to produce a correct output. Occasionally, though, this is not welcome. For instance, in {{sa-verb|pres|asti|santi|...}}, the internal sandhi rules will try to eliminate the स in the root. To avoid this, use the argument "auto_sandhi=false".

Limiting Voices

edit

A number of Sanskrit verbs are deponent (only middle voice), active-only, or have no passive. By default, this module will conjugate as many voices as each tense has. To limit the voices, use the argument "n=...". "a" stands for "active", "m" stands for "middle", and "p" stands for "passive", so "n=amp" will produce all three voices, "n=m" will produce just the middle voice, and "n=am" will produce both the active and middle voices, for example.

Overriding Arguments

edit

Occasionally, the automatic sandhi is unable to predict the right form in a particular case or the verb has some special cases. To handle this, every single cell of the table can be completely overridden by a keyword argument to the table. It should be of the form:

  • "[mood]_[voice]_[person]_[number]" for finite forms
  • "part_[voice]" for participles
  • "inf" for the infinitive, "gerundive_mn" for the masculine/neuter gerundive, "gerundive_f" for the feminine gerundive, "part_mn" for the masculine/neuter past passive participle, and "part_f" for the feminine past passive participle

where

  • "[mood]" is one of "indic", "optat", "imper"
  • "[voice]" is one of "av", "mv", "pv"
  • "[person]" is one "1", "2", "3"
  • and "[number]" is one of "s", "d", "p"

For instance, in {{sa-verb|pres|asti|santi|auto_sandhi=false|n=a}}, the second-person singular indicative present form will be *अस्सि by default, but it is actually irregular and is असि. Hence, we override the default value by providing the arg "indic_av_2_s=asi" in {{sa-verb|pres|asti|santi|auto_sandhi=false|indic_av_2_s=asi|n=a}}.

Examples

edit

khelati

edit

For खेलति (khelati) (thematic, class 1, no ablaut),
{{sa-verb|nonf|Kelitum}}
{{sa-verb|pres|Kelati}}
{{sa-verb|impf|aKelat}}
{{sa-verb|fut|Kelizyati}}
{{sa-verb|cond|aKeizyat}}
{{sa-verb|aor|aKelIt}}
{{sa-verb|bene|KelyAt}}
{{sa-verb|perf|caKela}}
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.

asti

edit

For अस्ति (asti) (athematic, class 2),
{{sa-verb|pres|asti|santi|auto_sandhi=false|indic_av_2_s=asi|n=a}}
{{sa-verb|impf|āsīt<ās>|āsan|auto_sandhi=false|indic_av_2_s=āsīḥ|indic_av_3_s=āsīt|n=a}} ("<ās>" is provided as the form "āsīt" is irregular). Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.

leḍhi

edit

For लेढि (leḍhi) (athematic, class 2, irregular), {{sa-verb|nonf|līḍhum<lih>}} {{sa-verb|pres|leḍhi<leh>|lihanti|lihyate}} {{sa-verb|impf|aleṭ<aleh>|alihan|alihyata}} {{sa-verb|fut|lekṣyati}} {{sa-verb|cond|alekṣyat}} {{sa-verb|aor|alikṣat||alikṣata}} {{sa-verb|bene|lihyāt||likṣīṣṭa}} {{sa-verb|perf|lileha|lilihuḥ}} Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.

riṇakti

edit

For रिणक्ति (riṇakti) (athematic, class 7), {{sa-verb|nonf|riṇaktum<riṇac>|rikta<ric>}} {{sa-verb|pres|riṇakti<riṇac>|riñcanti|ricyate}} {{sa-verb|impf|ariṇak<ariṇac>|ariñcan|aricyata}} {{sa-verb|fut|rekṣyati}} {{sa-verb|cond|arekṣyat}} {{sa-verb|aor|aricat,araikṣīt||arikta<aric>}} {{sa-verb|bene|recyāt||rikṣīṣṭa}} {{sa-verb|perf|rireca|riricuḥ}} Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used. Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.

TODO

edit
  • support accent marks (i.e. the shifting of accent onto the passive stem in Class 4 aorists)
  • third and first person occasional irregular forms for perfect verbs have to be provided separately
  • third-person plural ending in -uh if the root ends in -ā
  • siṣ aorist

local export = {}

local m_para = require("Module:parameters")
local m_links = require("Module:links")
local m_utils = require("Module:utilities")
local lang = require("Module:languages").getByCode("sa")
local m_script_utils = require("Module:script utilities")
local sa_verb_data = require("Module:User:Dragonoid76/sa-verb/data")
local SLP_to_IAST = require("Module:sa-utilities/translit/SLP1-to-IAST")
local sa_utils_translit = require("Module:sa-utilities/translit")
local PAGENAME = mw.title.getCurrentTitle().text

local gsub = mw.ustring.gsub
local match = mw.ustring.match
local split = mw.text.split

local sa_utils = require("Module:sa-utilities")

local names = {
	["pres"] = "Present",
	["impf"] = "Imperfect",
	["fut"] = "Future",
	["cond"] = "Conditional",
	["aor"] = "Aorist",
	["bene"] = "Benedictive/Precative",
	["perf"] = "Perfect",
	["indic"] = "Indicative",
	["imper"] = "Imperative",
	["optat"] = "Optative/Potential",
	["part"] = "Participles",
	["simple"] = "Simple Indicative",
	["periph"] = "Periphrastic Indicative",
	["inf"] = "Infinitive",
	["gerund"] = "Gerund",
	["gerundive_mn"] = "Masculine/Neuter Gerundive",
	["gerundive_f"] = "Feminine Gerundive",
	["part_mn"] = "Masculine/Neuter Past Passive Participle",
	["part_f"] = "Feminine Past Passive Participle",
	["part_av_mn"] = "Masculine/Neuter Past Active Participle",
	["part_av_f"] = "Feminine Past Active Participle",
	["nonf"] = "Nonfinite Forms"
}

local tenses = {
	["pres"] = {
		["moods"] = { "indic", "imper", "optat", "part" },
		["voices"] = { "av", "mv" }
	},
	["impf"] = {
		["moods"] = { "indic" },
		["voices"] = { "av", "mv" }
	},
	["fut"] = {
		["moods"] = { "simple", "periph", "part" },
		["voices"] = { "av", "mv" }
	},
	["cond"] = {
		["moods"] = { "indic" },
		["voices"] = { "av", "mv" }
	},
	["aor"] = {
		["moods"] = { "indic" },
		["voices"] = { "av", "mv" }
	},
	["bene"] = {
		["moods"] = { "optat" },
		["voices"] = { "av", "mv" }
	},
	["perf"] = {
		["moods"] = { "indic", "part" },
		["voices"] = { "av", "mv" }
	},
	["nonf"] = {
		["moods"] = { "inf", "gerund", "gerundive_mn", "gerundive_f", "part_mn", "part_f", "part_av_mn", "part_av_f" }
	}
}

local numbers = {"1_s", "2_s", "3_s", "1_d", "2_d", "3_d", "1_p", "2_p", "3_p"}

local super_nums = {
    [1] = "¹",
    [2] = "²",
    [3] = "³",
    [4] = "⁴",
    [5] = "⁵",
    [6] = "⁶",
    [7] = "⁷",
    [8] = "⁸",
    [9] = "⁹",
    [0] = "⁰"
}

local function to_super(num)
    local annotation = gsub(num, ".", super_nums)
    return annotation
end

local function get_form_note_tags(form_notes, data)
    local output = {}
    if type(form_notes) ~= "table" then
        form_notes = {form_notes}
    end
    for _, form_note in ipairs(form_notes) do
        if type(data.form_notes[form_note]) ~= "number" then
            table.insert(data.form_notes_out, form_note)
            data.form_notes[form_note] = #data.form_notes_out
        end
        table.insert(output, to_super(data.form_notes[form_note]))
    end
    return table.concat(output)
end

local function make_header(args, data, title_models, sc_cache)
    local width = 70
    local title = names[args.tense] .. ": " .. title_models

    local header = {
        '{| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="background:#F9F9F9; text-align:center; border: 1px solid #CCC; width: ' ..
            width .. 'em"\n'
    }
    table.insert(header, '|- style="background: #d9ebff;"\n')
    table.insert(
        header,
        '! class="vsToggleElement" style="text-align: left;" colspan="' .. args.colspan .. '" | ' .. title .. "\n"
    )
    table.insert(header, '|- class="vsHide"\n')
    table.insert(header, '! style="background:#eff7ff" rowspan="2" |\n')

    table.insert(header, '! colspan="3" style="background:#eff7ff" | Active\n')
    table.insert(header, '! colspan="3" style="background:#eff7ff" | Mediopassive\n')

    table.insert(header, '|- class="vsHide"\n')
    local size = 2
    for i = 1, size, 1 do
        table.insert(header, '! style="background:#eff7ff" | Singular\n')
        table.insert(header, '! style="background:#eff7ff" | Dual\n')
        table.insert(header, '! style="background:#eff7ff" | Plural\n')
    end

    return table.concat(header)
end

local function make_cell(args, data, tag, arg_tag, sc_cache, col_span, voice)
    local forms, links, trs = {}, {}, {}
    if (not match(args.n, "a") and voice == "av") or (not match(args.n, "m") and voice == "mv") or (not match(args.n, "p") and voice == "pv") then
    	forms = {"-"}
    elseif args[arg_tag] then
        forms = mw.text.split(args[arg_tag], "%s*[,]%s*")
    else
        forms = data.forms[tag]
    end

    if not forms then
        return "| -\n"
    end
    for i, form in ipairs(forms) do
    	form = sc_cache.tr(form)
    	form = gsub(form, 'V', 'f')
		form = gsub(form, "Z", "x")
        local form_note_tag = get_form_note_tags(forms["note" .. i] or {}, data)
        table.insert(
            links,
            m_links.full_link({term = sc_cache.reverse_tr(form), tr = "-", lang = lang, sc = sc_cache.sc}) ..
                form_note_tag
        )
        table.insert(trs, SLP_to_IAST.tr(form) .. form_note_tag)
    end

    return table.concat {
        "| ",
        "colspan = ",
        col_span,
        " | ",
        table.concat(links, " / "),
        "<br/>",
        m_script_utils.tag_translit(table.concat(trs, " / "), lang, "default", 'style="color: #888;"'),
        "\n"
    }
end

local function format_notes(args, data)
    local output = {
        '|- class="vsHide"',
        '| style="background-color:#eff7ff; font-style:italic;border-top:double #888;" | Notes',
        '| style="text-align:left;border-top:double #888;" colspan="' .. args.colspan .. '" |'
    }
    if #data.form_notes_out > 0 or #data.general_notes > 0 or #args.note > 0 then
        for i, form_note in ipairs(data.form_notes_out) do
            table.insert(output, "* " .. to_super(i) .. form_note)
        end
        for _, general_note in ipairs(data.general_notes) do
            table.insert(output, "* " .. general_note)
        end
        for _, note in ipairs(args.note) do
            table.insert(output, "* " .. note)
        end
        return table.concat(output, "\n") .. "\n"
    else
        return ""
    end
end

local function make_nonf_table(args, data, output, sc_cache)
    local moods = tenses[args.tense].moods
    if data.forms["part_mn"] ~= "-" and data.forms["part_mn"] ~= nil then
	    data.forms["part_av_mn"] = { data.forms["part_mn"][1] .. "vat" } -- these two formed directly from the given forms always
	    data.forms["part_av_f"] = { data.forms["part_mn"][1] .. "vatī" }
	else
		data.forms["part_av_mn"] = { "-" }
		data.forms["part_av_f"] = { "-" }
	end
    local title_models = ""
        local arg_before = false
        local tag = moods[1]
        local arg_tag = moods[1]
        local forms
        if args[arg_tag] then
            forms = mw.text.split(args[arg_tag], "%s*[,]%s*")
        else
            forms = data.forms[tag]
        end
        for i, title_lem in ipairs(forms) do
        	title_lem = sc_cache.tr(title_lem)
        	title_lem = gsub(title_lem, 'V', 'f')
			title_lem = gsub(title_lem, "Z", "x")
            if i > 1 then
                title_models = title_models .. " or "
            end
            title_models =
                title_models ..
                m_links.full_link(
                    {
                        term = nil,
                        alt = sc_cache.reverse_tr(title_lem),
                        tr = SLP_to_IAST.tr(title_lem),
                        lang = lang,
                        sc = sc_cache.sc
                    }
                )
        end
        local title = names[args.tense] .. ": " .. title_models
        table.insert(output, 'Forms of Sanskrit verbs are numerous and complicated. The following conjugation shows only a subset of all forms and should be treated as a guide. \n')
        table.insert(
            output,
            '{| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="background:#F9F9F9; text-align:center; border: 1px solid #CCC; width: 40em"\n'
        )
        table.insert(output, '|- style="background: #d9ebff;"\n')
        table.insert(output, '! class="vsToggleElement" style="text-align: left;" colspan="4" | ' .. title .. "\n")
        table.insert(output, '|- class="vsHide"\n')
        table.insert(output, '! style="background:#eff7ff" |\n')

        table.insert(output, '! colspan="2" style="background:#eff7ff" | Undeclinable\n')
        table.insert(output, '|- class="vsHide"\n')
        for _, mood in ipairs(moods) do
            if mood == "gerundive_mn" then
                table.insert(output, '! style="background:#eff7ff" |\n')
                table.insert(output, '! colspan="2" style="background:#eff7ff" | Participles\n')
                table.insert(output, '|- class="vsHide"\n')
            end
            table.insert(output, '! style="background-color:#eff7ff;" | ' .. names[mood] .. "\n")
            local tag = mood
            local arg_tag = mood
            table.insert(output, make_cell(args, data, tag, arg_tag, sc_cache, 1))
            table.insert(output, '|- class="vsHide"\n')
        end
        table.insert(output, format_notes(args, data))
        table.insert(output, "|}")
        if not args.nocat and #data.categories > 0 then
            table.insert(output, m_utils.format_categories(data.categories, lang))
        end
        return output
end

local function make_voice(title_models, args, data, sc_cache, voice)
    local moods = tenses[args.tense].moods
    local tag = moods[1] .. "_" .. voice .. "_3_s"
    local arg_tag = moods[1] .. "_" .. voice .. "_3_s"
    local forms
    if args[arg_tag] then
        forms = mw.text.split(args[arg_tag], "%s*[,]%s*")
    else
        forms = data.forms[tag]
    end
    if #title_models > 0 then
        table.insert(title_models, ", ")
    end
    for i, title_lem in ipairs(forms or {"-"}) do
    	title_lem = sc_cache.tr(title_lem)
        if i > 1 then
            table.insert(title_models, " or ")
        end
        title_lem = gsub(title_lem, 'V', 'f')
		title_lem = gsub(title_lem, "Z", "x")
        table.insert(title_models, 
            m_links.full_link(
                {
                    term = nil,
                    alt = sc_cache.reverse_tr(title_lem),
                    tr = SLP_to_IAST.tr(title_lem),
                    lang = lang,
                    sc = sc_cache.sc
                }
            )
        )
    end
end

local function make_table_verb(args, data, output, sc_cache)
    local moods = tenses[args.tense].moods

    if args.tense == "nonf" then
    	table.insert(data.categories, "Sanskrit verbs with nonfinite forms")
        return make_nonf_table(args, data, output, sc_cache)
    end

    -- local voices = tenses[args.tense].voices
    local voices = tenses[args.tense].voices
    local numbers = {"s", "d", "p"}
    local people = {{"3", "Third"}, {"2", "Second"}, {"1", "First"}}

    local title_models = {}
    if match(args.n, "a") then
        make_voice(title_models, args, data, sc_cache, "av")
    end
    if match(args.n, "m") then
        make_voice(title_models, args, data, sc_cache, "mv")
    end
    if match(args.n, "p") then
        make_voice(title_models, args, data, sc_cache, "pv")
    end

    table.insert(output, make_header(args, data, table.concat(title_models, ""), sc_cache))
    table.insert(output, '|- class="vsHide"\n')

    for _, mood in ipairs(moods) do
        table.insert(output, '! style="background:#eff7ff" colspan="' .. args.colspan .. '" | ' .. names[mood] .. "\n")
        table.insert(output, '|- class="vsHide"\n')
        if mood == "part" then
            table.insert(output, '| style="background-color:#eff7ff; font-style:italic;" | \n')
            for _, voice in ipairs(voices) do
                local tag = mood .. "_" .. voice
                local arg_tag = mood .. "_" .. voice
                table.insert(output, make_cell(args, data, tag, arg_tag, sc_cache, 3, voice))
            end
        else
            for i, person_pair in ipairs(people) do
                local person, person_name = person_pair[1], person_pair[2]
                table.insert(output, '| style="background-color:#eff7ff; font-style:italic;" | ' .. person_name .. "\n")
                for _, voice in ipairs(voices) do
                    for _, number in ipairs(numbers) do
                        local tag = mood .. "_" .. voice .. "_" .. person .. "_" .. number
                        local arg_tag = mood .. "_" .. voice .. "_" .. person .. "_" .. number
                        table.insert(output, make_cell(args, data, tag, arg_tag, sc_cache, 1, voice))
                    end
                end
                table.insert(output, '|- class="vsHide"\n')
            end
        end
    end

    table.insert(output, format_notes(args, data))
    table.insert(output, "|}")
    if not args.nocat and #data.categories > 0 then
        table.insert(output, m_utils.format_categories(data.categories, lang))
    end
    return output
end

local function get_sc_details(args)
    local sc, scCode
    if args.sc then
        sc = require("Module:scripts").getByCode(args.sc)
        scCode = args.sc
    else
        sc = lang:findBestScript(args.lemma)
        scCode = sc:getCode()
        if scCode == "None" then
            sc = lang:findBestScript(PAGENAME)
            scCode = sc:getCode()
            if scCode == "None" then
                -- error("Script code was not specified or detected.")
                -- Suppress; this fixes issues where docs pages get errors
                return get_sc_details({sc = "Deva"})
            end
        end
    end

    local tr, reverse_tr = sa_utils_translit.retrieve_tr_modules(scCode)
    return {tr = tr, reverse_tr = reverse_tr, sc = sc, scCode = scCode}
end

--[=[Splits a string by commas and displays
]=]
function export.split(frame)
	local args = frame.args
	args.lemma = args[1]
	local sc_cache = get_sc_details(args)
    if not sc_cache then
    	return "Module failed on page "
    end
    
	local output = {}
	local splitted = mw.text.split(frame.args[1], ",")
	for i, form in ipairs(splitted) do
		if i > 1 then table.insert(output, "<br/>") end
		table.insert(
            output,
            m_links.full_link({term = form, lang = lang, sc = sc_cache.sc})
        )
	end
	return table.concat(output)
end

function export.show(frame)
    local params = {
        lemma = {default = PAGENAME},
        n = {default = "amp"},
        sc = {},
        [1] = {required = true},
        [2] = {alias_of = "lemma"},
        [3] = {},
        [4] = {},
        auto_sandhi = {default = true, type = "boolean"},
        set = {default = false, type = "boolean" }, -- set vs anit roots
        note = {list = true, type = "boolean"},
        o = {default = false, type = "boolean"},
        mono = {default = false, type = "boolean"}
    }
    
    for tense, tense_l in pairs(tenses) do
    	if tense == "nonf" then
    		for _, mood in pairs(tense_l["moods"]) do
    			params[mood] = {}
    		end
    	else
    		for _, mood in pairs(tense_l["moods"]) do
    			for _, voice in pairs(tense_l["voices"]) do
    				if mood == "part" then
    					params[mood .. "_" .. voice] = {}
    				else
    					for _, number in pairs(numbers) do
    						params[mood .. "_" .. voice .. "_" .. number] = {}
    					end
    				end
    			end
    		end
    	end
    end
   
    local data = {
        forms = {},
        categories = {},
        decl_type = nil,
        form_notes = {},
        form_notes_out = {},
        general_notes = {}
    }
    local args = m_para.process(frame:getParent().args, params)

    local sc_cache = get_sc_details(args)
    if not sc_cache then
    	return "Module failed on page "
    end
    args.lemma = sc_cache.tr(args.lemma)
    if args[3] ~= nil then args[3] = sc_cache.tr(args[3]) end
    if args[4] ~= nil then args[4] = sc_cache.tr(args[4]) end

    local output = {}
    args.tense = args[1]
    -- conjugate(args, data)
    args.colspan = 7
    args.n = gsub(args.n, "p", "")
    
    args.strong_lemma = args.lemma -- split(args.lemma, ",")
    args.weak_lemma = args[3] -- and split(args[3], ",")
    args.passive_lemma = args[4] -- and split(args[4], ",")
    if not args.o then
    	sa_verb_data[args.tense](args, data)
    end
    
	make_table_verb(args, data, output, sc_cache)
    return table.concat(output)
end

return export