Jump to content

Module:sa-decl

From Wiktionary, the free dictionary

This module needs documentation.
Please document this module by describing its purpose and usage on the documentation page.

...

To indicate that a word ending on -vat/-mat is to be declined as a present participle (not as suffixed with -vat/-mat), use "participle=1"
Use "at_nom_s=1" for participles like जुह्वत् (júhvat) (or a case like वाघत् (vāghát)) with nom.s. 'júhvat', acc.s. 'júhvatam', etc.

...


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_decl_data = require("Module:sa-decl/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 sub = mw.ustring.sub
local gsub = mw.ustring.gsub
local match = mw.ustring.match
local len = mw.ustring.len

local accent = '[/\\]'

local genders = {
	m = 'Masculine', f = 'Feminine', n = 'Neuter',
}
local cases = {
	{ 'nom', 'nominative' }, { 'voc', 'vocative' }, { 'acc', 'accusative' }, { 'ins', 'instrumental' },
	{ 'dat', 'dative' }, { 'abl', 'ablative' }, { 'gen', 'genitive' }, { 'loc', 'locative' },
}

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, sc_cache)
	local width = '40'
	local title = genders[args.g] .. ' ' .. ' ' .. data.decl_type .. ' declension of ' ..
		m_links.full_link({ term = nil, alt = sc_cache.reverse_tr(args.lemma), tr = "-", lang = lang, sc = sc_cache.sc })

	local header = { mw.getCurrentFrame():expandTemplate {
		title = 'inflection-table-top',
		args = {
			title = title,
			palette = 'blue',
			tall = 'yes',
		}
	} }
	table.insert(header, '!\n')

	if args.n == 'sdp' then
		table.insert(header, '! singular\n')
		table.insert(header, '! dual\n')
		table.insert(header, '! plural\n')
	elseif args.n == 's' then
		table.insert(header, '! singular\n')
	elseif args.n == 'd' then
		table.insert(header, '! dual\n')
	elseif args.n == 'p' then
		table.insert(header, '! plural\n')
	end
	return table.concat(header)
end

local function make_cell(args, data, code, num, sc_cache)
	local tag = code .. '_' .. num
	local forms, links, trs = {}, {}, {}
	if args[tag] then
		forms = mw.text.split(sc_cache.tr(args[tag]), '%s*[,]%s*')
	else
		forms = data.forms[tag]
	end

	if not forms then
		error("Internal error: No forms for slot '" .. tag .. "'")
	end
	for i, form in ipairs(forms) do
		if form == "" then -- in case of form reduced to zero by 'novedic' parameter
			-- do nothing
		else
			local form_note_tag = get_form_note_tags(forms['note' .. i] or {}, data)
			-- a superscript number at the end of manually added forms should not be part of the (linked) form
			if match(form, "[¹²³⁴⁵⁶⁷⁸⁹]$") then
				extra_note_tag = gsub(form, "^.+(.)$", "%1")
				form = gsub(form, ".$", "")
			else
				extra_note_tag = ""
			end

			if form == "-" then
				table.insert(links, m_links.full_link({ term = nil, alt = '-', lang = lang, sc = sc_cache.sc }))
			else
				table.insert(links,
					m_links.full_link({
						term = sc_cache.reverse_tr(form),
						alt = sc_cache.reverse_tr(form) .. form_note_tag .. extra_note_tag,
						tr = SLP_to_IAST.tr(form) .. form_note_tag .. extra_note_tag,
						lang = lang,
						sc = sc_cache.sc
					}))
			end
		end
	end

	return table.concat {
		'| ',
		table.concat(links, '<br>'),
		'\n'
	}
end

local function format_notes(args, data)
	local output = {}
	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_table_noun(args, data, sc_cache)
	local output = { make_header(args, data, sc_cache) }
	for _, case in ipairs(cases) do
		local code, name = case[1], case[2]
		table.insert(output, '|-\n')
		table.insert(output, '! ' .. name .. '\n')
		if args.n == 'sdp' then
			table.insert(output, make_cell(args, data, code, 's', sc_cache))
			table.insert(output, make_cell(args, data, code, 'd', sc_cache))
			table.insert(output, make_cell(args, data, code, 'p', sc_cache))
		elseif args.n == 's' then
			table.insert(output, make_cell(args, data, code, 's', sc_cache))
		elseif args.n == 'd' then
			table.insert(output, make_cell(args, data, code, 'd', sc_cache))
		elseif args.n == 'p' then
			table.insert(output, make_cell(args, data, code, 'p', sc_cache))
		end
	end
	table.insert(output, mw.getCurrentFrame():expandTemplate {
		title = 'inflection-table-bottom',
		args = {
			notes = format_notes(args, data)
		}
	})
	if not args.nocat and #data.categories > 0 then
		table.insert(output, m_utils.format_categories(data.categories, lang))
	end
	return table.concat(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.')
			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

function export.show(frame)
	local params = {
		lemma = { default = PAGENAME },
		decl = { default = nil },
		n = { default = 'sdp' },
		sc = {},
		[1] = { alias_of = 'lemma' },
		nom_s = {},
		nom_d = {},
		nom_p = {},
		acc_s = {},
		acc_d = {},
		acc_p = {},
		ins_s = {},
		ins_d = {},
		ins_p = {},
		dat_s = {},
		dat_d = {},
		dat_p = {},
		abl_s = {},
		abl_d = {},
		abl_p = {},
		gen_s = {},
		gen_d = {},
		gen_p = {},
		loc_s = {},
		loc_d = {},
		loc_p = {},
		voc_s = {},
		voc_d = {},
		voc_p = {},
		note = { list = true },
		root = { type = 'boolean' },
		compound = { type = 'boolean' },
		pronominal = { type = 'boolean' },         -- use pronominal declension, e.g. for 'sarva'
		novedic = { default = false, type = "boolean" }, -- disable extra Vedic forms
		r_stem_a = {},
		at_nom_s = { type = 'boolean' },
		ambig_final = {},            -- for stems on -j, -ś or -h
		diaspirate = { type = 'boolean' }, -- for diaspirate roots like 'duh'
		participle = { type = 'boolean' },
		contract = { type = 'boolean' },
		adj = { type = 'boolean' }, -- internal argument for categorizing adjectives
		nocat = {},
	}
	local data = {
		forms = {},
		categories = {},
		decl_type = nil,
		form_notes = {},
		form_notes_out = {},
		general_notes = {},
	}
	local args = m_para.process(frame:getParent().args, params)
	args.g = frame.args[1]
	if args.pronominal then
		args.root = false -- the pronominal endings override the usual declension pattern
	end

	local sc_cache = get_sc_details(args)

	args.lemma = sc_cache.tr(args.lemma)
	args.has_accent = match(args.lemma, accent)

	if args.decl == nil then
		for decl, decl_data in pairs(sa_decl_data) do
			if decl_data.detect(args) then
				sa_decl_data[decl](args, data)
				break
			end
		end
	end
	if data.decl_type == nil then
		error("No declension class could be detected. Please check the lemma form or specify the declension.")
	end

	return make_table_noun(args, data, sc_cache)
end

return export