local export = {}
local m_links = require("Module:links")
local m_utils = require("Module:utilities")
local decl_data = require("Module:iir-decl-noun/data")
local decl_data_irreg = require("Module:iir-decl-noun/data/irreg")
local lang = require("Module:languages").getByCode("iir-pro")
local endings = {
= "a-m", = "a-m", = "a-n", = "a-n",
= "aH-f", = "aH-f",
= "i-mf", = "i-mf", = "i-n",
= "yaH-f", = "yaH-f",
= "iH-f", = "iH-f",
= "u-mf", = "u-mf", = "u-n", = "u-n",
= "uH-f", = "uH-f",
}
local endings_reverse = {
= "ás", = "as", = "ám", = "am",
= "áH", = "aH",
= "íš", = "iš", = "íš", = "iš", = "íš", = "iš", = "i",
= "íH", = "iH",
= "íHs", = "iHs",
= "uš", = "uš", = "uš", = "u",
= "úHs", = "uHs",
= "ā́", = "ā",
= "",
}
local function detect_decl(word, stem, gender)
if stem and gender then
local decl = stem .. "-" .. gender
return decl, {mw.ustring.sub(word, 1, -(mw.ustring.len(endings_reverse) + 1))}
elseif stem == "r" and mw.ustring.sub(word, -2) == "ā́" then --r-stem
return "r-n", {mw.ustring.sub(word, 1, -3)}
elseif stem == "s" and mw.ustring.sub(word, -2) == "as" then
return "s-n", {mw.ustring.sub(word, 1, -3)}
elseif stem == "cons" then
if gender == "n" then return "cons-n"
else return "cons-mf" end
else
for ending, decl in pairs(endings) do
if mw.ustring.find(word, ending .. "$") then
return decl, {mw.ustring.sub(word, 1, -(mw.ustring.len(ending) + 1))}
end
end
-- No matches, assume consonant stem.
local stem
stem = mw.ustring.sub(word, 1, -2)
return (gender and "cons-" .. gender or "cons-mf"), {stem}
end
end
function syllabify(text)
-- Supposed to syllabify resonants when appropriate
if mw.ustring.find(text, "???") then
local pref, syllabic, suf = mw.ustring.match(text, "(?)(?)(?)")
syllabic = syllabic:gsub("u", "wa")
:gsub("", "a")
:gsub("w", "u")
:gsub("y", "i")
syllabic = mw.ustring.gsub(syllabic, "", { = "r̥", = "ŕ̥"})
local syllabified = pref .. syllabic .. suf
text = mw.ustring.gsub(text, "???", syllabified)
end
if mw.ustring.find(text, "iw?") then text = text:gsub("iw", "yu") end
if mw.ustring.find(text, "ŕ") then text = mw.ustring.gsub(text, "ŕ", "r") end
if mw.ustring.find(text, "?$") then
text = mw.ustring.gsub(text, "$", { = "u", = "i", = "r̥"})
end
return text
end
function ruki(text)
text = mw.ustring.gsub(text, "?ʰ?s", {
= "rš",
= "ŕ̥š",
= "wš",
= "uš",
= "kš",
= "ćš",
= "kš",
= "yš",
= "iš",
= "s",
= "š",
= "kš",
= "kš",
= "ćš",
= "ćš",
= "ts",
= "ts",
= "ps"
})
return text
end
function dorsal_b(text)
text = mw.ustring.gsub(text, "ʰ?b", "gb")
text = mw.ustring.gsub(text, "b", {
= "ȷ́b",
= "bb",
= "db",
= "zb",
= "žb"
})
return text
end
function destress(text)
-- Suppresses default ending accent if accent is detected on a preceding stem.
-- It does this by checking the provided form to see if it has two accents. If the form does have two accents, the rightmost accent is isolated and removed.
-- The little mark on ȷ́ is identical to the combining accent mark; it needs to be ignored during the accent check.
text = text:gsub("ȷ́", "ȷ")
if mw.ustring.find(text, ".+") then
local initial, final = mw.ustring.match(text, "^(.-)(.*)")
final = mw.ustring.gsub(final, "", { = "a", = "i", = "u", = "r", = ""})
text = initial .. final
end
-- Readd accent mark to the resulting dotless J after the accent check
text = text:gsub("ȷ", "ȷ́")
return text
end
function vocstem(stem)
-- Enforces first-syllable accent in vocatives.
-- It does this by checking to see if a form has no accent.
-- Vocatives in the data submodule specifically have no accent specified on their endings, so unaccented stem + unaccented ending = unaccented word.
-- If there is no accent, the function parks the accent on the first available vowel.
local vocstem
if not mw.ustring.find(stem, "")
then
if mw.ustring.find(stem, "^-r̥") then
local pref, suf = mw.ustring.match(stem, "^(-r̥)(.+)")
pref = mw.ustring.gsub(pref, "r̥$", "ŕ̥")
vocstem = pref .. suf
else
local pref, firstvowel, suf = mw.ustring.match(stem, "^(.-)()(.*)")
firstvowel = mw.ustring.gsub(firstvowel, "", { = "á", = "ā́", = "í", = "ú"})
vocstem = pref .. firstvowel .. suf
end
else vocstem = stem
end
return vocstem
end
-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
local parent_args = frame:getParent().args
local stems = nil
local decl_type = {}
local word = mw.title.getCurrentTitle().subpageText
local args = {}
if not decl_data_irreg then
if frame.args.decl then
decl_type = frame.args.decl
else
if parent_args.stem and parent_args.g and parent_args then
decl_type = parent_args.stem .. "-" .. parent_args.g
stems = {parent_args}
elseif parent_args and not parent_args.stem then
decl_type = detect_decl(word, parent_args.stem, parent_args.g)
stems = {parent_args}
else
decl_type, stems = detect_decl(word, parent_args.stem, parent_args.g)
end
end
if not decl_type then
error("Unknown declension '" .. decl_type .. "'")
end
args = require("Module:parameters").process(parent_args, decl_data.params, true)
if stems then
for i, stem in ipairs(stems) do
args = stem
end
end
end
local data = {forms = {}, categories = {}}
data.head = parent_args or nil
-- Generate the forms
if decl_data_irreg then
table.insert(data.categories, "Proto-Indo-Iranian irregular nouns")
decl_data_irreg(parent_args, data)
else
decl_data(args, data)
end
-- Make the table
return make_table(data)
end
function make_table(data)
local function show_form(form)
if not form then
return "—"
end
local ret = {}
for key, subform in ipairs(form) do
if subform ~= "—" then
-- Post-processing of data
subform = syllabify(subform)
subform = ruki(subform)
subform = dorsal_b(subform)
subform = vocstem(subform)
subform = destress(subform)
subform = "*" .. subform
end
table.insert(ret, subform)
end
return table.concat(ret, ", ")
end
local function repl(param)
if param == "decl_type" then
return data.decl_type
elseif param == "title" then
return "*" .. data.forms.nom_sg
else
return show_form(data.forms)
end
end
local function make_cases(data)
local cases = {"nominative", "vocative", "accusative", "instrumental", "ablative", "dative", "genitive", "locative"}
local ret = {}
for _, case in ipairs(cases) do
local case_short = mw.ustring.sub(case, 1, 3)
-- assert(false, case_short)
table.insert(ret, "|- " .. ((case_short == "nom" or case_short == "gen") and "" or "class=\"vsHide\"") .. " \n! style=\"background: #DBEDFF\" | " .. case .. "\n")
table.insert(ret, "| style=\"background: #ECF5FF\" | " .. show_form(data.forms) .. "\n")
table.insert(ret, "| class=\"vsHide\" style=\"background: #ECF5FF\" | " .. show_form(data.forms) .. "\n")
if data.forms then
table.insert(ret, "| class=\"vsHide\" style=\"background: #ECF5FF\" | " .. show_form(data.forms) .. "\n")
end
end
return table.concat(ret)
end
local no_plural = data.forms.nom_pl == nil
local wikicode = [=[
{| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="background: #F8FBff; border: 1px solid #d0d0d0; text-align: left;" cellspacing="1" cellpadding="2"
|-
! style="background: #B5D9FF;" class="vsToggleElement" colspan="]=] .. (no_plural and "3" or "4") .. [=[" | {{{decl_type}}}
|-
| style="min-width: 8em; background-color:#B5D9FF" |
! style="min-width: 11em; background-color:#B5D9FF" | singular
! class="vsHide" style="min-width: 11em; background-color:#B5D9FF" | dual]=] .. (no_plural and "\n" or [=[
! class="vsHide" style="min-width: 11em; background-color:#B5D9FF" | plural
]=]) .. make_cases(data) .. [=[
|}]=]
return (mw.ustring.gsub(wikicode, "{{{(+)}}}", repl)) .. m_utils.format_categories(data.categories, lang)
end
return export