Module:User:RichardW57/pi-conj/verb

local export = {}

local links = require("Module:links") local lang = require("Module:languages").getByCode("pi") local m_parameters = require("Module:parameters") local m_noun = require("Module:pi-decl/noun") local to_script = require("Module:pi-Latn-translit").tr local debug_outer = ''

local gsub = mw.ustring.gsub local match = mw.ustring.match local sub = mw.ustring.sub local asub = string.sub -- quicker for ASCII, but works on bytes. local u = mw.ustring.char -- uses this for readability.

local function dc(x) -- Use this to make marks legible. The name'dc' means 'drop carrier'. return gsub(x, "[𑀓कকකကกᨠក]", "") end

local endings = { -- pa endings ["ati"] = "ati",		["ติ"] = "ati",			["ति"] = "ati",			["তি"] = "ati", ["တိ"] = "ati",									["ᨲᩥ"] = "ati", ["តិ"] = "ati",			["ති"] = "ati",			["𑀢𑀺"] = "ati",

["ayati"] = "ayati",	["ยติ"] = "ayati",		["यति"] = "ayati",			["যতি"] = "ayati", ["ယတိ"] = "ayati",								["ᨿᨲᩥ"] = "ayati", ["យតិ"] = "ayati",		["යති"] = "ayati",		["𑀬𑀢𑀺"] = "ayati",

["āti"] = "āti",		["าติ"] = "āti",		[dc("काति")] = "āti",	[dc("কাতি")] = "āti", ["ာတိ"] = "āti",		["ါတိ"] = "āti",		["ᩣᨲᩥ"] = "āti",		["ᩤᨲᩥ"] = "āti", [dc("កាតិ")] = "āti",	[dc("කාති")] = "āti",	[dc("𑀓𑀸𑀢𑀺")] = "āti",

["eti"] = "eti",								[dc("केति")] = "eti",	[dc("কেতি")] = "eti", ["ေတိ"] = "eti",								[dc("ᨠᩮᨲᩥ")] = "eti", [dc("កេតិ")] = "eti",	[dc("කෙති")] = "eti",	[dc("𑀓𑁂𑀢𑀺")] = "eti",

["oti"] = "oti",								[dc("कोति")] = "oti",	[dc("কোতি")] = "oti", ["ောတိ"] = "oti",		["ေါတိ"] = "oti",		["ᩮᩣᨲᩥ"] = "oti",		["ᩮᩤᨲᩥ"] = "oti", [dc("កោតិ")] = "oti",	[dc("කොති")] = "oti",	[dc("𑀓𑁄𑀢𑀺")] = "oti", -- pm endings ["ate"] = "ate",		["เต"] = "ate",			["ते"] = "ate",			["তে"] = "ate", ["တေ"] = "ate",									["ᨲᩮ"] = "ate", ["តេ"] = "ate",			["තෙ"] = "ate",			["𑀢𑁂"] = "ate",

["ayate"] = "ayate",	["ยเต"] = "ayate",		["यते"] = "ayate",			["যতে"] = "ayate", ["ယတေ"] = "ayate",								["ᨿᨲᩮ"] = "ayate", ["យតេ"] = "ayate",		["යතෙ"] = "ayate",		["𑀬𑀢𑁂"] = "ayate",

["āte"] = "āte",		["าเต"] = "āte",		[dc("काते")] = "āte",	[dc("কাতে")] = "āte", ["ာတေ"] = "āte",		["ါတေ"] = "āte",		["ᩣᨲᩮ"] = "āte",		["ᩤᨲᩮ"] = "āte", [dc("កាតេ")] = "āte",	[dc("කාතෙ")] = "āte",	[dc("𑀓𑀸𑀢𑁂")] = "āte",

["ete"] = "ete",								[dc("केते")] = "ete",	[dc("কেতে")] = "ete", ["ေတေ"] = "ete",								[dc("ᨠᩮᨲᩮ")] = "ete", [dc("កេតេ")] = "ete",	[dc("කෙතෙ")] = "ete",	[dc("𑀓𑁂𑀢𑁂")] = "ete",

["ute"] = "ute",		[dc("กุเต")] = "ute",		[dc("कुते")] = "ute",	[dc("কুতে")] = "ute", [dc("ကုတေ")] = "ute",							[dc("ᨠᩩᨲᩮ")] = "ute", [dc("កុតេ")] = "ute",	[dc("කුතෙ")] = "ute",	[dc("𑀓𑀼𑀢𑁂")] = "ute", -- optative endings ["eyya"] = "eyya",		["ยฺย"] = "eyya",			[dc("केय्य")] = "eyya",	[dc("কেয্য")] = "eyya", ["ေယျ"] = "eyya",								[dc("ᨠᩮᨿ᩠ᨿ")] = "eyya", [dc("កេយ្យ")] = "eyya",	[dc("කෙය්‍ය")] = "eyya",	[dc("𑀓𑁂𑀬𑁆𑀬")] = "eyya",

["ā"] = "ā",			["า"] = "ā",			[dc("का")] = "ā",	[dc("কা")] = "ā", ["ာ"] = "ā",			["ါ"] = "ā",			["ᩣ"] = "ā",		["ᩤ"] = "ā", [dc("កា")] = "ā",		[dc("කා")] = "ā",		[dc("𑀓𑀸")] = "ā",

["etha"] = "etha",		["ถ"] = "etha",			[dc("केथ")] = "etha",	[dc("কেথ")] = "etha", ["ေထ"] = "etha",								[dc("ᨠᩮᨳ")] = "etha", [dc("កេថ")] = "etha",	[dc("කෙථ")] = "etha",	[dc("𑀓𑁂𑀣")] = "etha", -- imperfect endings ["attha"] = "attha",	["ตฺถ"] = "attha",		["त्थ"] = "attha",	["ত্থ"] = "attha", ["တ္ထ"] = "attha",		["ᨲ᩠ᨳ"] = "attha", ["ត្ថ"] = "attha",		["ත්‍ථ"] = "attha",		["𑀢𑁆𑀣"] = "attha", }

function export.detectEnding(cite3s) local len local ending for len = 5, 1, -1 do		wordEnd = sub(cite3s, -len) ending = endings[wordEnd] if not ending then -- Try again elseif wordEnd == "ติ" then if match(cite3s, 'เ.ติ$') then return "eti" elseif match(cite3s, 'โ.ติ$') then return "oti" elseif match(cite3s, dc('เ.กฺ.ติ$')) then return "eti" elseif match(cite3s, dc('โ.กฺ.ติ$')) then return "oti" else return ending end elseif wordEnd == "เต" then if match(cite3s, 'เ.เต$') then return "ete" elseif match(cite3s, dc('เ.กฺ.เต$')) then return "ete" else return ending end elseif ending == 'ayati' and len == 3 then if match(sub(cite3s,-4,-4),				"^[ก-ฮअक-हঅক-হက-ဢᨠ-ᩌᩔ-ᩖᩚ-ᩞក-អඅක-ෆ𑀅𑀓-𑀷]") then return ending else return "ati" end elseif ending == 'ayate' and len == 3 then if match(sub(cite3s,-4,-4),				"^[ก-ฮअक-हঅক-হက-ဢᨠ-ᩌᩔ-ᩖᩚ-ᩞក-អඅක-ෆ𑀅𑀓-𑀷]") then return ending else return "ate" end else -- debug_outer = debug_outer..'\n'..cite3s..'='..ending..'\n' return ending end end -- debug_outer = debug_outer..'\n'..cite3s..'='.."ati"..'\n' return "ati" end

local active_optative = { {"⌫⌫⌫eyyāmi", "⌫⌫⌫eyyaṃ", "⌫⌫⌫e"}, {"⌫⌫⌫eyyāma"}, {"⌫⌫⌫eyyāsi", "⌫⌫⌫e"},            {"⌫⌫⌫eyyātha"}, {"⌫⌫⌫eyya",  "⌫⌫⌫e"},             {"⌫⌫⌫eyyuṃ"} } local active_optative_ati = mw.clone(active_optative) local active_optative_aati = mw.clone(active_optative) active_optative_aati[1] = {"⌫⌫⌫eyyāmi", "⌫⌫⌫eyyaṃ"} active_optative_aati[3] = {"⌫⌫⌫eyyāsi"} local active_optative_eti = mw.clone(active_optative_aati) active_optative_eti[5] = {"⌫⌫⌫eyya"} local active_optative_oti = mw.clone(active_optative_eti) local middle_optative = { {"⌫⌫⌫eyyaṃ"}, {"⌫⌫⌫eyyāmhe"}, {"⌫⌫⌫etho"}, {"⌫⌫⌫eyyavho"}, {"⌫⌫⌫etha"}, {"⌫⌫⌫eraṃ"} } local middle_optative_ati = mw.clone(middle_optative) local middle_optative_aati = mw.clone(middle_optative) local middle_optative_eti = mw.clone(middle_optative) local middle_optative_oti = mw.clone(middle_optative)

local pattern = { ["ati"] = { {"⌫⌫⌫āmi"}, {"⌫⌫⌫āma"},  {"⌫⌫si"}, {"⌫ha"},    {""}, {"⌫⌫nti"}, mid = "ate", imperfect = { {"⌫⌫", "⌫⌫ṃ"},	{"⌫⌫mhā"}, {"⌫⌫⌫o"},		{"⌫tha"}, {"⌫⌫", "⌫⌫⌫ā"},	{"⌫⌫⌫u", "⌫⌫⌫ū"}, },		imperative = { {"⌫⌫⌫āmi"}, {"⌫⌫⌫āma"}, {"⌫⌫", "⌫⌫⌫āhi"}, {"⌫ha"}, {"⌫u"}, {"⌫⌫ntu"} },		optative_active = active_optative_ati, optative_middle = middle_optative_ati, participle = , },	["āti"] = { {"⌫⌫mi"}, {"⌫⌫ma"},  {"⌫⌫si"}, {"⌫ha"},    {""}, {"⌫⌫⌫anti"}, mid = "āte", imperfect = { {"⌫⌫⌫a", "⌫⌫⌫aṃ"},	{"⌫⌫⌫amhā"}, {"⌫⌫⌫o"},			{"⌫⌫⌫attha"}, {"⌫⌫⌫a", "⌫⌫"},		{"⌫⌫⌫u", "⌫⌫⌫ū"}, },		imperative = { {"⌫⌫mi"}, {"⌫⌫ma"}, {"⌫⌫", "⌫⌫hi"}, {"⌫ha"},  {"⌫u"}, {"⌫⌫⌫antu"}, },		optative_active = active_optative_ati, optative_middle = middle_optative_aati, participle = , },	["eti"] = { {"⌫⌫mi"}, {"⌫⌫ma"},  {"⌫⌫si"}, {"⌫ha"},    {""}, {"⌫⌫nti"}, mid = nil, -- "ete", imperative = { {"⌫⌫mi"}, {"⌫⌫ma"},  {"⌫⌫hi"}, {"⌫ha"},    {"⌫u"}, {"⌫⌫ntu"}, },		optative_active = active_optative_eti, optative_middle = middle_optative_eti, participle = , },	["oti"] = { {"⌫⌫mi"}, {"⌫⌫ma"},  {"⌫⌫si"}, {"⌫ha"},    {""}, {"⌫⌫nti"}, mid = "oti_ute", imperative = { {"⌫⌫mi"}, {"⌫⌫ma"},  {"⌫⌫hi"}, {"⌫ha"},    {"⌫u"}, {"⌫⌫ntu"}, },		optative_active = active_optative_oti, optative_middle = middle_optative_oti, participle = , },	["ate"] = { -- Also services "ati" {"⌫⌫⌫e"}, {"⌫⌫⌫āmhe"}, {"⌫⌫se"}, {"⌫⌫vhe"},  {"⌫e"}, {"⌫⌫nte", "⌫⌫re"}, imperfect = { {"⌫⌫⌫iṃ"},	{"⌫⌫⌫āmhase", "⌫⌫mhase"}, {"⌫⌫se"},	{"⌫⌫vhaṃ"}, {"⌫tha"},	{"⌫thuṃ"}, },		imperative = { {"⌫⌫⌫e"}, {"⌫⌫⌫āmase"}, {"⌫⌫ssu"}, {"⌫⌫vho"},  {"⌫aṃ"}, {"⌫⌫ntaṃ"}, },		optative_active = active_optative_ati, optative_middle = middle_optative_ati, participle = , },	["āte"] = { -- Also services "āti" {"⌫⌫⌫e"},	{"⌫⌫mhe"}, {"⌫⌫se"},	{"⌫⌫⌫avhe"}, {"⌫e"},		{"⌫⌫⌫ante", "⌫⌫re"}, optative_active = active_optative_aati, optative_middle = middle_optative_aati, participle = , },	["ete"] = { -- Also services "eti" {"⌫⌫⌫aye"},		{"⌫⌫⌫ayāmhe"}, {"⌫⌫⌫ayase"},	{"⌫⌫⌫ayavhe"}, {"⌫⌫⌫ayate"},	{"⌫⌫⌫ayante", "⌫⌫⌫ayare"}, imperative = { {"⌫⌫⌫aye"},		{"⌫⌫⌫ayāmase"}, {"⌫⌫⌫ayassu"},	{"⌫⌫⌫ayavho"}, {}, -- {"⌫⌫⌫ayataṃ", "⌫aṃ"}, -- 3s needs review {"⌫⌫⌫ayantaṃ"} },		optative_active = active_optative_eti, optative_middle = middle_optative_eti, participle = , },	["ute"] = { -- Actual ending is "oti" when copied to "oti_ute". {"⌫⌫⌫ve"},	{"⌫⌫⌫umhe"}, {"⌫⌫⌫use"},	{"⌫⌫⌫uvhe"}, {"⌫⌫⌫ute"},	{"⌫⌫⌫unte", "⌫⌫⌫ure"}, imperative = { {"⌫⌫⌫ve"},		{"⌫⌫⌫vāmase"}, {"⌫⌫⌫ussu"},	{"⌫⌫⌫uvho"}, {"⌫⌫⌫utaṃ"},	{"⌫⌫⌫untaṃ"} -- 1s, 1pl and 3pl will often need manual repair. },	},	["eyya"] = { optative_active = { -- '-e' is not included! {"⌫āmi", "⌫aṃ"}, {"⌫āma"}, {"⌫āsi"},       {"⌫ātha"}, {""},          {"⌫uṃ"} },		optative_middle = { {"ṃ"},      {"⌫āmhe"}, {"⌫⌫⌫tho"}, {"vho"}, {"⌫⌫⌫tha"}, {"⌫⌫⌫raṃ"} },	},	["ā"] = { optative_active = { {"mi"}, {"ma"}, {"si"}, {"tha"},  {""}, {"⌫uṃ"} }	},	["etha"] = { optative_middle = { {"⌫⌫⌫yyaṃ"}, {"⌫⌫⌫yyāmhe"}, {"⌫o"},     {"⌫⌫⌫yyavho"}, {""},       {"⌫⌫⌫raṃ"} },	},	["attha"] = { imperfect = { {"⌫⌫⌫⌫⌫iṃ"}, {"⌫⌫⌫⌫mhase"}, {"⌫⌫⌫⌫se"}, {"⌫⌫⌫⌫vhaṃ"}, {""}, {"⌫uṃ"} }	}, }

-- -oti is too different from -ute in some scripts. pattern.oti_ute = mw.clone(pattern.ute)

-- convert Latin script inflections to another script --ⒹⓉ local convert_suffixes = function(stem, nstrip, suffixes, sc) local form, pre, stem_pre local xlitend = {} local strip = string.rep("⌫", nstrip) local altstem, as1 if sc == 'Thai' then altstem = to_script(stem, sc) stem_pre = match(altstem, "^[เโ]") as1 = sub(altstem, 1, 1) end for k = 1, #suffixes do		xlitend[k] = {} form = export.joinSuffix('Latn', stem, suffixes[k]) local ib = 1 -- Conversion is not one-to-one! for ia, va in pairs(form) do			local ibin = ib			altform = to_script(va, sc) -- Special handling is needed for a preposed vowel. pre = match(altform, "^[เโ]") if pre then if stem_pre then if sub(altform, 1, 1) == as1 then xlitend[k][ib] = sub(strip, 2) .. sub(altform, 3) ib = ib + 1 else --						mw.addWarning("Cannot abstract derivation "..altstem.." > "..altform) xlitend[k].voi = true xlitend[k][ib] = sub(strip, 2) .. 'Ⓣ' .. sub(altform, 3) ib = ib + 1 end -- Don't generate gibberish else xlitend[k][ib] = strip .. "↶" .. pre .. sub(altform, 3) ib = ib + 1 end else if stem_pre then xlitend[k].voi = true xlitend[k][ib] = sub(strip, 2) .. 'Ⓓ' .. sub(altform, 2) ib = ib + 1 else xlitend[k][ib] = strip .. sub(altform, 2) ib = ib + 1 end end if sc == 'Thai' and ib > ibin then -- New Thai ending local altend = gsub(xlitend[k][ibin], dc("([มว]กฺ)([เโ])(ห)"), "%2%1%3") if altend ~= xlitend[k][ibin] then xlitend[k][ib] = xlitend[k][ibin] xlitend[k][ibin] = altend ib = ib + 1 end end end end return xlitend end

function export.getSuffixes(sc, ending, tense) local pat if not pattern[ending] then error('No verb pattern for ending "'..ending..'".') end if tense then pat = pattern[ending][tense] else pat = pattern[ending] end if 'Latn' == sc then return pat elseif not pat then return nil elseif pat[sc] then return pat[sc] else local olen = {Mymr = 2, Lana = 2} -- Assume NFC local attha_len = {Latn = 5, Sinh = 4} eyya_len = {Sinh = 5} local way = { ["ati"] = {pseudostem = "kati", ndel = 2}, ["ayati"] = {pseudostem = "kayati", ndel = 3}, ["āti"] = {pseudostem = "kāti", ndel = 3}, ["eti"] = {pseudostem = "keti", ndel = 3}, ["oti"] = {pseudostem = "koti", ndel = 2 + (olen[sc] or 1)}, ["oti_ute"] = {pseudostem = "koti", ndel = 2 + (olen[sc] or 1)}, ["ate"] = {pseudostem = "kate", ndel = 2}, ["ayate"] = {pseudostem = "kayate", ndel = 3}, ["āte"] = {pseudostem = "kāte", ndel = 3}, ["ete"] = {pseudostem = "kete", ndel = 3}, ["ute"] = {pseudostem = "kute", ndel = 3}, ["eyya"] = {pseudostem = "keyya", ndel = eyya_len[sc] or 4}, ["ā"]   = {pseudostem = "kā", ndel = 1}, ["etha"] = {pseudostem = "ketha", ndel = 2}, ["attha"] = {pseudostem = "kattha", ndel = attha_len[sc] or 3}, }		way = way[ending] if way then pat[sc] = convert_suffixes(way.pseudostem, way.ndel, pat, sc) if ending == 'etha' then debug_outer=debug_outer..'tr:'..pat[sc][1][1] end else error('Cannot convert derivations from suffix '..ending..' for '..sc) end return pat[sc] end end

local function define_overrides(params, prefix, mod_default) for _, pn in pairs({"1s", "2s", "3s", "1p", "2p", "3p"}) do		params[prefix.."a"..pn] = {list = true} params[prefix.."m"..pn] = {list = true} params[prefix.."a"..pn.."_mod"] = {default = mod_default} params[prefix.."m"..pn.."_mod"] = {default = mod_default} end end

function export.parse(args) mod_default = 'after' local params = { [1] = {}, -- Just ignore cite = {list = true}, midl = {list = true}, label = {}, voice = {default = 'both'}, -- Overridden by cite and midl impf_voice = {default = 'none'}, augment = {default = 'both_made'}, impf = {list = true}, -- Only forms including augment impf_midl = {list = true}, -- Only forms including augment impr_voice = {}, -- defaults to (corrected) value of voice opta_voice = {}, -- defaults to (corrected) value of voice opta_mod = {default = mod_default}, opta = {list = true}, opta_midl = {list = true}, part_voice = {}, -- defaults to (corrected) value of voice pap_mod = {default = mod_default}, pap = {list = true}, pmp_mod = {default = mod_default}, pmp = {list = true}, }	define_overrides(params, '',     mod_default) define_overrides(params, 'impf_', mod_default) define_overrides(params, 'impr_', mod_default) define_overrides(params, 'opta_', mod_default) return m_parameters.process(args, params) end

local arrcat_nodup = function(a1, a2) -- Concatenate two arrays local n1 = #a1 local n2 = #a2 local cat = {} for i = 1, n1 do cat[i] = a1[i] end for i = 1, n2 do		local met = false for j = 1, n1 do			if a2[i] == cat[j] then met = true; break; end end if not met then n1 = n1 + 1 cat[n1] = a2[i] end end return cat end

local function kill_final_vole(stem) return gsub(stem, "([เโ])([^เโ]*)$", "%2") end

local function toggle_vo(stem) local toggle = {["เ"]="โ", ["โ"]="เ"} local function f_toggle(m1, m2) return toggle[m1]..m2 end return gsub(stem, "([เโ])([^เโ]*)$", f_toggle) end

function export.joinSuffix(sc, base, pattern) if pattern.voi then local res = {} for _,v in ipairs(pattern) do			local forms, rest local base2 = nil if match(v, '⌫⌫⌫⌫⌫Ⓓ') then base2 = kill_final_vole(sub(base, 1, -6)) rest = sub(v,7) elseif match(v, '⌫⌫⌫⌫Ⓓ') then base2 = kill_final_vole(sub(base, 1, -5)) rest = sub(v,6) elseif match(v, '⌫⌫⌫Ⓓ') then base2 = kill_final_vole(sub(base, 1, -4)) rest = sub(v,5) elseif match(v, '⌫⌫Ⓓ') then base2 = kill_final_vole(sub(base, 1, -3)) rest = sub(v,4) elseif match(v, '⌫Ⓓ') then base2 = kill_final_vole(sub(base, 1, -2)) rest = sub(v,3) elseif match(v, 'Ⓓ') then base2 = kill_final_vole(sub(base, 1, -1)) rest = sub(v,2) elseif match(v, '⌫⌫⌫⌫⌫Ⓣ') then base2 = toggle_vo(sub(base, 1, -6)) rest = sub(v,7) elseif match(v, '⌫⌫⌫⌫Ⓣ') then base2 = toggle_vo(sub(base, 1, -5)) rest = sub(v,6) elseif match(v, '⌫⌫⌫Ⓣ') then base2 = toggle_vo(sub(base, 1, -4)) rest = sub(v,5) elseif match(v, '⌫⌫Ⓣ') then base2 = toggle_vo(sub(base, 1, -3)) rest = sub(v,4) elseif match(v, '⌫Ⓣ') then base2 = toggle_vo(sub(base, 1, -2)) rest = sub(v,3) elseif match(v, 'Ⓣ') then base2 = toggle_vo(sub(base, 1, -1)) rest = sub(v,2) end if base2 then forms = m_noun.joinSuffix(sc, base2, {rest}) else forms = m_noun.joinSuffix(sc, base, {v}) end res = arrcat_nodup(res, forms) end return res elseif pattern.kill_final_preposed then return m_noun.joinSuffix(sc, kill_final_vole(base), pattern) else return m_noun.joinSuffix(sc, base, pattern) end end

function export.joinSuffixes(scriptCode, stem, pattern) local forms = {} for i = 1, 6 do		forms[i] = export.joinSuffix(scriptCode, stem, pattern[i]) end return forms end

pattern.ayati = mw.clone(pattern.ati) pattern.ayati.mid = "ayate" -- Lose some of the shorter forms. pattern.ayati.imperative[3] = {"⌫⌫⌫āhi"} pattern.ayati.imperative[5] = {} -- {"⌫aṃ", "⌫⌫⌫⌫⌫etaṃ"} -- 3s needs review pattern.ayati.optative_active[1] = {"⌫⌫⌫eyyāmi", "⌫⌫⌫eyyaṃ"} pattern.ayati.optative_active[3] = {"⌫⌫⌫eyyāsi"} pattern.ayate = mw.clone(pattern.ate)

function export.modify_voice(forms, prefix, args) -- Only null action is implemented. for i, pn in pairs({"1s", "1p", "2s", "2p", "3s", "3p"}) do			local flag = pn..'_mod' if #args[pn] > 0 then if args[flag] == 'after' then forms[i] = arrcat_nodup(forms[i], args[pn]) forms.isnil = false elseif args[flag] == 'replace' then forms[i] = args[pn] forms.isnil = false elseif args[flag] == 'before' then forms[i] = arrcat_nodup(args[pn], forms[i]) forms.isnil = false elseif args[flag] == 'blank' then forms[i] = {} else error('Argument '..prefix..pn..' has invalid value '..args[flag]) end elseif args[flag] == 'blank' then forms[i] = {} end end end

function export.present(cite, tense, formsa, formsm) local rows = {"1st", "2nd", "3rd"} local forms1 local output = ' '.. ' '..tense.. ' forms of "' .. cite .. '"' ..' ' output = output .. ' "	return output end

-- Basic from of augment: local augment = { Latn="a", Thai="อ", Deva="अ", Beng="অ", Mymr="အ", Lana="ᩋ", Khmr="អ", Sinh="අ", Brah="𑀅", }

local enda3s = { Latn="ti", Thai="ติ", Deva="ति", Beng="তি ", Mymr="တိ", Lana="ᨲᩥ", Khmr="តិ", Sinh="ති", Brah="𑀢𑀺", }

local function presentify(imp3s, sc) return imp3s..enda3s[sc] end

local function select_args(old, prefix) -- prefix must be in ASCII local new = {} local pattern = '^'..prefix local follow = string.len(pattern) for i, v in pairs(old) do		if string.match(i,pattern) then new[asub(i, follow)] = v		end end return new end

function export.modify(formsa, formsm, prefix, args) local subprefix if not formsa then formsa = {{}, {}, {}, {}, {}, {}, isnil=true} end subprefix = prefix..'a'	export.modify_voice(formsa, subprefix, select_args(args,subprefix)) if formsa.isnil then formsa = nil end if not formsm then formsm = {{}, {}, {}, {}, {}, {}, isnil=true} end subprefix = prefix..'m'	export.modify_voice(formsm, subprefix, select_args(args,subprefix)) if formsm.isnil then formsm = nil end return formsa, formsm end

function export.show(frame) local args = mw.clone(frame:getParent.args) local PAGENAME = mw.title.getCurrentTitle.text local cite = args[1] or args["cite"] or PAGENAME currentScript = lang:findBestScript(cite) scriptCode = currentScript:getCode args = export.parse(args) args.cite = arrcat_nodup({cite}, args.cite) if not args.label then args.label = cite end local debug = '\n\nAt (1), args.cite = '..table.concat(args.cite, ' ') local patpa, patpm, basepa, basepm

local tables = {"", "", "", "", "", ""} -- Handle present tense. This forms a base for others. local ending = export.detectEnding(cite) patpa = export.getSuffixes(scriptCode, ending) basepa = cite local mset = nil local forBoth = false local aset = args.cite local voice = "both" if 'e' == asub(ending, -1) then -- No active inflection patpm = patpa patpa = nil basepm = cite aset = nil mset = args.cite voice = "midl" elseif args.midl and args.midl[1] then basepm = args.midl[1] mset = args.midl local midend = export.detectEnding(basepm) patpm = export.getSuffixes(scriptCode, midend) elseif args.voice == 'act' then patpm = nil voice = "act" else patpm = pattern[ending].mid and export.getSuffixes(scriptCode, pattern[ending].mid) basepm = cite forBoth = true mset = args.cite end local formsa = nil local formsm = nil if patpa then formsa = export.joinSuffixes(scriptCode, basepa, patpa) for k = 2, #aset do			basepa = aset[k] patpa = export.getSuffixes(scriptCode, export.detectEnding(basepa)) local extras = export.joinSuffixes(scriptCode, basepa, patpa) for ip = 1, 6 do				formsa[ip] = arrcat_nodup(formsa[ip], extras[ip]) end end end if patpm or forBoth then if patpm then formsm = export.joinSuffixes(scriptCode, basepm, patpm) else formsm = {{}, {}, {}, {}, {}, {}} end for k = 2, #mset do			basepm = mset[k] local kend = export.detectEnding(basepm) if forBoth then kend = pattern[kend].mid end if kend then patpm = export.getSuffixes(scriptCode, kend) local extras = export.joinSuffixes(scriptCode, basepm, patpm) for ip = 1, 6 do					formsm[ip] = arrcat_nodup(formsm[ip], extras[ip]) end end end end formsa, formsm = export.modify(formsa, formsm, '', args)

if formsa or formsm then tables[1] = export.present(args.label, 'Present', formsa, formsm) end

-- Form imperative from present formsa = nil formsm = nil local imperativeVoice = args.impr_voice or voice if imperativeVoice == 'act' or imperativeVoice == 'both' then local patma formsa = {{}, {}, {}, {}, {}, {}} for k = 1, #aset do   		kend = export.detectEnding(aset[k]) patma = export.getSuffixes(scriptCode, kend, 'imperative') if patma then local extras = export.joinSuffixes(scriptCode, aset[k], patma) for ip = 1, 6 do   				formsa[ip] = arrcat_nodup(formsa[ip], extras[ip]) end end end end if imperativeVoice == 'midl' or imperativeVoice == 'both' then local patmm formsm = {{}, {}, {}, {}, {}, {}} local nstem, form3s if forBoth then nstem = #aset else nstem = #mset end for k = 1, nstem do   		if forBoth then form3s = aset[k] kend = export.detectEnding(form3s) if pattern[kend].mid then kend = pattern[kend].mid elseif kend == "eti" then kend = nil else error('No middle endings for ending "'..kend..'".') kend = nil end else form3s = mset[k] kend = export.detectEnding(form3s) end patmm = kend and export.getSuffixes(scriptCode, kend, 'imperative') if patmm then local extras = export.joinSuffixes(scriptCode, form3s, patmm) for ip = 1, 6 do   				formsm[ip] = arrcat_nodup(formsm[ip], extras[ip]) end end end end debug = debug..'\n\nAt (8), formsa='..tostring(formsa) formsa, formsm = export.modify(formsa, formsm, 'impr_', args) if formsa then debug = debug..'\n\nAt (9), formsa='..tostring(formsa).. ' formsa.isnil='..tostring(formsa.isnil) else debug = debug..'\n\nAt (9), formsa='..tostring(formsa) end if formsa or formsm then tables[3] = export.present(args.label, 'Imperative', formsa, formsm) end

-- Form imperfect from present. Existence defaults to false for both voices. impf = {} if (args.impf_voice ~= 'none') then if args.augment == 'without' then if not aset then impf = aset end elseif args.augment == 'with_made' then if aset then for k = 1, #aset do impf[k] = augment[scriptCode] .. aset[k] end end elseif args.augment == 'with_given' then for k = 1, #args.impf do				impf[k] = presentify(args.impf[k], scriptCode) end elseif args.augment == 'both_made' then if aset then for k = 1, #aset do impf[k] = augment[scriptCode] .. aset[k] end for k = 1, #aset do					impf[#aset+k] = aset[k] end end elseif args.argument == 'both_given' then for k = 1, #args.impf do				impf[k] = presentify(args.impf[k], scriptCode) end if aset then for k = 1, #aset do					impf[#args.impf+k] = aset[k] end end else error('Argument augment has bad value "'..args.augment..'".') end end if (args.impf_voice == 'both' or args.impf_voice == 'act') and (voice == 'both' or voice == 'act') then formsa = {{}, {}, {}, {}, {}, {}} for k = 1, #impf do			kend = export.detectEnding(impf[k]) patma = export.getSuffixes(scriptCode, kend, 'imperfect') if patma then local extras = export.joinSuffixes(scriptCode, impf[k], patma) for ip = 1, 6 do					formsa[ip] = arrcat_nodup(formsa[ip], extras[ip]) end end end else formsa = nil end if (args.impf_voice == 'both' or args.impf_voice == 'midl') and (voice == 'both' or voice == 'midl') then formsm = {{}, {}, {}, {}, {}, {}} if not forBoth then impf = {} if args.augment == 'without' then impf = mset elseif args.augment == 'with_made' then for k = 1, #mset do impf[k] = augment[scriptCode] .. mset[k] end elseif args.augment == 'with_given' then impf = args.impf_midl elseif args.augment == 'both_made' then for k = 1, #mset do impf[k] = augment[scriptCode] .. mset[k] end for k = 1, #mset do					impf[#mset+k] = mset[k] end elseif args.argument == 'both_given' then for k = 1, #args.impf_midl do					impf[k] = args.impf_midl[k] end for k = 1, #mset do					impf[#args.impf_midl+k] = mset[k] end else error('Argument augment has bad value "'..args.augment..'".') end end for k = 1, #impf do			kend = export.detectEnding(impf[k]) debug=debug..'\n\nAt (7) impf[k]='..impf[k] if forBoth then if pattern[kend].mid then kend = pattern[kend].mid else error('No middle endings for ending "'..kend..'".') kend = nil end end local pat = export.getSuffixes(scriptCode, kend, 'imperfect') if pat then local extras = export.joinSuffixes(scriptCode, impf[k], pat) for ip = 1, 6 do					formsm[ip] = arrcat_nodup(formsm[ip], extras[ip]) end else mw.addWarning('No imperfect middle suffixes for '..impf[k]..					' ('..kend..')') end end else formsm = nil end formsa, formsm = export.modify(formsa, formsm, 'impf_', args) if formsa or formsm then tables[2] = export.present(args.label, 'Imperfect', formsa, formsm) end -- Form optative from present citation forms. args.opta_voice = args.opta_voice or voice debug = debug .. '\n\nAt (2), args.cite = '..table.concat(args.cite, ' ') local opta = args.cite debug = debug .. '\n\nAt (3), opta = '..table.concat(opta, ' ') if args.opta then debug = debug..'\n\nAt (4), args.opta='..table.concat(args.opta)..', args.opta_mod='..args.opta_mod if args.opta_mod == 'replace' then opta = args.opta elseif args.opta_mod == 'after' then opta = arrcat_nodup(opta, args.opta) elseif args.opta_mod == 'before' then opta = arrcat_nodup(args.opta, opta) elseif args.opta_mod == 'blank' then args.opta_voice = 'none' else error('Argument opta_mod has bad value "'..args.opta_mode..'".') end end debug = debug .. '\n\nAt (5), opta = '..table.concat(opta, ' ').. ', args.opta_voice='..args.opta_voice if args.opta_voice == 'both' or args.opta_voice == 'act' then formsa = {{}, {}, {}, {}, {}, {}} for k = 1, #opta do			kend = export.detectEnding(opta[k]) patma = export.getSuffixes(scriptCode, kend, 'optative_active') if patma then local extras = export.joinSuffixes(scriptCode, opta[k], patma) for ip = 1, 6 do					formsa[ip] = arrcat_nodup(formsa[ip], extras[ip]) end end end elseif args.opta_voice == 'midl' or args.opta_voice == 'none' then formsa = nil else error('Argument opta_voice has bad value "'..args.opta_voice..'".') end if #args.opta_midl > 0 then opta = args.opta_midl end formsm = nil

if args.opta_voice == 'both' or args.opta_voice == 'midl' then formsm = {{}, {}, {}, {}, {}, {}} debug=debug..'\n\nAt (6), opta='..table.concat(opta) for k = 1, #opta do			kend = export.detectEnding(opta[k]) patma = export.getSuffixes(scriptCode, kend, 'optative_middle') if patma then local extras = export.joinSuffixes(scriptCode, opta[k], patma) for ip = 1, 6 do					formsm[ip] = arrcat_nodup(formsm[ip], extras[ip]) end else debug = debug.."\n\nNo "..kend..".optative_middle" end end else formsm = nil end

formsa, formsm = export.modify(formsa, formsm, 'opta_', args) if formsa or formsm then tables[4] = export.present(args.label, 'Optative', formsa, formsm) end

--	List present participles. local pap, pmp = {}, {} args.part_voice = args.part_voice or voice if args.part_voice == 'both' or args.part_voice == 'act' then if voice == 'both' or voice == 'act' then for k = 1, aset and #aset or 0 do				local kend = export.detectEnding(aset[k]) local pat = kend and export.getSuffixes(scriptCode, kend, "participle") if pat then local extra = export.joinSuffix(scriptCode, aset[k], pat[1]) pap = arrcat_nodup(pap, extra) end end end if args.pap_mod == 'blank' then pap = {} elseif args.pap_mod == 'after' then pap = arrcat_nodup(pap, args.pap) elseif args.pap_mod == 'before' then pap = arrcat_nodup(args.pap, pap) elseif args.pap_mod == 'replace' then pap = args.pap else error('Argument pap_mod has invalid value '..args.pap_mod) end if #pap > 0 then tables[5] = tables[5]..'\n* Present participle: '.. m_noun.orJoin(currentScript, pap)..', which see for forms and usage' end elseif args.part_voice == 'midl' or args.part_voice == 'none' then -- permissible else error('Argument part_voice has invalid value '..args.part_voice) end if args.part_voice == 'both' or args.part_voice == 'midl' then local list local from_active = forBoth or voice == 'act' if from_active then list = aset else list = mset end for k = 1, list and #list or 0 do			local kend = export.detectEnding(list[k]) if from_active then kend = pattern[kend].mid end local pat = kend and export.getSuffixes(scriptCode, kend, "participle") if pat then local extra = export.joinSuffix(scriptCode, list[k], pat[1]) pmp = arrcat_nodup(pmp, extra) end end if args.pmp_mod == 'blank' then pmp = {} elseif args.pmp_mod == 'after' then pmp = arrcat_nodup(pmp, args.pmp) elseif args.pmp_mod == 'before' then pmp = arrcat_nodup(args.pmp, pmp) elseif args.pmp_mod == 'replace' then pmp = args.pmp else error('Argument pmp_mod has invalid value '..args.pmp_mod) end if #pmp > 0 then tables[5] = tables[5]..'\n* Present participle: '.. m_noun.orJoin(currentScript, pmp)..', which see for forms and usage' end end --	tables[6] = debug..'\n\n'..debug_outer

return table.concat(tables)

end

return export