This module serves as the backend for Template:ta-conj-auto. It is also used in Module:ta-decl.


local export = {}
local m_translit = require("Module:ta-translit")

local gsub = mw.ustring.gsub
local sub = mw.ustring.sub
local match = mw.ustring.match
local len = mw.ustring.len

local consonants = {
	['க']='k' , ['ங']='ṅ' , ['ச']='c' , ['ஞ']='ñ' , ['ட']='ṭ' , ['ண']='ṇ' , ['த']='t' ,
	['ந']='n' , ['ப']='p', ['ம']='m' , ['ய']='y' , ['ர']='r' , ['ல']='l' , ['வ']='v' ,
	['ழ']='ḻ' , ['ள']='ḷ' , ['ற']='ṟ' , ['ன']='ṉ' , ['ஶ']='ś' , ['ஜ']='j' , ['ஷ']='ṣ' , 
	['ஸ']='s' , ['ஹ']='h' , ['ஃப']='f' , ['ஃஜ']='z' , ['ஃஸ']='x' ,
	['ஃ']='ḥ' ,
}

local stops = {
	['க']='k' , ['ச']='c' , ['ட']='ṭ' , ['த']='t' ,
	['ப']='p', ['ற']='ṟ'
}

local matras = {
	['ா']= 'ā' , ['ி']='i' , ['ீ']='ī' , ['ு']='u' , ['ூ']='ū' ,  ['ெ']='e' ,
	['ே']='ē' , ['ை']='ai' , ['ொ']='o' , ['ோ']='ō' , ['ௌ']='au'  ,
	['்']='',	--halant, supresses the inherent vowel "a"
	-- no diacritic
	[''] = 'a'
}

local front_vowels = {
	['ி']='i' , ['ீ']='ī' , ['ு']='u' , ['ெ']='e' ,
	['ே']='ē' , ['ை']='ai' 
}

local back_vowels = {
	-- or implicit 'a' ending! --
	['ா']= 'ā' , ['ு']='u' , ['ூ']='ū' ,
	['ொ']='o' , ['ோ']='ō' , ['ௌ']='au'  ,
}

local nonconsonants = {
	['அ']='’a' , ['ஆ']='’ā' , ['இ']='’i' , ['ஈ']='’ī' , ['உ']='’u' , ['ஊ']='’ū' , 
	['எ']='’e' , ['ஏ']='’ē' , ['ஐ']='’ai' , ['ஒ']='’o' , ['ஓ']='’ō' , ['ஔ']='’au' 
}

local nasals = {
	['ங']='ṅ' , ['ஞ']='ñ' ,  ['ண']='ṇ' , ['ந']='n' ,
	['ம']='m' , ['ன']='ṉ' ,
}

local laterals = {
	['ள']='ḷ' , ['ல']='l' 
}

local vowel_conv = {
	['அ']='', ['ஆ']='ா' , ['இ']='ி' , ['ஈ']='ீ' , ['உ']='ு' , ['ஊ']='ூ' , 
    ['எ']='ெ' , ['ஏ']='ே' , ['ஐ']='ை' , ['ஒ']='ொ' , ['ஓ']='ோ' , ['ஔ']='ௌ' , 
}


local irregular_infinitives = {
	['வில்'] = "விற்க",
	['நில்'] = "நிற்க",
	['கல்'] = "கற்க",
	['கில்'] = "கிற்க",
	['கேள்'] = "கேட்க",
	['வா'] = "வர",
	['தா'] = "தர",
	['போ'] = "போக",
	['சா'] = "சாக",
	['தோல்'] = "தோற்க",
}

-- this is meant to be an all purpose sandhi handler
function export.agglutinate(stem, suffix, args)
    delete_final_u = (args and args.delete_final_u) or false
    delete_final_a = (args and args.delete_final_a) or false
    assimilate_lateral_to_stop = (args and args.assimilate_lateral_to_stop) or false
    do_not_duplicate_laterals = (args and args.do_not_duplicate_laterals) or false
    do_not_duplicate_nasals = (args and args.do_not_duplicate_nasals) or false
    do_not_adjust_nasals = (args and args.do_not_adjust_nasals) or false
    
    -- conv matras
    local vowelic_suffix = false
    if nonconsonants[sub(suffix, 1, 1)] then
    	vowelic_suffix = true
    	suffix = vowel_conv[sub(suffix, 1, 1)] .. sub(suffix, 2)
    end
    
    -- simple cases without sandhi
    if sub(stem, -1) == '்' and vowelic_suffix then
    	-- consonant meets vowel boundary
    	if (nasals[sub(stem, -2, -2)] and not do_not_duplicate_nasals) or (laterals[sub(stem, -2, -2)] and not do_not_duplicate_laterals) then
    		return stem .. sub(stem, -2, -2) .. suffix
    	end
    	return sub(stem, 1, -2) .. suffix
    elseif sub(stem, -1) ~= '்' and consonants[sub(suffix, 1, 1)] then
    	-- vowel meets consonant boundary 
    	if sub(suffix, 1, 1) == 'ந' and sub(suffix, 2, 2) ~= '்' then
    		return stem .. 'ன' .. sub(suffix, 2) -- edge case since ந is never intervowelic
    	end
    	return stem .. suffix
    end
    
    -- vowel meets vowel cases with deletion
    if sub(stem, -1) == 'ு' and delete_final_u then
    	return sub(stem, 1, -2) .. suffix
    elseif consonants[sub(stem, -1)] and delete_final_a then
    	return stem .. suffix
    end
    
    -- vowel meets vowel cases include vowel for euphony
    if sub(stem, -1) ~= '்' then
    	if front_vowels[sub(stem, -1)] then
    		return stem .. 'ய' .. suffix
    	elseif back_vowels[sub(stem, -1)] or consonants[sub(stem, -1)] then
    		return stem .. 'வ' .. suffix
    	end
    	return stem .. suffix -- something unusual
    end
    -- consonant meets consonant cases
    if (nasals[sub(stem, -2, -2)] and stops[sub(suffix, 1, 1)]) and not do_not_adjust_nasals then -- nasal assimilation
    	if sub(suffix, 1, 1) == 'க' and sub(stem, -2, -2) ~= "ண" then return sub(stem, 1, -3) .. 'ங்' .. suffix
    	elseif sub(suffix, 1, 1) == 'ச' then return sub(stem, 1, -3) .. 'ஞ்' .. suffix
    	elseif sub(suffix, 1, 1) == 'ட' then return sub(stem, 1, -3) .. 'ண்' .. suffix
    	elseif sub(suffix, 1, 1) == 'த' then return sub(stem, 1, -3) .. 'ந்' .. suffix
    	elseif sub(suffix, 1, 1) == 'ப' and sub(stem, -2, -2) ~= ("ண" or "ன") then return sub(stem, 1, -3) .. 'ம்' .. suffix
    	elseif sub(suffix, 1, 1) == 'ற' then return sub(stem, 1, -3) .. 'ன்' .. suffix
    	end
    	return stem .. suffix -- something unusual
    end
    if laterals[sub(stem, -2, -2)] and (sub(suffix, 1, 1) == 'ட' or sub(suffix, 1, 1) == 'த') then -- lateral assimilation
    	if assimilate_lateral_to_stop then
    		if sub(stem, -2, -2) == 'ல' then return sub(stem, 1, -3) .. 'ற்ற' .. sub(suffix, 2)
    		elseif sub(stem, -2, -2) == 'ள' then return sub(stem, 1, -3) .. 'ட்ட' .. sub(suffix, 2)
    		end
    	else
    		if sub(stem, -2, -2) == 'ல' then return sub(stem, 1, -3) .. 'ன்ற' .. sub(suffix, 2)
    		elseif sub(stem, -2, -2) == 'ள' then return sub(stem, 1, -3) .. 'ண்ட' .. sub(suffix, 2)
    		end
    	end
    end    
	return stem .. suffix -- ordinary
end

local endings = { -- 10 personal endings
	"ஏன்", "ஆய்", "ஆன்", "ஆள்", "ஆர்", "அது", "ஓம்", "ஈர்கள்", "ஆர்கள்", "அன"
}

local neg_futu_endings = { -- 10 personal endings
	"மாட்டேன்", "மாட்டாய்", "மாட்டான்", "மாட்டாள்", "மாட்டார்", "ஆது", "மாட்டோம்", "மாட்டீர்கள்", "மாட்டார்கள்", "ஆ"
}

local verbal_noun_endings = { -- 6 verbal noun endings
	"அவன்", "அவள்", "அவர்", "அது", "அவர்கள்", "அவை"
}

local suffixes = {
	[1] = {
		["past"] = "த",
		["present"] = "கிற",
		["avai_present"] = "கின்ற",
		["future"] = "வ",
		["infinitive"] = "அ",
		["gerunds"] = "தல்",
		["infinitive_sandhi"] = {
			["delete_final_u"] = true
		},
		["past_sandhi"] = {}
	},
	[2] = {
		["past"] = "ந்த",
		["present"] = "கிற",
		["avai_present"] = "கின்ற",
		["future"] = "வ",
		["infinitive"] = "அ",
		["gerunds"] = "தல்",
		["infinitive_sandhi"] = {
			["delete_final_u"] = true
		},
		["past_sandhi"] = {}
	},
	[3] = {
		["past"] = "ன",
		["present"] = "கிற",
		["avai_present"] = "கின்ற",
		["future"] = "வ",
		["infinitive"] = "அ",
		["gerunds"] = "தல்",
		["infinitive_sandhi"] = {
			["delete_final_u"] = true
		},
		["past_sandhi"] = {}
	},
	[4] = {
		["past"] = "ட",
		["present"] = "கிற",
		["avai_present"] = "கின்ற",
		["future"] = "வ",
		["infinitive"] = "அ",
		["gerunds"] = "தல்",
		["infinitive_sandhi"] = {
			["delete_final_u"] = true
		},
		["past_sandhi"] = {
			["delete_final_u"] = true
		}
	},
	[5] = {
		["past"] = "ட",
		["present"] = "கிற",
		["avai_present"] = "கின்ற",
		["future"] = "ப",
		["infinitive"] = "அ",
		["gerunds"] = "தல்",
		["infinitive_sandhi"] = {
			["delete_final_u"] = true
		},
		["past_sandhi"] = {}
	},
	[6] = {
		["past"] = "த்த",
		["present"] = "க்கிற",
		["avai_present"] = "க்கின்ற",
		["future"] = "ப்ப",
		["infinitive"] = "க்க",
		["gerunds"] = "த்தல்",
		["infinitive_sandhi"] = {},
		["past_sandhi"] = {}
	},
	[7] = {
		["past"] = "ந்த",
		["present"] = "க்கிற",
		["avai_present"] = "க்கின்ற",
		["future"] = "ப்ப",
		["infinitive"] = "க்க",
		["gerunds"] = "ந்தல்",
		["infinitive_sandhi"] = {},
		["past_sandhi"] = {}
	}
}

-- Clone parent’s args while also assigning nil to empty strings.
local function clone_args(frame)
	local args = {}
	for pname, param in pairs(frame:getParent().args) do
		if param == "" then args[pname] = nil
		else args[pname] = param
		end
	end
	return args
end

function export.do_generate_forms(args)
	local data = {}
	
	assert(args[1], "Need a class for the word")
	local class = tonumber(args[1])
	data.class = class
	assert(data.class, "Class is not a number: " .. args[1])
	local base = args[2] or mw.title.getCurrentTitle().text
	local namespace = mw.title.getCurrentTitle().nsText
	data.imperat_sg = args.imperat_sg or base
	data.inf = args.inf or irregular_infinitives[base] or export.agglutinate(base, suffixes[class].infinitive, suffixes[class].infinitive_sandhi)
	data.imperat_pl = args.imperat_pl or ""
	if data.imperat_pl == "" then
	if class > 4 then
		data.imperat_pl = export.agglutinate(base, "உங்கள்", {["delete_final_u"] = true })
	else data.imperat_pl = export.agglutinate(data.inf, "உங்கள்", {["delete_final_a"] = true })
	end
	end
	-- if not data.inf then
	-- 	-- if data.class <= 5 then
	-- 	-- 	data.inf = export.agglutinate(data.imperat, "அ", {["delete_final_u"] = true })
	-- 	-- elseif data.class <= 7 then
	-- 	-- 	data.inf = export.agglutinate(data.imperat, "க்க", {})
	-- 	-- end
	-- end
	data.adv_part = args.adv_part or ""
	if class == 3 and data.adv_part == "" then
		data.adv_part = export.agglutinate(data.inf, "இ", {["delete_final_a"] = true })
	end
	data.gerunds2 = args.gerund_2 or export.agglutinate(base, suffixes[class].gerunds)
	data.aff_pres = {}
	local aff_pres_base = args.aff_pres_base or export.agglutinate(base, suffixes[class].present)
	local aff_pres_avai_base = args.aff_pres_avai_base or export.agglutinate(base, suffixes[class].avai_present)
	for i, ending in pairs(endings) do
		if i == 10 then
			table.insert(data.aff_pres, export.agglutinate(aff_pres_avai_base, ending,  {["delete_final_a"] = true }))
		else
			table.insert(data.aff_pres, export.agglutinate(aff_pres_base, ending,  {["delete_final_a"] = true }))
		end
	end
	
	data.aff_past = {}
	local aff_past_base = args.aff_past_base
	if not aff_past_base then
		if class == 3 then 
			aff_past_base = export.agglutinate(data.adv_part, suffixes[class].past, suffixes[class].past_sandhi)
elseif class == 4 and sub(base, -2) ~= "டு" and sub(base, -1) == "ு" then
aff_past_base = export.agglutinate(sub(base, 1, -3)..sub(sub(base, 1, -2), -1).."்", sub(sub(base, 1, -2), -1))
		elseif class == 4 and sub(base, -1) ~= '்' then
			aff_past_base = export.agglutinate(sub(base, 1, -2) .. '்', suffixes[class].past, suffixes[class].past_sandhi)
		else
			aff_past_base = export.agglutinate(base, suffixes[class].past, suffixes[class].past_sandhi)
		end
	end
	for i, ending in pairs(endings) do
		table.insert(data.aff_past, export.agglutinate(aff_past_base, ending,  {["delete_final_a"] = true }))
	end
	if class ~= 3 and data.adv_part == "" then
		data.adv_part = export.agglutinate(aff_past_base, "உ",  {["delete_final_a"] = true })
	end
	
	data.aff_futu = {}
	local aff_futu_base = args.aff_futu_base or export.agglutinate(base, suffixes[class].future)
	for i, ending in pairs(endings) do
		if i == 6 then
			table.insert(data.aff_futu, export.agglutinate(data.inf, "உம்",  {["delete_final_a"] = true }))
		else
			table.insert(data.aff_futu, export.agglutinate(aff_futu_base, ending,  {["delete_final_a"] = true }))
		end
	end
	
	data.aff_neg_futu = {}
	for i, ending in pairs(neg_futu_endings) do
		table.insert(data.aff_neg_futu, export.agglutinate(data.inf, ending,  {["delete_final_a"] = true }))
	end
	
	data.aff_neg = export.agglutinate(data.inf, "வில்லை",  {["delete_final_a"] = true })
	data.neg_imperat_sg = export.agglutinate(data.inf, "ஆதே",  {["delete_final_a"] = true })
	data.neg_imperat_pl = export.agglutinate(data.inf, "ஆதீர்கள்",  {["delete_final_a"] = true })
	local avp = data.adv_part
	data.pres_perf = export.agglutinate(avp, "விடு")
	data.past_perf = export.agglutinate(avp, "விட்டிரு")
	data.futu_perf = export.agglutinate(avp, "விடு")
	data.progressive = export.agglutinate(avp, "க்கொண்டிரு")
	data.eff = export.agglutinate(data.inf, "ப்படு")
	data.neg_inf = export.agglutinate(data.inf, "ஆமல் இருக்க", {["delete_final_a"] = true })
	data.pot = export.agglutinate(data.inf, "லாம்", {["delete_final_a"] = true })
	data.neg_pot = export.agglutinate(data.inf, "ஆமல் இருக்கலாம்", {["delete_final_a"] = true })
	data.cohortative = export.agglutinate(data.inf, "ட்டும்", {["delete_final_a"] = true })
	data.neg_cohortative = export.agglutinate(data.inf, "ஆமல் இருக்கட்டும்", {["delete_final_a"] = true })
	
	data.neg_casual_conditional = export.agglutinate(data.inf, "ஆத்தால்", {["delete_final_a"] = true })
	data.conditional = export.agglutinate(aff_past_base, "ஆல்", {["delete_final_a"] = true })
	data.neg_conditional = export.agglutinate(data.inf, "ஆவிட்டால்", {["delete_final_a"] = true })
	
	data.neg_adv_part = export.agglutinate(data.inf, "ஆமல்", {["delete_final_a"] = true })
	
	data.pres_adj_part = aff_pres_base
	data.past_adj_part = aff_past_base
	data.futu_adj_part = export.agglutinate(data.inf, "உம்",  {["delete_final_a"] = true })
	data.neg_adj_part = export.agglutinate(data.inf, "ஆத", {["delete_final_a"] = true })
	
	data.verbal_noun_pres = {}
	for i, ending in pairs(verbal_noun_endings) do
		table.insert(data.verbal_noun_pres, export.agglutinate(aff_pres_base, ending,  {["delete_final_a"] = true }))
	end
	
	data.verbal_noun_past = {}
	for i, ending in pairs(verbal_noun_endings) do
		table.insert(data.verbal_noun_past, export.agglutinate(aff_past_base, ending,  {["delete_final_a"] = true }))
	end
	
	data.verbal_noun_futu = {}
	local verbal_noun_futu_base = aff_futu_base
	if suffixes[class].future == "வ" then
		verbal_noun_futu_base = export.agglutinate(base, "ப",  {["delete_final_a"] = true })
	end
	local verbal_noun = export.agglutinate(aff_futu_base, "அது",  {["delete_final_a"] = true })
	for i, ending in pairs(verbal_noun_endings) do
		if i == 4 then
			table.insert(data.verbal_noun_futu, verbal_noun)
		else
			table.insert(data.verbal_noun_futu, export.agglutinate(verbal_noun_futu_base, ending,  {["delete_final_a"] = true }))
		end
	end

	data.casual_conditional = export.agglutinate(verbal_noun, "ஆல்", {["delete_final_a"] = true, ["delete_final_u"] = true  })
	
	data.verbal_noun_neg = {}
	local verbal_noun_neg_base = export.agglutinate(data.inf, "ஆத",  {["delete_final_a"] = true })
	for i, ending in pairs(verbal_noun_endings) do
		table.insert(data.verbal_noun_neg, export.agglutinate(verbal_noun_neg_base, ending,  {["delete_final_a"] = true }))
	end
	
	data.gerunds = {
		verbal_noun,
		data.gerunds2,
		export.agglutinate(data.inf, "அல்", {["delete_final_a"] = true })
	}
	
	local pres_perf = data.pres_perf
	local past_perf = data.past_perf
	local futu_perf = data.futu_perf
	for k, v in pairs(data) do
		if type(v) == "table" then
			for k1, v1 in pairs(v) do
				if (v1 ~= "-") then
					data[k][k1] = '<span class="Taml">[[' .. v1 .. ']]</span> ' .. ' <br/><small style="color: #888">' .. m_translit.tr(v1) .. '</small>'
				end
			end
		else
			if (v ~= "-") then
				data[k] = '<span class="Taml">[[' .. v .. ']]</span>' .. ' <br/><small style="color: #888">' .. m_translit.tr(v) .. '</small>'
			end
		end
	end
	data.base = base .. ' (' .. m_translit.tr(base) .. ')'
	data.pres_perf = '[[' .. pres_perf .. ']] (' .. m_translit.tr(pres_perf) .. ')'
	data.past_perf = '[[' .. past_perf .. ']] (' .. m_translit.tr(past_perf) .. ')'
	data.futu_perf = '[[' .. futu_perf .. ']] (' .. m_translit.tr(futu_perf) .. ')'
	data.categories = ""
	if not (args.nocat or namespace ~= "")  then
		data.categories = "[[Category:Tamil verbs of conjugation "..class.."]]"
	end
	return data
end

function export.show(frame)
	local args = clone_args(frame)
	local data = export.do_generate_forms(args)
	
	local res = {'<div class="NavFrame"><div class="NavHead" style="text-align: left">Conjugation of ' .. data.base .. '</div><div class="NavContent" style="text-align: center; display: none;">'}
	-- local res = {'{| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="background:#F9F9F9; text-align:center; border: 1px solid #CCC; min-width: 20em"'}
	-- table.insert(res, '|- style="background: #d9ebff;"')
	-- table.insert(res, '! class="vsToggleElement" style="text-align: left;" colspan="100%" | Conjugation of ' .. data.imperat_sg)
	table.insert(res, '{| style="width:100%;;text-align:center;;background:#F0F0F0;;padding:.3em"')
	table.insert(res, '|-')
	table.insert(res, '! colspan="1" rowspan="2" style="background:#c0cfe4;;width:14.28%" | singular affective')
	table.insert(res, '! style="background:#c0cfe4;;width:14.28%" | first')
	table.insert(res, '! style="background:#c0cfe4;;width:14.28%" | second')
	table.insert(res, '! style="background:#c0cfe4;;width:14.28%" | third masculine')
	table.insert(res, '! style="background:#c0cfe4;;width:14.28%" | third feminine')
	table.insert(res, '! style="background:#c0cfe4;;width:14.28%" | third honorific')
	table.insert(res, '! style="background:#c0cfe4;;width:14.28%" | third neuter')
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0cfe4;" | [[நான்]]')
	table.insert(res, '! style="background:#c0cfe4;" | [[நீ]]')
	table.insert(res, '! style="background:#c0cfe4;" | [[அவன்]]')
	table.insert(res, '! style="background:#c0cfe4;" | [[அவள்]]')
	table.insert(res, '! style="background:#c0cfe4;" | [[அவர்]]')
	table.insert(res, '! style="background:#c0cfe4;" | [[அது]]')
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0cfe4;" | present')
	table.insert(res, '| ' .. data.aff_pres[1])
	table.insert(res, '| ' .. data.aff_pres[2])
	table.insert(res, '| ' .. data.aff_pres[3])
	table.insert(res, '| ' .. data.aff_pres[4])
	table.insert(res, '| ' .. data.aff_pres[5])
	table.insert(res, '| ' .. data.aff_pres[6])
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0cfe4;" | past')
	table.insert(res, '| ' .. data.aff_past[1])
	table.insert(res, '| ' .. data.aff_past[2])
	table.insert(res, '| ' .. data.aff_past[3])
	table.insert(res, '| ' .. data.aff_past[4])
	table.insert(res, '| ' .. data.aff_past[5])
	table.insert(res, '| ' .. data.aff_past[6])
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0cfe4;" | future')
	table.insert(res, '| ' .. data.aff_futu[1])
	table.insert(res, '| ' .. data.aff_futu[2])
	table.insert(res, '| ' .. data.aff_futu[3])
	table.insert(res, '| ' .. data.aff_futu[4])
	table.insert(res, '| ' .. data.aff_futu[5])
	table.insert(res, '| ' .. data.aff_futu[6])
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0cfe4;" | future negative')
	table.insert(res, '| ' .. data.aff_neg_futu[1])
	table.insert(res, '| ' .. data.aff_neg_futu[2])
	table.insert(res, '| ' .. data.aff_neg_futu[3])
	table.insert(res, '| ' .. data.aff_neg_futu[4])
	table.insert(res, '| ' .. data.aff_neg_futu[5])
	table.insert(res, '| ' .. data.aff_neg_futu[6])
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0cfe4;" | negative')
	table.insert(res, '| colspan="6" | ' .. data.aff_neg)
	table.insert(res, '|-')
	table.insert(res, '! rowspan="2" style="background:#c0cfe4;" | plural affective')
	table.insert(res, '! style="background:#c0cfe4;" | first')
	table.insert(res, '! style="background:#c0cfe4;" | second<br />(or singular polite)')
	table.insert(res, '! colspan="2" style="background:#c0cfe4;" | third epicene')
	table.insert(res, '! colspan="2" style="background:#c0cfe4;" | third neuter')
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0cfe4;" | [[நாம்]] (inclusive)<br />[[நாங்கள்]] (exclusive)')
	table.insert(res, '! style="background:#c0cfe4;" | [[நீங்கள்]]')
	table.insert(res, '! colspan="2" style="background:#c0cfe4;" | [[அவர்கள்]]')
	table.insert(res, '! colspan="2" style="background:#c0cfe4;" | [[அவை]]')
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0cfe4;" | present')
	table.insert(res, '| ' .. data.aff_pres[7])
	table.insert(res, '| ' .. data.aff_pres[8])
	table.insert(res, '| colspan="2" | ' .. data.aff_pres[9])
	table.insert(res, '| colspan="2" | ' .. data.aff_pres[10])
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0cfe4;" | past')
	table.insert(res, '| ' .. data.aff_past[7])
	table.insert(res, '| ' .. data.aff_past[8])
	table.insert(res, '| colspan="2" | ' .. data.aff_past[9])
	table.insert(res, '| colspan="2" | ' .. data.aff_past[10])
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0cfe4;" | future')
	table.insert(res, '| ' .. data.aff_futu[7])
	table.insert(res, '| ' .. data.aff_futu[8])
	table.insert(res, '| colspan="2" | ' .. data.aff_futu[9])
	table.insert(res, '| colspan="2" | ' .. data.aff_futu[10])
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0cfe4;" | future negative')
	table.insert(res, '| ' .. data.aff_neg_futu[7])
	table.insert(res, '| ' .. data.aff_neg_futu[8])
	table.insert(res, '| colspan="2" | ' .. data.aff_neg_futu[9])
	table.insert(res, '| colspan="2" | ' .. data.aff_neg_futu[10])
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0cfe4;" | negative')
	table.insert(res, '| colspan="6" | ' .. data.aff_neg)
	table.insert(res, '|-')
	table.insert(res, '! rowspan="2" style="background:#c0cfe4;" | imperative')
	table.insert(res, '! colspan="3" style="background:#c0cfe4;" | singular')
	table.insert(res, '! colspan="3" style="background:#c0cfe4;" | plural (or singular polite)')
	table.insert(res, '|-')
	table.insert(res, '| colspan="3" | ' .. data.imperat_sg)
	table.insert(res, '| colspan="3" | ' .. data.imperat_pl)
	table.insert(res, '|-')
	table.insert(res, '! rowspan="2" style="background:#c0cfe4;" | negative imperative')
	table.insert(res, '! colspan="3" style="background:#c0cfe4;" | singular')
	table.insert(res, '! colspan="3" style="background:#c0cfe4;" | plural (or singular polite)')
	table.insert(res, '|-')
	table.insert(res, '| colspan="3" | ' .. data.neg_imperat_sg)
	table.insert(res, '| colspan="3" | ' .. data.neg_imperat_pl)
	table.insert(res, '|-')
	table.insert(res, '! rowspan="2" style="background:#c0e4c0;" | perfect')
	table.insert(res, '! colspan="2" style="background:#c0e4c0;" | present')
	table.insert(res, '! colspan="2" style="background:#c0e4c0;" | past')
	table.insert(res, '! colspan="2" style="background:#c0e4c0;" | future')
	table.insert(res, '|-')
	table.insert(res, '| colspan="2" style="background:#CCC;font-weight:bold;" | past of ' .. data.pres_perf)
	table.insert(res, '| colspan="2" style="background:#CCC;font-weight:bold;" | past of ' .. data.past_perf)
	table.insert(res, '| colspan="2" style="background:#CCC;font-weight:bold;" | future of ' .. data.futu_perf)
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0e4c0;" | progressive')
	table.insert(res, '| colspan="7" style="background:#CCC;font-weight:bold;" | ' .. data.progressive)
	table.insert(res, '|-')
	table.insert(res, '! style="background:#c0e4c0;" | effective')
	table.insert(res, '| colspan="7" style="background:#CCC;font-weight:bold;" | ' .. data.eff)
	table.insert(res, '|-')
	table.insert(res, '! style="background:#e2e4cb;" | non-finite forms')
	table.insert(res, '! colspan="3" style="background:#e2e4cb;" | plain')
	table.insert(res, '! colspan="3" style="background:#e2e4cb;" | negative')
	table.insert(res, '|-')
	table.insert(res, '! style="background:#e2e4cb;" | infinitive')
	table.insert(res, '| colspan="3" | ' .. data.inf)
	table.insert(res, '| colspan="3" | ' .. data.neg_inf)
	table.insert(res, '|-')
	table.insert(res, '! style="background:#e2e4cb;" | potential')
	table.insert(res, '| colspan="3" | ' .. data.pot)
	table.insert(res, '| colspan="3" | ' .. data.neg_pot)
	table.insert(res, '|-')
	table.insert(res, '! style="background:#e2e4cb;" | cohortative')
	table.insert(res, '| colspan="3" | ' .. data.cohortative)
	table.insert(res, '| colspan="3" | ' .. data.neg_cohortative)
	table.insert(res, '|-')
	table.insert(res, '! style="background:#e2e4cb;" | casual conditional')
	table.insert(res, '| colspan="3" | ' .. data.casual_conditional)
	table.insert(res, '| colspan="3" | ' .. data.neg_casual_conditional)
	table.insert(res, '|-')
	table.insert(res, '! style="background:#e2e4cb;" | conditional')
	table.insert(res, '| colspan="3" | ' .. data.conditional)
	table.insert(res, '| colspan="3" | ' .. data.neg_conditional)
	table.insert(res, '|-')
	table.insert(res, '! style="background:#e2e4cb;" | adverbial participle')
	table.insert(res, '| colspan="3" | ' .. data.adv_part)
	table.insert(res, '| colspan="3" | ' .. data.neg_adv_part)
	table.insert(res, '|-')
	table.insert(res, '! rowspan="2" style="background:#e2e4cb;" | adjectival participle')
	table.insert(res, '! style="background:#e2e4cb;" | present')
	table.insert(res, '! style="background:#e2e4cb;" | past')
	table.insert(res, '! style="background:#e2e4cb;" | future')
	table.insert(res, '! colspan="3" style="background:#e2e4cb;" | negative')
	table.insert(res, '|-')
	table.insert(res, '| ' .. data.pres_adj_part)
	table.insert(res, '| ' .. data.past_adj_part)
	table.insert(res, '| ' .. data.futu_adj_part)
	table.insert(res, '| colspan="3" | ' .. data.neg_adj_part)
	table.insert(res, '|-')
	table.insert(res, '! rowspan="2" style="background:#e4d4c0;" | verbal noun')
	table.insert(res, '! colspan="4" style="background:#e4d4c0;" | singular')
	table.insert(res, '! colspan="2" style="background:#e4d4c0;" | plural')
	table.insert(res, '|-')
	table.insert(res, '! style="background:#e4d4c0;" | masculine')
	table.insert(res, '! style="background:#e4d4c0;" | feminine')
	table.insert(res, '! style="background:#e4d4c0;" | honorific')
	table.insert(res, '! style="background:#e4d4c0;" | neuter')
	table.insert(res, '! style="background:#e4d4c0;" | epicene')
	table.insert(res, '! style="background:#e4d4c0;" | neuter')
	table.insert(res, '|-')
	table.insert(res, '! style="background:#e4d4c0;" | present')
	table.insert(res, '| ' .. data.verbal_noun_pres[1])
	table.insert(res, '| ' .. data.verbal_noun_pres[2])
	table.insert(res, '| ' .. data.verbal_noun_pres[3])
	table.insert(res, '| ' .. data.verbal_noun_pres[4])
	table.insert(res, '| ' .. data.verbal_noun_pres[5])
	table.insert(res, '| ' .. data.verbal_noun_pres[6])
	table.insert(res, '|-')
	table.insert(res, '! style="background:#e4d4c0;" | past')
	table.insert(res, '| ' .. data.verbal_noun_past[1])
	table.insert(res, '| ' .. data.verbal_noun_past[2])
	table.insert(res, '| ' .. data.verbal_noun_past[3])
	table.insert(res, '| ' .. data.verbal_noun_past[4])
	table.insert(res, '| ' .. data.verbal_noun_past[5])
	table.insert(res, '| ' .. data.verbal_noun_past[6])
	table.insert(res, '|-')
	table.insert(res, '! style="background:#e4d4c0;" | future')
	table.insert(res, '| ' .. data.verbal_noun_futu[1])
	table.insert(res, '| ' .. data.verbal_noun_futu[2])
	table.insert(res, '| ' .. data.verbal_noun_futu[3])
	table.insert(res, '| ' .. data.verbal_noun_futu[4])
	table.insert(res, '| ' .. data.verbal_noun_futu[5])
	table.insert(res, '| ' .. data.verbal_noun_futu[6])
	table.insert(res, '|-')
	table.insert(res, '! style="background:#e4d4c0;" | negative')
	table.insert(res, '| ' .. data.verbal_noun_neg[1])
	table.insert(res, '| ' .. data.verbal_noun_neg[2])
	table.insert(res, '| ' .. data.verbal_noun_neg[3])
	table.insert(res, '| ' .. data.verbal_noun_neg[4])
	table.insert(res, '| ' .. data.verbal_noun_neg[5])
	table.insert(res, '| ' .. data.verbal_noun_neg[6])
	table.insert(res, '|-')
	table.insert(res, '! rowspan="2" style="background:#e4d4c0;" | gerund')
	table.insert(res, '! colspan="2" style="background:#e4d4c0;" | Form I')
	table.insert(res, '! colspan="2" style="background:#e4d4c0;" | Form II')
	table.insert(res, '! colspan="2" style="background:#e4d4c0;" | Form III')
	table.insert(res, '|-')
	table.insert(res, '| colspan="2" | ' .. data.gerunds[1])
	table.insert(res, '| colspan="2" | ' .. data.gerunds[2])
	table.insert(res, '| colspan="2" | ' .. data.gerunds[3])
	table.insert(res, '|}</div></div>')
	if data.categories ~= "" then
		table.insert(res, data.categories)
	end
	
	return table.concat(res, "\n")
end

return export