Module:sla-noun
Jump to navigation
Jump to search
- The following documentation is located at Module:sla-noun/documentation. [edit] Categories were auto-generated by Module:module categorization. [edit]
- Useful links: subpage list • links • transclusions • testcases • sandbox
This module is used to create declensional tables for Proto-Slavic nouns.
local m_utilities = require("Module:utilities")
local com = require("Module:sla-common")
local export = {}
local lang = require("Module:languages").getByCode("sla-pro")
local rfind = mw.ustring.find
local rsubn = mw.ustring.gsub
local rmatch = mw.ustring.match
local rsplit = mw.text.split
local ulower = mw.ustring.lower
local uupper = mw.ustring.upper
local usub = mw.ustring.sub
local ulen = mw.ustring.len
local ugmatch = mw.ustring.gmatch
function export.show(frame)
local SUBPAGENAME = mw.title.getCurrentTitle().subpageText
local params = {
[1] = {alias_of = 'recons'},
recons = {default = SUBPAGENAME},
n = {default = "sdp"},
ap = {},
g = {},
stem = {},
}
local args = require("Module:parameters").process(frame:getParent().args, params)
local gender = args["g"]
local ap = args["ap"]
local nom_sg = com.canon_decompose(args["recons"])
local unom_sg = (lang:makeEntryName(nom_sg))
local stem, desinence = com.auto_accent_and_check_accents(nom_sg, ap)
local ustem, _ = com.split_stem_desinence(unom_sg)
local num = {}
if not args.n or not rfind(args.n, "^s?d?p?$") then
error("Illegal number “" .. args.n .. "”. Possible values are “s”, “d”, “p”, “sd”, “dp”, “sp”, or “sdp”.")
else
num = rsplit(args.n, "")
end
if (nom_sg == "" or desinence == "") then
error("Error: SUBPAGENAME=" .. SUBPAGENAME .. "Must only be used in the Reconstruction namespace with " .. lang:getCanonicalName() .. " reconstructions")
end
local stem_type = get_stem(args["stem"], desinence, gender, unom_sg)
if stem_type == "soft a-stem" and desinence=="i" then -- ī-stem +j/+ьj (Module:sla-noun/data declensions["soft a-stem"] doesn't let check data.args["stem"], for some reason #data.args==0)
stem = ( args["stem"] and args["stem"]=="ī/ьj" and ustem.."ьj" or com.iotate(ustem) )
end
if ap and ap ~= "a" and ap ~= "b" and ap ~= "c" then
error("Accent paradigm “" .. ap .. "” must be either “a”, “b”, or “c”")
end
local forms, title, extracats
local categories = {}
local data = {
args = args,
gender = gender,
desinence = desinence,
ap = ap,
nom_sg = nom_sg,
unom_sg = unom_sg, -- only used for *mati/*dъťi?
stem = stem,
ustem = ustem,
footnotes = {},
footnote_to_sym = {},
next_notesym = "*"
}
local declensions = require("Module:sla-noun/data")
if declensions[stem_type] then
forms, title, extracats = declensions[stem_type](data)
else
error("Internal error -- unrecognized internal stem type '" .. stem_type .. "'")
end
if extracats then
for _, cat in ipairs(extracats) do
table.insert(categories, lang:getCanonicalName() .. " " .. cat)
end
end
table.insert(categories, 1, lang:getCanonicalName() .. " " .. title .. " nouns")
if ap then
title = title .. ", accent paradigm " .. ap
table.insert(categories, lang:getCanonicalName() .. " nominals with accent paradigm " .. ap)
end
if #num == 1 then
if num[1] == 's' then
title = title .. ', uncountable'
table.insert(categories, lang:getCanonicalName() .. " singularia tantum")
elseif num[1] == 'p' then
title = title .. ', plural only'
table.insert(categories, lang:getCanonicalName() .. " pluralia tantum")
end
end
return make_table(forms, num, title, data.footnotes) .. m_utilities.format_categories(categories, lang)
end
function get_stem(st, desinence, gender, unom_sg)
if st then -- explicitly specified stem
if st == "o" then
if "ъ" == desinence then
return "hard masculine o-stem"
elseif "ь" == desinence then
return "soft masculine o-stem"
elseif "o" == desinence then
return "hard neuter o-stem"
elseif "e" == desinence then
return "soft neuter o-stem"
else
error("Unrecognized ending for o-stem")
end
elseif st == "a" then
if "a" ~= desinence then
error("Unrecognized ending for a-stem")
end
if rfind(unom_sg, "[cčďjľňřšťž]a$") or rfind(unom_sg, "dza$") then
return "soft a-stem"
else
return "hard a-stem"
end
elseif st == "i" then
if "ь" ~= desinence then
error("Unrecognized ending for i-stem")
end
if gender == "m" then
return "masculine i-stem"
elseif gender == "f" then
return "feminine i-stem"
else
error("Gender for i-stems must be specified through g= parameter, as \"m\" or \"f\"")
end
elseif st == "ī" or st=="ī/ьj" or st=="ī/j" then
if "i" ~= desinence then
error("Unrecognized ending for ī-stem")
end
return "soft a-stem" -- FIXME, remove this hack
--consonant stems have several names in the literature, we handle all so that editors don't have to remember which one Wiktionary prefers
elseif st == "n" then
return "n-stem"
elseif st == "nt" or st == "t" then
return "nt-stem"
elseif st == "r" then
return "r-stem"
elseif st == "s" then
return "s-stem"
elseif st == "u" then
return "u-stem"
elseif st == "v" or st == "ū" or st == "ъv" then
return "v-stem"
else
error("Unrecognized stem class " .. st)
end
-- Autodetect common stem types on the basis of desinence, preceding
-- consonant, and passed arguments (g=).
-- hard masculine o-stems always and in -ъ, and we skip u-stems (which have stem= parameter provided)
elseif "ъ" == desinence then
return "hard masculine o-stem"
-- soft masculine o-stems end in ь and are preceded by a soft, palatal consonant, except for such i-stems which will
-- always have g= parameter specified
elseif "ь" == desinence and not gender and (rfind(unom_sg, "[cčďjľňřšťž]ь$") or rfind(unom_sg, "dzь$")) then
return "soft masculine o-stem"
-- hard neuter o-stems always end in -o, and we skip s-stems in -o (which have stem= parameter provided)
elseif "o" == desinence then
return "hard neuter o-stem"
-- soft neuter o-stems always end in -e and are preceded by a soft, platal consonant, and we skip s-stems in -e
-- (which have stem= parameter provided)
elseif "e" == desinence and rfind(unom_sg, "[cčďjľňřšťž]e$") then
return "soft neuter o-stem"
-- soft a-stems are feminines and masculines (OCS junoša) that and in -a and are preceded by a soft, palatal consonant, or
-- in -i (except for words *mati and *dъťi which are handled as r-stems)
elseif ( "a" == desinence and ( rfind(unom_sg, "[cčďjľňřšťž]a$") or rfind(unom_sg, "dza$") ) )
or
( ("i" == desinence) and (unom_sg ~= "mati") and (unom_sg ~= "dъťi") ) then
return "soft a-stem"
-- hard a-stems are the ones that are not soft a-stems
elseif "a" == desinence then
return "hard a-stem"
-- i-stems ending in -ь preceded by a hard, non-palatal consonant. Gender is mandatory to distinguish between masculine and
-- feminine inflection. We skip n-stems (having stem= parameter specified), which are handled below.
elseif "ь" == desinence then
if gender == "m" then
return "masculine i-stem"
elseif gender == "f" then
return "feminine i-stem"
else
error("Gender for i-stems must be specified through g= parameter, as “m” or “f”")
end
-- in case of r-stems, there are only two nouns, so the stem= parameter might as well be superfluous
elseif (unom_sg == "mati") or (unom_sg == "dъťi") then
return "r-stem"
else
error("Unable to autodetect stem type; must specify stem=, per [[WT:ASLA]]")
end
end
local number_map = {
s = "singular",
d = "dual",
p = "plural",
}
local case_map = {
nom = "'''nominative'''",
acc = "'''accusative'''",
gen = "'''genitive'''",
loc = "'''locative'''",
dat = "'''dative'''",
ins = "'''instrumental'''",
voc = "'''vocative'''",
}
function make_header(forms, num, title)
local lemma = forms.nom[num[1]]
if type(lemma) ~= "table" then
-- lemma remains
elseif lemma.notesym then
lemma = lemma[1]
else
local lemmavals = {}
for _, item in ipairs(lemma) do
if type(item) == "table" then
table.insert(lemmavals, com.link_form(item[1]))
else
table.insert(lemmavals, com.link_form(item))
end
end
lemma = table.concat(lemmavals, ", ")
end
local header = {
'<div class="NavFrame" style="max-width: ' .. (13 * (1 + #num)) .. 'em">',
'<div class="NavHead" style="background:#eff7ff">[[Template:sla-decl-noun|Declension]] of '
.. lemma .. (title and " (" .. title .. ")" or "") .. '</div>',
'<div class="NavContent">',
'{| class="inflection-table" style="width: 100%; background: #F9F9F9; text-align: center"',
'|-',
'| style="width:15%; background: #d9ebff" |',
}
for _, n in ipairs(num) do
table.insert(header, '! style="width: ' .. math.floor(100 / (1 + #num)) .. '%; background: #d9ebff;" | ' .. number_map[n])
end
return table.concat(header, "\n")
end
function make_row(forms, num, case)
local row = {
"|-",
"| style=\"background-color: #eff7ff;\" | " .. case_map[case] .. ""
}
for _, n in ipairs(num) do
table.insert(row, "| " .. com.link_form(forms[case][n]))
end
return table.concat(row, "\n")
end
function make_footer(footnotes)
local footnote_text = (#footnotes > 0) and [===[
<div style="width:100%;text-align:left;background:#e4f1ff">
<div style="display:inline-block;text-align:left;padding-left:1em;padding-right:1em">
]===] .. table.concat(footnotes, "<br />") .. [===[
</div></div>
]===] or ""
return "|}\n" .. footnote_text .. "</div></div>"
end
-- Make the table
function make_table(forms, num, title, footnotes)
return table.concat(
{
make_header(forms, num, title),
make_row(forms, num, "nom"),
make_row(forms, num, "gen"),
make_row(forms, num, "dat"),
make_row(forms, num, "acc"),
make_row(forms, num, "ins"),
make_row(forms, num, "loc"),
make_row(forms, num, "voc"),
make_footer(footnotes),
},
"\n"
)
end
return export