local export = {}
local m_links = require("Module:links")
local m_utils = require("Module:utilities")
local decl_data = require("Module:ira-decl-noun/data")
local decl_data_irreg = require("Module:ira-decl-noun/data/irreg")
local lang = require("Module:languages").getByCode("ira-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 = {
= "áh", = "ah", = "á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) == "ah" 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("", "a")
:gsub("w", "u")
:gsub("y", "i")
:gsub("ua", "wa")
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, "?", {
= "rš",
= "ŕ̥š",
= "wš",
= "uš",
= "xš",
= "xš",
= "cš",
= "xš",
= "yš",
= "iš",
= "s",
= "š",
= "xš",
= "xš",
= "cš",
= "cš",
= "ts",
= "ts",
= "fš",
= "fš",
= "fš",
= "h",
})
return text
end
function lenite(text)
text = mw.ustring.gsub(text, "p()", "f%1")
text = mw.ustring.gsub(text, "t()", "θ%1")
text = mw.ustring.gsub(text, "k()", "x%1")
text = mw.ustring.gsub(text, "r̥", {
= "pr̥",
= "tr̥",
= "kr̥",
})
text = string.gsub(text, "sθ", "st")
return text
end
function dorsal_b(text)
text = mw.ustring.gsub(text, "ʰ?b", "gb")
text = mw.ustring.gsub(text, "b", {
= "jb",
= "bb",
= "db",
= "ž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.
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
-- Suppress default ending stress if the page name has no stress specified
local word = mw.title.getCurrentTitle().subpageText
if not mw.ustring.find(word, "") then
text = mw.ustring.gsub(text, "", { = "a", = "i", = "u", = "r", = ""})
end
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-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 = lenite(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: #E9F4FF\" | " .. case .. "\n")
table.insert(ret, "| style=\"background: #F4F9FF\" | " .. show_form(data.forms) .. "\n")
table.insert(ret, "| class=\"vsHide\" style=\"background: #F4F9FF\" | " .. show_form(data.forms) .. "\n")
if data.forms then
table.insert(ret, "| class=\"vsHide\" style=\"background: #F4F9FF\" | " .. 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: #FBFDFF; border: 1px solid #d0d0d0; text-align: left;" cellspacing="1" cellpadding="2"
|-
! style="background: #D4E9FF;" class="vsToggleElement" colspan="]=] .. (no_plural and "3" or "4") .. [=[" | {{{decl_type}}}
|-
| style="min-width: 8em; background-color:#D3E8FF" |
! style="min-width: 11em; background-color:#D3E8FF" | singular
! class="vsHide" style="min-width: 11em; background-color:#D3E8FF" | dual]=] .. (no_plural and "\n" or [=[
! class="vsHide" style="min-width: 11em; background-color:#D3E8FF" | plural
]=]) .. make_cases(data) .. [=[
|}]=]
return (mw.ustring.gsub(wikicode, "{{{(+)}}}", repl)) .. m_utils.format_categories(data.categories, lang)
end
return export