Module:sjd-decl
Jump to navigation
Jump to search
- This module lacks a documentation subpage. Please create it.
- Useful links: subpage list • links • transclusions • testcases • sandbox
local export = {}
local vowels = "аӓеёиоуыҍэӭюя"
local macron = mw.ustring.char(0x0304)
-- also includes digraphs for monophthongs, despite its name
local diphthongs = {
"оа", "ёа",
"оа̄", "ёа̄",
"уэ", "уа",
}
-- e.g. ьэ => е
local fusion = {
["ьэ"] = "е", ["ьа"] = "я",
["ҍэ"] = "ӭ", ["ҍа"] = "ӓ",
["йэ"] = "е", ["йа"] = "я",
["чэ"] = "че",
-- remove redundant palatal markers
["ьи"] = "и", ["ҍи"] = "и",
["ье"] = "е", ["ҍӭ"] = "ӭ",
["ья"] = "я", ["ҍӓ"] = "ӓ",
["ьё"] = "ё", ["ҍё"] = "ё",
["ью"] = "ю", ["ҍю"] = "ю",
}
-- e.g. a word ending is е is actually ь + э
local fission = {
["е"] = { "ь", "э" },
["я"] = { "ь", "а" },
["ӭ"] = { "ҍ", "э" },
["ӓ"] = { "ҍ", "а" },
}
-- precomposed Unicode macrons (i.e. ones that don't require a separate combining macron codepoint)
local macrons = {
["ӣ"] = "и",
["ӯ"] = "у",
}
local macroned = ""
local macroned_reverse = ""
local macrons_with_macron = {}
local macrons_reversed = {}
for k, v in pairs(macrons) do
macroned = macroned .. k
macroned_reverse = macroned_reverse .. v
macrons_reversed[v .. macron] = k
macrons_with_macron[k] = v .. macron
end
local diphthongs_by_final = {}
for _, v in ipairs(diphthongs) do
local a, b = mw.ustring.sub(v, 1, 1), mw.ustring.sub(v, 2)
diphthongs_by_final[b] = (diphthongs_by_final[b] or "") .. a
end
local function extract(word, ending)
if mw.ustring.match(word, ending .. "$") then
return mw.ustring.match(word, "(.*)" .. ending .. "$")
end
error("Unexpected ending for this inflection type! Wrong type?")
end
local function extract_final_vowel(word)
local stem, vowel, macron = extract(word, "([" .. vowels .. "])(" .. macron .. "?)")
if diphthongs_by_final[vowel .. macron] and mw.ustring.match(stem, "[" .. diphthongs_by_final[vowel .. macron] .. "]$") then
vowel = mw.ustring.sub(stem, -1, -1) .. vowel .. macron
stem = mw.ustring.sub(stem, 1, -2)
end
if fission[vowel] then
local stem_extra
stem_extra, vowel = unpack(fission[vowel])
stem = stem .. stem_extra
end
if vowel == "оа̄" then vowel = "оа" end
if vowel == "ёа̄" then vowel = "ёа" end
return stem, vowel .. macron
end
local function decompose_macrons(word)
return mw.ustring.gsub(word, "[" .. macroned .. "]", macrons_with_macron)
end
local function recompose_macrons(word)
return mw.ustring.gsub(word, "[" .. macroned_reverse .. "]" .. macron, macrons_reversed)
end
local function join(...)
local t = {}
for _, s in ipairs(arg) do
if type(s) == "table" then
for _, v in ipairs(s) do
table.insert(t, v)
end
else
table.insert(t, s)
end
end
return t
end
local function append(t, x)
if not x then return t end
if type(t) == "string" then
return t .. x
end
local r = {}
for _, v in ipairs(t) do
table.insert(r, v .. x)
end
return r
end
local function append_smart(t, x)
if not x then return t end
if type(t) == "string" then
local key = mw.ustring.sub(t, -1, -1) .. mw.ustring.sub(x, 1, 1)
if fusion[key] then
return mw.ustring.sub(t, 1, -2) .. fusion[key] .. mw.ustring.sub(x, 2)
else
return t .. x
end
end
local r = {}
for _, v in ipairs(t) do
table.insert(r, append_smart(v, x))
end
return r
end
local function strip_final_vowel(t)
if type(t) == "string" then
return mw.ustring.gsub(t, "[" .. vowels .. "]+$", "")
end
local r = {}
for _, v in ipairs(t) do
table.insert(r, strip_final_vowel(v))
end
return r
end
local function make_gradation(s, w)
if s == w then
return "no gradation"
else
return s .. "-" .. w .. " gradation"
end
end
local function process(data, result, vh)
local vh = data.vh
-- genitive singular/plural stem
local gs = result.stem_gs
local gp = result.stem_gp
-- illative singular stem
local is = result.stem_is
-- locative singular stem
local ls = result.stem_ls or gs
-- comitative singular stem
local cs = result.stem_cs or gp
-- essive stem
local es = result.stem_es or data.title
-- abessive singular stem
local as = result.stem_as or gs
-- partitive singular stem
local pt = result.stem_as or gs
if not data.no_singular then
result["nom_sg"] = { data.title }
result["gen_sg"] = gs
result["ill_sg"] = is
result["loc_sg"] = append_smart(ls, "сьт")
result["com_sg"] = append_smart(cs, "нҍ")
result["abe_sg"] = result.strong_abessive and append_smart(strip_final_vowel(es), "аһта") or append_smart(as, "ха")
result["ess"] = append_smart(es, "нҍ")
result["prt"] = result.strong_partitive and append_smart(is, "дтӭ") or es
end
if not data.no_plural then
result["nom_pl"] = gs
result["acc_pl"] = append_smart(gp, "тҍ")
result["gen_pl"] = gp
result["ill_pl"] = append_smart(gp, "тҍ")
result["loc_pl"] = append_smart(gp, "нҍ")
result["com_pl"] = append_smart(gp, "гуэйм")
result["abe_pl"] = append_smart(gp, "ха")
end
for k, v in pairs(result) do
if type(v) == "string" then
result[k] = recompose_macrons(v)
elseif type(v) == "table" then
for i = 1,#v do
v[i] = recompose_macrons(v[i])
end
end
end
return result
end
-- inflection classes begin
local inflections = {}
inflections["I"] = function (data)
local vowel_com = data.args[1] or error("must specify plural/comitative vowel")
local vowel_ill = data.args[2] or error("must specify illative vowel")
local strong = data.args[3] or error("must specify strong grade")
local weak = data.args[4] or error("must specify weak grade")
local ending_ill = data.args[5] or error("must specify illative ending")
local result = { typeno = (strong == weak and "II" or "I") }
local word = decompose_macrons(data.title)
local stem, vowel_nom
if data.no_singular then
stem = extract(word, weak)
else
stem = extract(word, strong)
end
stem, vowel_nom = extract_final_vowel(stem)
vowel_com = decompose_macrons(vowel_com)
vowel_ill = decompose_macrons(vowel_ill)
result.stem_gs = append_smart(stem, vowel_nom .. weak)
result.stem_ls = append_smart(append_smart(stem, vowel_nom .. weak), "э")
result.stem_es = append_smart(append_smart(stem, vowel_nom .. strong), "э")
result.stem_is = append_smart(stem, vowel_ill .. ending_ill)
result.stem_gp = append_smart(append_smart(stem, vowel_com .. weak), "э")
result.grade = make_gradation(strong, weak)
return process(data, result)
end
inflections["II"] = inflections["I"]
inflections["III"] = function (data)
local result = { typeno = "III" }
local word = decompose_macrons(data.title)
local stem, final_c = extract(word, "([^" .. vowels .. "]+)")
local final_v
stem, final_v = extract_final_vowel(stem)
local vowel_ill = data.args[1]
local final_palatal = ""
local stem_c = append_smart(stem, final_v .. final_c)
-- if mw.ustring.match(stem, "[ьҍ]$") then
-- stem, final_palatal = mw.ustring.sub(stem, 1, -2), mw.ustring.sub(stem, -1, -1)
-- end
-- local stem_v = stem .. final_c .. final_palatal
local stem_v = stem .. final_c
if not vowel_ill then
vowel_ill = (not mw.ustring.match(stem, "[ьҍ]$")) and fusion["ь" .. final_v] or final_v
end
result.stem_gs = stem_c
result.stem_is = append_smart(stem_v, vowel_ill)
result.stem_es = append_smart(stem_c, "э")
result.stem_as = stem_c
result.stem_gp = append_smart(stem_v, "э")
result.stem_ls = result.stem_gp
result.strong_partitive = true
return process(data, result)
end
inflections["IV"] = function (data)
local result = { typeno = "IV" }
local word = decompose_macrons(data.title)
local vowel_ill = data.args[1] or "е"
result.stem_gs = word
result.stem_is = append_smart(word, vowel_ill)
result.stem_ls = word
result.stem_as = word
result.stem_es = word
result.stem_gp = word
result.strong_abessive = true
result.strong_partitive = true
return process(data, result)
end
-- inflection classes end
local infl_table = [=[{| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="border:solid 1px #CCCCFF; text-align: left;" cellspacing="1" cellpadding="2"
|- style="background: #E2F6E2; text-align: left;"
! class="vsToggleElement" colspan="3" | Declension of {{{title}}} (<span style="font-size:90%">{{{type}}}</span>)
|- class="vsShow" style="background: #F2F2FF;"
! style="width: 10em; background: #E2F6E2;" | Nominative
| style="width: 15em;" colspan="2" | {{{nom_sg}}}
|- class="vsShow" style="background: #F2F2FF;"
! style="background: #E2F6E2;" | Genitive
| colspan="2" | {{{gen_sg}}}
|- class="vsHide"
! style="width: 10em; background:#c0e4c0" |
! style="width: 15em; background:#c0e4c0" | singular
! style="width: 15em; background:#c0e4c0" | plural
|- class="vsHide" style="background: #F2F2FF;"
! style="background: #E2F6E2;" | Nominative
| {{{nom_sg}}}
| {{{nom_pl}}}
|- class="vsHide" style="background: #F2F2FF;"
! style="background: #E2F6E2;" | Accusative
| {{{gen_sg}}}
| {{{acc_pl}}}
|- class="vsHide" style="background: #F2F2FF;"
! style="background: #E2F6E2;" | Genitive
| {{{gen_sg}}}
| {{{gen_pl}}}
|- class="vsHide" style="background: #F2F2FF;"
! style="background: #E2F6E2;" | Dative-Illative
| {{{ill_sg}}}
| {{{ill_pl}}}
|- class="vsHide" style="background: #F2F2FF;"
! style="background: #E2F6E2;" | Locative
| {{{loc_sg}}}
| {{{loc_pl}}}
|- class="vsHide" style="background: #F2F2FF;"
! style="background: #E2F6E2;" | Comitative
| {{{com_sg}}}
| {{{com_pl}}}
|- class="vsHide" style="background: #F2F2FF;"
! style="background: #E2F6E2;" | Abessive
| {{{abe_sg}}}
| {{{abe_pl}}}
|- class="vsHide" style="background: #F2F2FF;"
! style="background: #E2F6E2;" | Essive
| colspan="2" | {{{ess}}}
|- class="vsHide" style="background: #F2F2FF;"
! style="background: #E2F6E2;" | Partitive
| colspan="2" | {{{prt}}}
|}]=]
local function link(text)
return require("Module:links").full_link{ term = text, lang = require("Module:languages").getByCode("sjd") }
end
local function mention(text)
return require("Module:links").full_link({ term = text, lang = require("Module:languages").getByCode("sjd") }, "term")
end
function export.show(frame)
local infl_type = frame.args[1] or error("inflection class not specified")
local infl = inflections[infl_type] or error("unsupported inflection type")
local args = frame:getParent().args
local title = args["title"] or mw.title.getCurrentTitle().text
local data = { title = title, headword = headword, args = args }
if args["n"] then
if args["n"] == "s" or args["n"] == "sg" then
data.no_plural = true
elseif args["n"] == "p" or args["n"] == "pl" then
data.no_singular = true
end
end
local forms = infl(data)
local function repl(form)
if form == "title" then
return "'''" .. title .. "'''"
elseif form == "type" then
if forms.irregular then
return "irregular"
end
local s = "type " .. (forms.typeno or infl_type) .. " noun"
if forms.grade then
s = s .. ", " .. forms.grade
else
s = s .. ", " .. make_gradation(nil, nil)
end
return s
else
local value = forms[form]
if not value then
return "—"
elseif type(value) == "table" then
local result = {}
for _, f in ipairs(value) do
table.insert(result, link(f))
end
return table.concat(result, ", ")
else
return link(value)
end
end
end
local result = mw.ustring.gsub(infl_table, "{{{([a-z0-9_:]+)}}}", repl)
result = mw.ustring.gsub(result, "{{m|sjd|([^}]-)}}", mention)
return result
end
return export