Module:Pl-noun
local export = {}
local m_links = require('Module:links')
local m_adj = require('Module:pl-adj')
local m_g = require('Module:gender and number')
local lang = require("Module:languages").getByCode("pl")
-- local consonants = "[bcćdfghjklłmnńpqrsśtvwxzżź]";
-- case information
local cases = {
{ key = "nom"; en = "nominative"; pl = "mianownik (kto? co?)" },
{ key = "gen"; en = "genitive"; pl = "dopełniacz (kogo? czego?)" },
{ key = "dat"; en = "dative"; pl = "celownik (komu? czemu?)" },
{ key = "acc"; en = "accusative"; pl = "biernik (kogo? co?)" },
{ key = "ins"; en = "instrumental"; pl = "narzędnik (kim? czym?)" },
{ key = "loc"; en = "locative"; pl = "miejscownik (o kim? o czym?)" },
{ key = "voc"; en = "vocative"; pl = "wołacz (o!)" },
}
-- columns for normal nouns
local noun_cols = {
{ key = "s"; title = "singular" },
{ key = "p"; title = "plural" },
}
-- columns for Old Polish nouns
local noun_dual_cols = {
{ key = "s"; title = "singular" },
{ key = "d"; title = "dual" },
{ key = "p"; title = "plural" },
}
-- columns for pronouns
local pronoun_cols = {
{ key = "sm"; title = m_g.format_list({"m"}, lang) },
{ key = "sf"; title = m_g.format_list({"f"}, lang) },
{ key = "sn"; title = m_g.format_list({"n"}, lang) },
{ key = "pm"; title = m_g.format_list({"m-pr-p"}, lang) },
{ key = "po"; title = m_g.format_list({"np-p"}, lang) },
}
local altsep = "/"
function empty_item(text)
return (not text) or text == "" or text == "-" or text == "–" or text == "—"
end
-- add link markers, with links separated by any of splitchars
-- exported for use in testcases
-- normally the separator is altsep
function export.make_links(text, splitchars, title)
if not title then
title = mw.title.getCurrentTitle().fullText
end
if empty_item(text) then
return "—"
elseif not splitchars or splitchars == "" then
return ("[[%s#Pols|%s]]"):format(text, text)
else
items = {}
for word in mw.ustring.gmatch(text, "[^" .. splitchars .. "]+") do
if word == title then
table.insert(items, ("[[%s]]"):format(word))
else
table.insert(items, ("[[%s#Pols|%s]]"):format(word, word))
end
end
return table.concat(items, "/")
end
end
local function linkify_info(declinfo, splitchars, nolinks)
local linked = {}
local title = mw.title.getCurrentTitle().fullText
for k, v in pairs(declinfo) do
if v == title then
linked[k] = "[[" .. v .. "]]"
elseif nolinks then
linked[k] = v
else
linked[k] = export.make_links(v, splitchars, title)
end
end
return linked
end
local function nowiki_info(declinfo)
local nowikied = {}
for k, v in pairs(declinfo) do
nowikied[k] = mw.text.nowiki(v)
end
return nowikied
end
local function override_col_titles(heads, cols)
if not heads then
return cols or {}
end
local new_cols = {}
local index = 1
for word in mw.ustring.gmatch(heads, "[^,]+") do
if cols[index] then
table.insert(new_cols, { key = cols[index].key; title = word } )
else
table.insert(new_cols, { key = tostring(index); title = word } )
end
index = index + 1
end
for ci, col in ipairs(cols) do
if ci >= index then
table.insert(new_cols, cols[index])
end
end
return new_cols
end
local function normalize_tantum(pargs)
-- support "num" as fallback for "tantum" to match Latin templates
local tantum = pargs.tantum or pargs.num
if not tantum then
return nil
end
if tantum == "sg" then
tantum = "s"
elseif tantum == "pl" then
tantum = "p"
end
return tantum
end
local function guess_width(declinfo, cols)
local maxl = 0
for k, v in pairs(declinfo) do
local l = mw.ustring.len(mw.text.trim(v))
if maxl < l then
maxl = l
end
end
local width = math.floor(maxl * 0.78) -- number obtained by anecdotal evidence
width = (width < 10) and 10 or width
width = 9 + (width * #cols)
return width
end
-- generate the HTML code of an inflection table
-- each entry in heads must have "key" and "title"
local function make_table(declinfo, cols, preproc, width, title, tantum, nolinks)
local result = {}
if not cols or not cols[1] then
error("make_table: invalid cols parameter")
end
local lemma_key = cases[1].key .. cols[1].key
local lemma = m_links.remove_links(declinfo[lemma_key])
title = title or ('declension of <span class="Latn mention" lang="pl" xml:lang="pl">%s</span>'):format(lemma)
local emwidth = width or guess_width(declinfo, cols)
if preproc == "nowiki" then
declinfo = nowiki_info(declinfo)
elseif preproc == "linkify" then
declinfo = linkify_info(declinfo, altsep, nolinks)
end
if cols and (#cols > 0) then
table.insert(result, '|-\n! style="width: 8em;" |\n')
for i, col in ipairs(cols) do
table.insert(result, ('! scope="col" | %s\n'):format(col.title))
end
end
local maxl = 0
for i, case in ipairs(cases) do
table.insert(result, ('|-\n! title="%s" scope="row" | %s\n'):format(case.pl, case.en))
for _, col in ipairs(cols) do
local declkey = case.key .. col.key
local item = mw.text.trim(declinfo[declkey])
if empty_item(item) then
table.insert(result, '| —\n')
else
table.insert(result, ('| <span class="Latn" lang="pl" xml:lang="pl">%s</span>\n'):format(item))
end
end
end
local outtext = ([=[<div class="NavFrame inflection-table-noun" style="width: %uem">
<div class="NavHead">%s</div>
<div class="NavContent">
{| style="width: %uem; margin: 0;" class="wikitable inflection-table"
]=]):format(emwidth, title, emwidth) .. table.concat(result, "") .. "|}</div></div>"
if tantum == "s" then
outtext = outtext .. "[[Category:Polish singularia tantum]]"
elseif tantum == "p" then
outtext = outtext .. "[[Category:Polish pluralia tantum]]"
end
return outtext
end
local function get_mode()
local frame = mw.getCurrentFrame()
if mw.isSubsting() then
return 'subst'
elseif frame:getParent():getTitle() == mw.title.getCurrentTitle().fullText then
return 'demo'
else
return 'xclude'
end
end
local function make_table_from_pargs(pargs, cols, tantum)
local width = pargs.width and tonumber(pargs.width)
local declinfo = {}
if get_mode() == 'demo' then
if not cols then
cols = {
{ key = "1"; title = "column 1" },
{ key = "2"; title = "column 2" },
{ key = "3"; title = "column 3" },
}
end
for i = 1, 7 do
for j, col in ipairs(cols) do
local case_key = cases[i].key .. col.key
local argn = (i-1) * #cols + j
declinfo[case_key] = '{{{' .. case_key .. '| {{{' .. argn .. '}}} }}}'
end
end
return make_table(declinfo, cols, "nowiki", width, nil, nil, nil)
else
cols = override_col_titles(pargs.heads, cols or {})
for i = 1, 7 do
for j, col in ipairs(cols) do
local case_key = cases[i].key .. col.key
local argn = ((i-1) * #cols) + j
declinfo[case_key] = m_links.remove_links(mw.text.trim(pargs[case_key] or pargs[argn] or "-"))
end
end
return make_table(declinfo, cols, "linkify", pargs.width, pargs.title, normalize_tantum(pargs), pargs.nolinks)
end
end
-- Generate declension table for a singulare tantum with all forms passed explicitly as parameters
function export.template_decl_noun_sg(frame)
local pargs = frame:getParent().args
local cols = { noun_cols[1] }
return make_table_from_pargs(pargs, cols, "s")
end
-- Generate declension table for a plurale tantum with all forms passed explicitly as parameters
function export.template_decl_noun_pl(frame)
local pargs = frame:getParent().args
local cols = { noun_cols[2] }
return make_table_from_pargs(pargs, cols, "p")
end
-- Generate declension table for a regular noun with all forms passed explicitly as parameters
function export.template_decl_noun(frame)
local pargs = frame:getParent().args
return make_table_from_pargs(pargs, noun_cols, nil)
end
function export.template_decl_pronoun(frame)
local pargs = frame:getParent().args
return make_table_from_pargs(pargs, pronoun_cols, nil)
end
-- this probably belongs in a module for Old Polish (zlw-opl).
-- which reminds me: someone should write [[WT:AZLW-OPL]].
-- Generate declension table for a noun with dual number with all forms passed explicitly as parameters
function export.template_decl_noun_dual(frame)
local pargs = frame:getParent().args
return make_table_from_pargs(pargs, noun_dual_cols, nil)
end
function export.template_decl_generic(frame)
local pargs = frame:getParent().args
local heads = pargs.heads
if not heads then
if get_mode() == "demo" then
heads = "column 1,column 2"
else
error("No column headings defined!")
end
end
local cols = override_col_titles(heads, {})
return make_table_from_pargs(pargs, cols, nil)
end
-- -----------------------------------------------------------------------------
-- -----------------------------------------------------------------------------
-- ------------- Semi-automatic generation of inflected forms ------------------
-- -----------------------------------------------------------------------------
-- -----------------------------------------------------------------------------
local function nonempty(str)
if not str or str == "" then
return nil
else
return str
end
end
-- Generate a table contains true for each space-separated word in str
local function make_lookup_table(str)
local ret = {}
for i in mw.ustring.gmatch(str, "%a+") do
ret[i] = true
end
return ret
end
-- table that converts nominative soft endings to their genitive form
-- required for proper functioning of masc_common
local soft_ending_lookup = {
["ć"] = "ci";
["dź"] = "dzi";
["ń"] = "ni";
["ś"] = "si";
["ź"] = "zi";
}
-- Given a word and a lookup table of accepted endings,
-- split the word into a stem and an ending.
-- Ending is returned in genitive form, i.e. soft consonants
-- and digraphs such as ć, ś, dź are converted to midword
-- i-forms ci, si, dzi.
local function split_stem(word, lookup)
-- match the longest possible ending
local last, last_gen
local limit = math.min(mw.ustring.len(word), 5)
for i = -limit, -1 do
if not last_gen then
last = mw.ustring.sub(word, i)
if lookup[last] or soft_ending_lookup[last] then
last_gen = soft_ending_lookup[last] or last
end
end
end
if last_gen then
local stem = mw.ustring.sub(word, 1, -mw.ustring.len(last)-1)
return stem, last_gen
else
return nil, nil
end
end
local function check_split(stem, last)
if not stem then
error("nil stem encountered in declension pattern")
end
if not last then
error("nil ending encountered in declension pattern")
end
end
local function handle_overrides(pargs, declinfo, ovinfo)
-- process cases in order
local ret = {}
local singpl = { "s", "p" }
for i = 1, 14 do
local caseno = math.floor((i+1)/2)
local sp = 2 - (i % 2)
local case_key = cases[caseno].key .. singpl[sp]
if pargs[case_key] then
ret[case_key] = pargs[case_key]
if ovinfo[case_key] then
for dummy, v in pairs(ovinfo[case_key]) do
ret[v] = pargs[case_key]
end
end
elseif not ret[case_key] then
ret[case_key] = declinfo[case_key]
end
end
return ret
end
-- This table will hold patterns
local patterns = {}
-- -----------------------------------------------------------------------------
-- -------------------------- Masculine declension -----------------------------
-- -----------------------------------------------------------------------------
-- accepted masculine endings in genitive singular form
local masc_endings = make_lookup_table(
"acz b bi c ch ci ciec ciel cz d dz dzi dziec ek el eł f g giel h iec ieł ik j k kiel l ł m n ni niec p pi r rz rzeł " ..
"s si seł siec sł sm sn st sz t unek w wi x z zi ż zd zeł ziec zł zm zn")
-- common function for masculine declensions
local function masc_common(pattern, stem, last, gens_ending, noms_form, nomp_form, altgenp, explicit_stem)
-- verify that the word ending is supported
if not masc_endings[last] then
-- suppress module error on the template page
if not last or not mw.ustring.match(last, "^{{{") then
error("Unsupported word ending: " .. (last or "nil"))
end
end
local initial_last = last
-- nominative singular
local noms_lookup = { bi = "b"; ci = "ć"; dzi = "dź"; ni = "ń"; ["pi"] = "p"; si = "ś"; wi = "w"; zi = "ź"; }
if not noms_form then
noms_form = stem .. (noms_lookup[last] or last)
end
-- fix the only exceptions to -iec vowel elision
if last == "iec" and (stem == "w" or stem == "p") then
if not gens_ending and stem == "p" then
gens_ending = "a"
end
stem = stem .. "ie"
last = "c"
end
-- limited guessing of masculine inanimate endings here
-- personal and animate nouns (except for ''wół'') always have "a"
local gens_a = make_lookup_table("acz ciec ciel dzi dziec ek el eł iec ieł ik kiel giel ni niec seł siec rz rzeł zeł")
if not gens_ending then
if gens_a[last] then
gens_ending = "a"
else
gens_ending = "u"
end
end
-- handle the following things here:
-- regular vowel elisions
-- overlong endings used only for genitive singular guessing, e.g. acz, unek
-- x becoming ks in inflected forms
-- stem-final ó becoming o in inflected forms
local last_lookup = {
acz = "cz";
ciec = "c"; ciel = "l";
dziec = "c";
ek = "k"; el = "l"; ["eł"] = "ł";
iec = "c"; ["ieł"] = "ł"; ik = "k";
kiel = "l";
giel = "l";
niec = "c";
["rzeł"] = "ł";
["seł"] = "sł"; siec = "c";
unek = "k";
x = "s";
["zeł"] = "zł"; ziec = "c";
}
local stem_add = {
acz = "a";
ciec = "ć"; ciel = "cie";
dziec = "dź";
ik = "i";
kiel = "k";
giel = "g";
niec = "ń";
["rzeł"] = "r";
siec = "ś";
unek = "un";
x = "k";
ziec = "ź";
}
stem = stem .. (stem_add[last] or "")
last = last_lookup[last] or last
if mw.ustring.match(stem, "ó$") and not explicit_stem then
stem = mw.ustring.sub(stem, 1, -2) .. "o"
end
-- genitive singular
local gens_form = stem .. last .. gens_ending
-- accusative singular
local accs_form = (pattern == "m-in") and noms_form or gens_form
-- instrumental singular
local inss_form
if (last == "g") or (last == "k") then
inss_form = stem .. last .. "iem"
else
inss_form = stem .. last .. "em"
end
-- locative singular
local locs_lookup = {
b = "bie"; bi = "biu";
c = "cu"; ch = "chu"; ci = "ciu"; cz = "czu";
d = "dzie"; dz = "dzu"; dzi = "dziu";
f = "fie";
g = "gu";
h = "hu";
j = "ju";
k = "ku";
l = "lu"; ["ł"] = "le";
m = "mie";
n = "nie"; ni = "niu";
p = "pie"; ["pi"] = "piu";
r = "rze"; rz = "rzu";
s = "sie"; si = "siu"; ["sł"] = "śle"; sm = "śmie"; sn = "śnie";
st = "ście"; sz = "szu";
t = "cie";
w = "wie"; wi = "wiu";
z = "zie"; zd = "ździe"; zi = "ziu"; ["zł"] = "źle"; zm = "zmie";
zn = "źnie"; ["ż"] = "żu";
-- the -zm ending should not be palatalized, since it normally occurs
-- in borrowed nouns such as "marazm", "komunizm", "faszyzm"
}
local locs_form = stem .. (locs_lookup[last] or last)
-- vocative singular is the same as locative singular, with the exception of -iec
local vocs_form = locs_form
if pattern == "m-pr" and mw.ustring.match(initial_last, "iec$") then
vocs_form = stem .. "cze"
end
-- nominative plural
-- accusative and vocative plural are the same
if not nomp_form then
local nomp_e_ending = make_lookup_table("bi c ci cz dz dzi j l ni pi rz si sz wi zi ż")
if (last == "g") or (last == "k") then
nomp_form = stem .. last .. "i"
elseif nomp_e_ending[last] then
nomp_form = stem ..last .. "e"
else
nomp_form = stem .. last .. "y"
end
end
-- genitive plural
local genp_form
if mw.ustring.match(last, "i$") and (last ~= "pi") then
genp_form = stem .. last
elseif (last == "l") then
genp_form = stem .. last .. "i"
elseif (last == "j") then
genp_form = stem .. last .. "ów"
if not altgenp or (altgenp == "") then
altgenp = stem .. "i"
end
elseif (last == "cz") or (last == "rz") or (last == "sz") or (last == "ż") then
genp_form = stem .. last .. "y"
else
genp_form = stem .. last .. "ów"
end
if nonempty(altgenp) then
genp_form = genp_form .. "/" .. altgenp
end
-- accusative plural - same as genitive or nominative depending on animacy
local accp_form = (pattern == "m-pr") and genp_form or nomp_form
return {
noms = noms_form; nomp = nomp_form;
gens = gens_form; genp = genp_form;
dats = stem .. last .. "owi"; datp = stem .. last .. "om";
accs = accs_form; accp = accp_form;
inss = inss_form; insp = stem .. last .. "ami";
locs = locs_form; locp = stem .. last .. "ach";
vocs = vocs_form; vocp = nomp_form;
}
end
-- masculine inanimate nouns, e.g. bruk, beton, słup, szczaw, kurnik
-- default genitive singular ending is "u", but "a" endings are common as well
patterns["m-in"] = function (pargs, word)
local stem, last = split_stem(word, masc_endings)
local explicit_stem = false
if nonempty(pargs[2]) then
stem = pargs[1] or ""
last = pargs[2]
explicit_stem = true
end
local gens_ending = pargs[3] or gens_ending
local noms_form = nonempty(pargs[4])
local altgenp = nonempty(pargs[5])
local declinfo = masc_common("m-in", stem, last, gens_ending, noms_form,
nil, altgenp, explicit_stem)
return handle_overrides(pargs, declinfo,
{ noms = {"accs"}; locs = {"vocs"}; nomp = {"accp", "vocp"} })
end
-- masculine animate nouns, e.g. bocian, dzik, jeleń
patterns["m-an"] = function (pargs, word)
local stem, last = split_stem(word, masc_endings)
local explicit_stem = false
if nonempty(pargs[2]) then
stem = pargs[1] or ""
last = pargs[2]
explicit_stem = true
end
local noms_form = nonempty(pargs[3])
local altgenp = nonempty(pargs[4])
local declinfo = masc_common("m-an", stem, last, "a", noms_form,
nil, altgenp, explicit_stem)
return handle_overrides(pargs, declinfo,
{ gens = {"accs"}; locs = {"vocs"}; nomp = {"accp", "vocp"} })
end
-- masculine personal nouns, e.g. policjant, sknerus, polityk
patterns["m-pr"] = function (pargs, word)
if not pargs[1] and not pargs[2] then
if mw.ustring.match(word, "a$") then
return patterns["m-pr-a"](pargs, word)
elseif mw.ustring.match(word, "[yi]$") then
return patterns["m-pr-adj"](pargs, word)
elseif mw.ustring.match(word, "nin$") then
return patterns["m-pr-nin"](pargs, word)
end
end
local stem, last = split_stem(word, masc_endings)
local explicit_stem = false
if nonempty(pargs[2]) then
stem = pargs[1] or ""
last = pargs[2] or ""
explicit_stem = true
end
local nomp_form = nonempty(pargs[3]) or nonempty(pargs.nomp)
local noms_form = nonempty(pargs[4]) or nonempty(pargs.noms)
local altgenp = nonempty(pargs[5])
-- note: this is only a default, and will need to be overridden often
if not nomp_form then
nomp_lookup = {
acz = "acze"; -- palacz
ch = "chowie"; ci = "cie"; ciec = "ćcy"; cz = "cze";
ciel = "ciele"; -- eunuch, cieć, ?, ?, nauczyciel
d = "dzi", dziec = "dźcy"; -- kloszard, jeździec
ek = "kowie"; el = "ele"; -- świadek, ?
f = "fowie"; -- szeryf
g = "dzy"; -- szpieg
h = "howie"; -- druh
iec = "cy"; ik = "icy"; -- pogrobowiec, czytelnik
j = "je"; -- lokaj
k = "cy"; -- alkoholik
l = "le"; ["ł"] = "łowie"; -- ?, apostoł
m = "mi"; -- pielgrzym
n = "ni"; ni = "nie"; niec = "ńcy"; -- kompan, leń, jeniec
p = "pi"; -- chłop
r = "rzy"; rz = "rze"; -- konduktor, murarz
s = "si"; si = "sie"; siec = "ścy"; sz = "sze"; -- ordynans, rabuś, ?, jarosz
t = "ci"; -- policjant
z = "zi"; zi = "zie"; ziec = "źcy"; ["ż"] = "żowie"; -- intruz, kniaź, ?, mąż
}
if not nomp_lookup[last] then
error("Unsupported word ending: " .. last ..
"; please define the nominative plural form")
end
if last == "g" and mw.ustring.match(stem, "lo$") then
nomp_form = stem .. "dzy/" .. stem .. "gowie"
else
nomp_form = stem .. nomp_lookup[last]
end
end
local declinfo = masc_common("m-pr", stem, last, "a", noms_form,
nomp_form, altgenp, explicit_stem)
return handle_overrides(pargs, declinfo,
{ gens = {"accs"}; locs = {"vocs"}; nomp = {"vocp"}; genp = {"accp"} })
end
-- masculine personal nouns with adjectival declension
-- e.g. radny, łowczy, salowy
patterns["m-pr-adj"] = function (pargs, title)
local word = pargs[1] or title
if mw.ustring.match(word, "^{{{") then
word = "przykładowy"
end
local decl = m_adj.autoinflect(word)
local declinfo = {
noms = decl[1]; nomp = decl[4];
gens = decl[6]; genp = decl[8];
dats = decl[9]; datp = decl[10];
accs = decl[6]; accp = decl[8];
inss = decl[12]; insp = decl[13];
locs = decl[12]; locp = decl[8];
vocs = decl[1]; vocp = decl[4];
}
return handle_overrides(pargs, declinfo,
{ noms = {"vocs"}; gens = {"accs"}; nomp = {"vocp"}; genp = {"accp", "locp"} })
end
-- masculine personal nouns that end in -a
-- e.g. stażysta, dawca, banita
patterns["m-pr-a"] = function (pargs, word)
local word_no_a = mw.ustring.match(word, "^(.*)a$") or ""
local endings = make_lookup_table("b bi c ch d g j p r st t zd zn ż")
local stem, last = split_stem(word_no_a, endings)
stem = nonempty(pargs[1]) or stem
last = nonempty(pargs[2]) or last
if not endings[last] then
-- suppress module error on the template page
if not mw.ustring.match(last, "^{{{") then
error("Unsupported word ending: " .. last)
end
end
local gens_form = stem .. last .. "y"
if last == "j" then
gens_form = stem .. "i"
elseif last == "g" then
gens_form = stem .. "gi"
end
local dats_lookup = {
b = "bie"; -- Barnaba
bi = "bi";
c = "cy"; -- zdrajca
ch = "sze"; -- monarcha
d = "dzie"; -- nomada (?)
g = "dze"; -- sługa
j = "i"; -- kaznodzieja
p = "pie"; -- satrapa
r = "rze"; -- sknera
st = "ście"; -- starosta
t = "cie"; -- idiota
zd = "ździe"; -- gazda
zn = "źnie"; -- mężczyzna
["ż"] = "ży"; -- doża
}
local dats_form = stem .. (dats_lookup[last] or last)
local nomp_lookup = {
b = "bowie";
bi = "biowie";
c = "cy";
ch = "chowie";
d = "dzi";
g = "dzy";
j = "je";
p = "powie";
r = "rzy";
st = "ści";
t = "ci";
zd = "zdowie";
zn = "źni";
["ż"] = "żowie";
}
local nomp_form = stem .. (nomp_lookup[last] or (last .. "i"))
local genp_form = stem .. last .. "ów"
if last == "zn" then
genp_form = stem .. last
end
-- TODO: alternative adjectival declension for -bia
local declinfo = {
noms = stem .. last .. "a"; nomp = nomp_form;
gens = gens_form; genp = genp_form;
dats = dats_form; datp = stem .. last .. "om";
accs = stem .. last .. "ę"; accp = genp_form;
inss = stem .. last .. "ą"; insp = stem .. last .. "ami";
locs = dats_form; locp = stem .. last .. "ach";
vocs = stem .. last .. "o"; vocp = nomp_form;
}
return handle_overrides(pargs, declinfo,
{ dats = {"locs"}; nomp = {"vocp"}; genp = {"accp"} })
end
-- masculine nouns ending in -log, both personal and inanimate
-- inanimate form is chosen when the first parameter is empty
patterns["log"] = function (pargs, title)
local stem = nonempty(pargs[1]) or mw.ustring.match(title, "^(.*)log$") or ""
local nomp_form = nonempty(pargs[2])
local inanimate = not nonempty(pargs[1])
if not nomp_form then
if inanimate then
nomp_form = stem .. "logi"
else
nomp_form = stem .. "lodzy/" .. stem .. "logowie"
end
end
local gens_form = stem .. "loga"
if inanimate then
gens_form = stem .. "logu"
end
local accs_form = stem .. "loga"
if inanimate then
accs_form = stem .. "log"
end
local declinfo = {
noms = stem .. "log"; nomp = nomp_form;
gens = gens_form; genp = stem .. "logów";
dats = stem .. "logowi"; datp = stem .. "logom";
accs = accs_form; accp = stem .. "logów";
inss = stem .. "logiem"; insp = stem .. "logami";
locs = stem .. "logu"; locp = stem .. "logach";
vocs = stem .. "logu"; vocp = nomp_form;
}
return handle_overrides(pargs, declinfo,
{ locs = {"vocs"}; nomp = {"vocp"}; genp = {"accp"} })
end
-- masculine personal nouns ending with -nin, e.g. Rosjanin, łodzianin
-- popular for demonyms
patterns["m-pr-nin"] = function (pargs, word)
local stem = nonempty(pargs[1]) or mw.ustring.match(word, "^(.*)nin$")
local genp_ending = pargs[2] or "n"
local declinfo = {
noms = stem .. "nin"; nomp = stem .. "nie";
gens = stem .. "nina"; genp = stem .. genp_ending;
dats = stem .. "ninowi"; datp = stem .. "nom";
accs = stem .. "nina"; accp = stem .. genp_ending;
inss = stem .. "ninem"; insp = stem .. "nami";
locs = stem .. "ninie"; locp = stem .. "nach";
vocs = stem .. "ninie"; vocp = stem .. "nie";
}
return handle_overrides(pargs, declinfo,
{ gens = {"accs"}; locs = {"vocs"}; nomp = {"vocp"}; genp = {"accp"} })
end
-- masculine inanimate adjectives in noun phrases
patterns["adj-m-in"] = function (pargs, word)
word = nonempty(pargs[1]) or word
if mw.ustring.match(word, "^{{{") then
word = "przykładowy"
end
local decl = m_adj.autoinflect(word)
local declinfo = {
noms = decl[1]; nomp = decl[5];
gens = decl[6]; genp = decl[8];
dats = decl[9]; datp = decl[10];
accs = decl[1]; accp = decl[5];
inss = decl[12]; insp = decl[13];
locs = decl[12]; locp = decl[8];
vocs = decl[1]; vocp = decl[5];
}
return handle_overrides(pargs, declinfo,
{ noms = {"accs", "vocs"}; inss = {"locs"}; nomp = {"accp", "vocp"}; genp = {"locp"} })
end
-- masculine animate adjectives in noun phrases
patterns["adj-m-an"] = function (pargs, word)
word = nonempty(pargs[1]) or word
if mw.ustring.match(word, "^{{{") then
word = "przykładowy"
end
local decl = m_adj.autoinflect(word)
local declinfo = {
noms = decl[1]; nomp = decl[5];
gens = decl[6]; genp = decl[8];
dats = decl[9]; datp = decl[10];
accs = decl[6]; accp = decl[5];
inss = decl[12]; insp = decl[13];
locs = decl[12]; locp = decl[8];
vocs = decl[1]; vocp = decl[5];
}
return handle_overrides(pargs, declinfo,
{ noms = {"vocs"}; gens = {"accs"}; inss = {"locs"}; nomp = {"accp", "vocp"}; genp = {"locp"} })
end
-- masculine personal adjectives in noun phrases are identical
-- to masculine personal adjectival declension
-- -----------------------------------------------------------------------------
-- -------------------------- Feminine declension ------------------------------
-- -----------------------------------------------------------------------------
local fem_endings = make_lookup_table(
"b bi c ch ci cz d dz dzi dż f g h j k l ł m n ni p pi r rz " ..
"s si sł sm sn st sz t w wi z zd zi zł zm zn ż")
-- most feminine nouns ending in -a
-- note that some nouns ending in -ia have this declension and others
-- follow the "f-ia" pattern - it's impossible to tell from the word alone.
patterns["f"] = function (pargs, word)
-- to handle pluralia tantum as well
local word_no_a = mw.ustring.match(word, "^(.*)[aeiy]$")
local pars3 = pargs[1] and pargs[2] and pargs[3]
local nopars = not pargs[1] and not pargs[2] and not pargs[3]
-- 2 positional parameters given OR a at the and -> use a-final declension
-- 3+ positional parameters given OR consonant at the end -> use f-softcons
if nopars then
if mw.ustring.match(word, "ia$") then
native_ia = mw.ustring.match(word, "[bcdjklłrśtwzź]nia$")
native_ia = native_ia or mw.ustring.match(word, "[csz]ia$")
if not native_ia then
return patterns["f-ia"](pargs, word)
end
elseif mw.ustring.match(word, "ni$") then
return patterns["f-ni"](pargs, word)
end
end
if pars3 or not word_no_a then
return patterns["f-softcons"](pargs, word)
end
word_no_a = word_no_a or word
local stem, last = split_stem(word_no_a, fem_endings)
stem = nonempty(pargs[1]) or stem
last = nonempty(pargs[2]) or last
if not fem_endings[last] then
-- suppress module error on the template page
if not mw.ustring.match(last, "^{{{") then
error("Unsupported word ending: " .. last)
end
end
local soft_endings = make_lookup_table("bi ci dzi ni pi si wi zi")
local gens_form = stem .. last .. "y"
if soft_endings[last] then
gens_form = stem .. last
elseif last == "j" then
if mw.ustring.match(stem, "[aąeęioóuy]$") then
gens_form = stem .. "i"
else
gens_form = stem .. last .. "i"
end
elseif (last == "g") or (last == "k") or (last == "l") then
gens_form = stem .. last .. "i"
end
local dats_lookup = {
b = "bie"; bi = "bi";
c = "cy"; ch = "sze"; ci = "ci"; cz = "czy";
d = "dzie"; dz = "dzy"; dzi = "dzi"; ["dż"] = "dży";
f = "fie";
g = "dze";
h = "że";
j = "ji";
k = "ce";
l = "li"; ["ł"] = "le";
m = "mie";
n = "nie"; ni = "ni";
p = "pie"; ["pi"] = "pi";
r = "rze"; rz = "rzy";
s = "sie"; si = "si"; ["sł"] = "śle"; sm = "śmie"; sn = "śnie";
st = "ście"; sz = "szy";
t = "cie";
w = "wie"; wi = "wi";
z = "zie"; zd = "ździe"; zi = "zi"; ["zł"] = "źle"; zm = "zmie";
zn = "źnie"; ["ż"] = "ży";
-- -zm should not be palatalized
}
local dats_form = stem .. (dats_lookup[last] or last)
if last == "j" and mw.ustring.match(stem, "[aąeęioóuy]$") then
dats_form = stem .. "i"
end
local nomp_e_ending = make_lookup_table("bi c ci cz dz dzi dż j l ni pi rz si sz wi zi ż")
local nomp_form = stem .. last .. "y"
if (last == "g") or (last == "k") then
nomp_form = stem .. last .. "i"
elseif nomp_e_ending[last] then
nomp_form = stem .. last .. "e"
end
local genp_form = stem .. last
if last == "j" then
if mw.ustring.match(stem, "[aąeęioóuy]$") then
-- zgraja, breja, żmija, koja, szuja, chryja ->
-- zgraj, brej, żmij, koj, szuj, chryj
genp_form = stem .. last
else
-- e.g. gracja, torsja
genp_form = stem .. "ji/" .. stem .. "yj"
end
elseif last == "l" then
if mw.ustring.match(stem, "[aąeęioóuy]$") then
-- hala, tabela, mila, rola, kula
genp_form = stem .. "l"
else
-- hodowla, grobla, bernikla
genp_form = stem .. "li"
end
elseif last == "k" then
local kstem, klast = split_stem(stem, soft_ending_lookup)
if kstem then
kstem = kstem .. klast
else
kstem = stem
end
if mw.ustring.match(stem, "[aąeęioóuy]$") then
genp_form = kstem .. "k"
else
genp_form = kstem .. "ek"
end
end
local declinfo = {
noms = stem .. last .. "a"; nomp = nomp_form;
gens = gens_form; genp = genp_form;
dats = dats_form; datp = stem .. last .. "om";
accs = stem .. last .. "ę"; accp = nomp_form;
inss = stem .. last .. "ą"; insp = stem .. last .. "ami";
locs = dats_form; locp = stem .. last .. "ach";
vocs = stem .. last .. "o"; vocp = nomp_form;
}
return handle_overrides(pargs, declinfo,
{ dats = {"locs"}; nomp = {"accp", "vocp"} })
end
-- feminine nouns ending with a consonant, e.g. stal, sól, brew
patterns["f-softcons"] = function (pargs, title)
local endings = make_lookup_table("c ć cz dz dź ew iew j l ń rz ś sz w z ż ź")
local accepted_lasts = make_lookup_table("c ci cz dz dzi j l ni rz si sz wi zi ż")
local stem, last = split_stem(title, endings)
local explicit_stem = false
stem = nonempty(pargs[1]) or stem
last = nonempty(pargs[2]) or last
if nonempty(pargs[2]) then
stem = pargs[1] or ""
last = pargs[2] or ""
explicit_stem = true
end
local nomp_ending = pargs[3] -- may be empty
local noms_form = nonempty(pargs[4])
-- Narew, brukiew, żagiew, brew - elide -e- or -ie-
if last == "iew" or last == "ew" then
if not noms_form then
noms_form = stem .. last
end
last = "wi"
end
if last == "w" or last == "z" then
last = last .. "i"
end
if not accepted_lasts[last] then
-- suppress module error on the template page
if not last or not mw.ustring.match(last, "^{{{") then
error("Unsupported word ending: " .. (last or "nil"))
end
end
-- nominative singular
if not noms_form or (noms_form == "") then
local noms_lookup = {
ci = "ć"; dzi = "dź"; ni = "ń"; si = "ś"; wi = "w"; zi = "ź"; }
noms_form = stem .. (noms_lookup[last] or last)
end
-- Stem-final ó becoming o in inflected forms
if mw.ustring.match(stem, "ó$") and not explicit_stem then
stem = mw.ustring.sub(stem, 1, -2) .. "o"
end
-- genitive singular
local gens_form = stem .. last
local gens_y_ending = make_lookup_table("c cz dz sz rz ż")
if last == "j" then
gens_form = stem .. "i"
elseif last == "l" then
gens_form = gens_form .. "i"
elseif gens_y_ending[last] then
gens_form = gens_form .. "y"
end
-- nominative plural
if not nomp_ending then
if last == "ci" then
-- some words have -e, but this is a lot more common
nomp_ending = ""
else
nomp_ending = "e"
end
end
-- this is trivial, but used in 3 places in the table
local nomp_form = stem .. last .. nomp_ending;
local declinfo = {
noms = noms_form; nomp = nomp_form;
gens = gens_form; genp = gens_form;
dats = gens_form; datp = stem .. last .. "om";
accs = noms_form; accp = nomp_form;
inss = stem .. last .. "ą"; insp = stem .. last .. "ami";
locs = gens_form; locp = stem .. last .. "ach";
vocs = gens_form; vocp = nomp_form;
}
return handle_overrides(pargs, declinfo,
{ noms = {"accs"}; gens = {"dats", "locs", "vocs", "genp"}; nomp = {"accp", "vocp"} })
end
-- feminine nouns with adjectival declension
patterns["f-adj"] = function (pargs, title)
local word = nonempty(pargs[1]) or title
if mw.ustring.match(word, "^{{{") then
word = "przykładowa"
end
local decl = m_adj.autoinflect(word)
local declinfo = {
noms = decl[2]; nomp = decl[5];
gens = decl[7]; genp = decl[8];
dats = decl[7]; datp = decl[10];
accs = decl[11]; accp = decl[5];
inss = decl[11]; insp = decl[13];
locs = decl[7]; locp = decl[8];
vocs = decl[2]; vocp = decl[5];
}
return handle_overrides(pargs, declinfo,
{ gens = {"dats", "locs"}; accs = {"inss"}; nomp = {"accp", "vocp"}; genp = {"locp"} })
-- "vocs" may not always be equal to "noms" (e.g. "teściowa")
end
-- feminine nouns ending with -ja, e.g. fuzja, anomizja, animacja
-- obsolete - "f" handles them as well
patterns["f-ja"] = function (pargs, title)
local stem = nonempty(pargs[1]) or mw.ustring.match(title, "^(.*)ja$")
local yj = "yj"
if pargs[2] and (pargs[2] ~= "") then
yj = "ij"
end
genp_form = stem .. "ji/" .. stem .. yj;
local declinfo = {
noms = stem .. "ja"; nomp = stem .. "je";
gens = stem .. "ji"; genp = genp_form;
dats = stem .. "ji"; datp = stem .. "jom";
accs = stem .. "ję"; accp = stem .. "je";
inss = stem .. "ją"; insp = stem .. "jami";
locs = stem .. "ji"; locp = stem .. "jach";
vocs = stem .. "jo"; vocp = stem .. "je";
}
return handle_overrides(pargs, declinfo,
{ gens = {"dats", "locs"}; nomp = {"accp", "vocp"} })
end
-- most feminine nouns ending with -ia, e.g. mafia, kopia, balia
-- note that some nouns follow the "f" pattern instead, e.g. konopia, głębia
patterns["f-ia"] = function (pargs, title)
local stem = nonempty(pargs[1]) or mw.ustring.match(title, "^(.*)ia$")
local oldgenp = stem .. "ij"
if mw.ustring.match(stem, "[dtr]$") then
oldgenp = stem .. "yj"
end
local genp_form = stem .. "ii/" .. oldgenp;
local declinfo = {
noms = stem .. "ia"; nomp = stem .. "ie";
gens = stem .. "ii"; genp = genp_form;
dats = stem .. "ii"; datp = stem .. "iom";
accs = stem .. "ię"; accp = stem .. "ie";
inss = stem .. "ią"; insp = stem .. "iami";
locs = stem .. "ii"; locp = stem .. "iach";
vocs = stem .. "io"; vocp = stem .. "ie";
}
return handle_overrides(pargs, declinfo,
{ gens = {"dats", "locs"}; nomp = {"accp", "vocp"} })
end
-- feminine nouns ending in -ni, e.g. mistrzyni, mędrczyni
patterns["f-ni"] = function (pargs, title)
local stem = nonempty(pargs[1]) or mw.ustring.match(title, "^(.*)ni$")
local declinfo = {
noms = stem .. "ni"; nomp = stem .. "nie";
gens = stem .. "ni"; genp = stem .. "ń";
dats = stem .. "ni"; datp = stem .. "niom";
accs = stem .. "nię"; accp = stem .. "nie";
inss = stem .. "nią"; insp = stem .. "niami";
locs = stem .. "ni"; locp = stem .. "niach";
vocs = stem .. "ni"; vocp = stem .. "nie";
}
return handle_overrides(pargs, declinfo,
{ noms = {"gens", "dats", "locs", "vocs"}; nomp = {"accp", "vocp"} })
end
-- feminine adjectives in noun phrases
patterns["adj-f"] = function (pargs, title)
local word = nonempty(pargs[1]) or title
if mw.ustring.match(word, "^{{{") then
word = "przykładowa"
end
local decl = m_adj.autoinflect(word)
local declinfo = {
noms = decl[2]; nomp = decl[5];
gens = decl[7]; genp = decl[8];
dats = decl[7]; datp = decl[10];
accs = decl[11]; accp = decl[5];
inss = decl[11]; insp = decl[13];
locs = decl[7]; locp = decl[8];
vocs = decl[2]; vocp = decl[5];
}
return handle_overrides(pargs, declinfo,
{ noms = {"vocs"}; gens = {"dats", "locs"}; accs = {"inss"}; nomp = {"accp", "vocp"}; genp = {"locp"} })
end
-- -----------------------------------------------------------------------------
-- -------------------------- Neuter declension -----------------------------
-- -----------------------------------------------------------------------------
-- neuter nouns ending in -o, e.g. jajko, jarzmo, gusło, cudo
patterns["n"] = function (pargs, word)
if pargs[1] and mw.ustring.match(pargs[1], "^{{{") then
word = "jajko"
end
-- forward to other patterns depending on the last letter
if not nonempty(pargs[1]) and not nonempty(pargs[2]) then
if mw.ustring.match(word, "e$") then
return patterns["n-e"](pargs, word)
elseif mw.ustring.match(word, "ę$") then
return patterns["n-ę"](pargs, word)
elseif mw.ustring.match(word, "um$") then
return patterns["n-um"](pargs, word)
end
end
local word_no_o = mw.ustring.match(word, "^(.*)o$")
local endings = make_lookup_table(
"b bn c ch d f g gn j k kn l ł m mn n nd p r rz rzm " ..
"s sk sł sm sn st t tt tw w wn z zd zł zm zn zz")
local stem, last
if word_no_o then
stem, last = split_stem(word_no_o, endings)
end
stem = nonempty(pargs[1]) or stem
last = nonempty(pargs[2]) or last
local genp_form = nonempty(pargs[3])
if not endings[last] then
-- suppress module error on the template page
if not mw.ustring.match(last, "^{{{") then
error("Unsupported word ending: " .. last)
end
end
local inss_form = stem .. last .. "em"
if last == "g" or last == "k" then
inss_form = stem .. last .. "iem"
end
local locs_lookup = {
b = "bie"; bn = "bnie";
c = "cu"; ch = "chu";
d = "dzie";
f = "fie";
g = "gu"; gn = "gnie";
j = "ju";
k = "ku"; kn = "knie";
l = "lu"; ["ł"] = "le";
m = "mie"; mn = "mnie";
n = "nie"; nd = "ndzie";
p = "pie";
r = "rze"; rz = "rzu"; rzm = "rzmie"; -- piórze, scherzu, jarzmie
s = "sie"; sk = "sku"; ["sł"] = "śle"; sm = "śmie"; sn = "śnie"; st = "ście";
t = "cie"; tt = "tcie"; tw = "twie";
w = "wie"; wn = "wnie";
z = "zie"; zd = "ździe"; ["zł"] = "źle"; zm = "źmie"; zn = "źnie"; zz = "zzu";
}
locs_form = stem .. (locs_lookup[last] or (last .. "u"))
if not genp_form then
if last == "sn" or last == "zn" then
genp_form = stem .. mw.ustring.sub(last, 1, 1) .. "en" -- e.g. krosno -> krosen
elseif mw.ustring.match(last, "^.n$") then
genp_form = stem .. mw.ustring.sub(last, 1, 1) .. "ien" -- e.g. bagno -> bagien
elseif last == "tw" or last == "sk" or mw.ustring.match(stem, "[aąeęioóuy]$") then
genp_form = stem .. last -- e.g. bogactwo -> bogactw, dyktando -> dyktand (nd treated as digraph)
else
if mw.ustring.match(stem, "[gk]$") then
genp_form = stem .. "ie" .. last -- e.g. szkło -> szkieł
else
genp_form = stem .. "e" .. last -- e.g. jajko -> jajek
end
end
end
local declinfo = {
noms = stem .. last .. "o"; nomp = stem .. last .. "a";
gens = stem .. last .. "a"; genp = genp_form;
dats = stem .. last .. "u"; datp = stem .. last .. "om";
accs = stem .. last .. "o"; accp = stem .. last .. "a";
inss = inss_form; insp = stem .. last .. "ami";
locs = locs_form; locp = stem .. last .. "ach";
vocs = stem .. last .. "o"; vocp = stem .. last .. "a";
}
return handle_overrides(pargs, declinfo,
{ noms = {"accs", "vocs"}; gens = {"nomp", "accp", "vocp"}; nomp = {"accp", "vocp"} })
end
-- neuter nouns ending in -e
patterns["n-e"] = function (pargs, word)
local word_no_e = mw.ustring.match(word, "^(.*)e$")
local endings = make_lookup_table("bi c ci cz dz dzi fi j l mi ni pi rz si sz wi zi ż")
local stem, last
if word_no_e then
stem, last = split_stem(word_no_e, endings)
end
if nonempty(pargs[1]) then
stem = pargs[1]
last = ""
end
local genp_lookup = { ci = "ć"; cz = "czy"; ni = "ń"; rz = "rzy"; sz = "szy"; ["ż"] = "ży"; }
local genp_form = pargs[3] or (stem .. (genp_lookup[last] or last))
local sl = stem .. last
local declinfo = {
noms = sl .. "e"; nomp = sl .. "a";
gens = sl .. "a"; genp = genp_form;
dats = sl .. "u"; datp = sl .. "om";
accs = sl .. "e"; accp = sl .. "a";
inss = sl .. "em"; insp = sl .. "ami";
locs = sl .. "u"; locp = sl .. "ach";
vocs = sl .. "e"; vocp = sl .. "a";
}
return handle_overrides(pargs, declinfo,
{ noms = {"accs", "vocs"}; gens = {"nomp", "accp", "vocp"}; dats = {"locs"}; nomp = {"accp", "vocp"} })
end
-- neuter nouns ending in -ę but not in -mię, e.g. kocię, szczenię, dziecię
patterns["n-ę"] = function (pargs, title)
local mstem = mw.ustring.match(title, "^(.*)mię$")
if mstem then
pargs[1] = mstem
return patterns["n-mię"](pargs, title)
end
local stem = nonempty(pargs[1]) or mw.ustring.match(title, "^(.*)ę$")
local declinfo = {
noms = stem .. "ę"; nomp = stem .. "ęta";
gens = stem .. "ęcia"; genp = stem .. "ąt";
dats = stem .. "ęciu"; datp = stem .. "ętom";
accs = stem .. "ę"; accp = stem .. "ęta";
inss = stem .. "ęciem"; insp = stem .. "ętami";
locs = stem .. "ęciu"; locp = stem .. "ętach";
vocs = stem .. "ę"; vocp = stem .. "ęta";
}
return handle_overrides(pargs, declinfo,
{ noms = {"accs", "vocs"}; dats = {"locs"}; nomp = {"accp", "vocp"} })
end
-- neuter nouns ending in -mię, e.g. wymię, znamię, plemię
patterns["n-mię"] = function (pargs, title)
local stem = nonempty(pargs[1]) or mw.ustring.match(title, "^(.*)mię$")
local declinfo = {
noms = stem .. "mię"; nomp = stem .. "miona";
gens = stem .. "mienia"; genp = stem .. "mion";
dats = stem .. "mieniu"; datp = stem .. "mionom";
accs = stem .. "mię"; accp = stem .. "miona";
inss = stem .. "mieniem"; insp = stem .. "mionami";
locs = stem .. "mieniu"; locp = stem .. "mionach";
vocs = stem .. "mię"; vocp = stem .. "miona";
}
return handle_overrides(pargs, declinfo,
{ noms = {"accs", "vocs"}; dats = {"locs"}; nomp = {"accp", "vocp"} })
end
-- neuter nouns with adjectival declension, e.g. bykowe
patterns["n-adj"] = function (pargs, title)
local word = nonempty(pargs[1]) or title
if mw.ustring.match(word, "^{{{") then
word = "przykładowe"
end
local decl = m_adj.autoinflect(word)
local declinfo = {
noms = decl[3]; nomp = decl[5];
gens = decl[6]; genp = decl[8];
dats = decl[9]; datp = decl[10];
accs = decl[3]; accp = decl[5];
inss = decl[12]; insp = decl[13];
locs = decl[12]; locp = decl[8];
vocs = decl[3]; vocp = decl[5];
}
return handle_overrides(pargs, declinfo,
{ noms = {"accs", "vocs"}; inss = {"locs"}; nomp = {"accp", "vocp"}; genp = {"locp"} })
end
-- neuter nouns ending in -um, e.g. liceum, gimnazjum, kryterium
-- mostly nouns borrow from ancient Greek
patterns["n-um"] = function (pargs, title)
local stem = nonempty(pargs[1]) or mw.ustring.match(title, "^(.*)um$")
local declinfo = {
noms = stem .. "um"; nomp = stem .. "a";
gens = stem .. "um"; genp = stem .. "ów";
dats = stem .. "um"; datp = stem .. "om";
accs = stem .. "um"; accp = stem .. "a";
inss = stem .. "um"; insp = stem .. "ami";
locs = stem .. "um"; locp = stem .. "ach";
vocs = stem .. "um"; vocp = stem .. "a";
}
return handle_overrides(pargs, declinfo,
{ nomp = {"accp", "vocp"} })
end
-- highly irregular nouns
patterns["irreg"] = function (pargs, title)
local word = make_lookup_table("brat dziecko ksiądz książę rok")
if not word[title] then
if not mw.ustring.match(title, "^{{{") then
error("Unsupported word")
end
end
-- brat
if title == "brat" then
noms_form = "brat"
gens_form = "brata"
dats_form = "bratu"
accs_form = "brata"
inss_form = "bratem"
locs_form = "bracie"
vocs_form = "bracie"
nomp_form = "bracia"
genp_form = "braci"
datp_form = "braciom"
accp_form = "braci"
insp_form = "braćmi"
locp_form = "braciach"
vocp_form = "bracia"
end
-- dziecko
if title == "dziecko" then
noms_form = "dziecko"
gens_form = "dziecka"
dats_form = "dziecku"
accs_form = "dziecko"
inss_form = "dzieckiem"
locs_form = "dziecku"
vocs_form = "dziecko"
nomp_form = "dzieci"
genp_form = "dzieci"
datp_form = "dzieciom"
accp_form = "dzieci"
insp_form = "dziećmi"
locp_form = "dzieciach"
vocp_form = "dzieci"
end
--ksiądz
if title == "ksiądz" then
noms_form = "ksiądz"
gens_form = "księdza"
dats_form = "księdzu"
accs_form = "księdza"
inss_form = "księdzem"
locs_form = "księdzu"
vocs_form = "księże"
nomp_form = "księża"
genp_form = "księży"
datp_form = "księżom"
accp_form = "księży"
insp_form = "księżmi"
locp_form = "księżach"
vocp_form = "księża"
end
--książę
if title == "książę" then
noms_form = "książę"
gens_form = "księcia"
dats_form = "księciu"
accs_form = "księcia"
inss_form = "księciem"
locs_form = "księciu"
vocs_form = "książę"
nomp_form = "książęta"
genp_form = "książąt"
datp_form = "książętom"
accp_form = "książąt"
insp_form = "książętami"
locp_form = "książętach"
vocp_form = "książęta"
end
-- rok
if title == "rok" then
noms_form = "rok"
gens_form = "roku"
dats_form = "rokowi"
accs_form = "rok"
inss_form = "rokiem"
locs_form = "roku"
vocs_form = "roku"
nomp_form = "lata"
genp_form = "lat"
datp_form = "latom"
accp_form = "lata"
insp_form = "latami"
locp_form = "latach"
vocp_form = "lata"
end
local declinfo = {
noms = noms_form; nomp = nomp_form;
gens = gens_form; genp = genp_form;
dats = dats_form; datp = datp_form;
accs = accs_form; accp = accp_form;
inss = inss_form; insp = insp_form;
locs = locs_form; locp = locp_form;
vocs = vocs_form; vocp = vocp_form;
}
return handle_overrides(pargs, declinfo, {})
end
-- indeclinable pattern, i.e. same word for all cases
patterns["indec"] = function (pargs, title)
local word = nonempty(pargs[1]) or title
local declinfo = {}
for i = 1, 7 do
for _, col in ipairs(noun_cols) do
declinfo[cases[i].key .. col.key] = word
end
end
return handle_overrides(pargs, declinfo, {})
end
-- shorthands
patterns["nin"] = patterns["m-pr-nin"]
patterns["ia"] = patterns["fem-ia"]
-- aliases for adjectives in phrases
patterns["adj-m-pr"] = patterns["m-pr-adj"]
patterns["adj-n"] = patterns["n-adj"]
-- used for autodetection of adjective genders in phrases
local function pattern_gender(pattern)
if pattern == "m-in" or pattern == "adj-m-in" then
return "m-in"
elseif pattern == "m-an" or pattern == "adj-m-an" then
return "m-an"
elseif string.match(pattern, "^m-pr") or pattern == "adj-m-pr" then
return "m-pr"
elseif string.match(pattern, "^f") or pattern == "adj-f" then
return "f"
elseif string.match(pattern, "^n") or pattern == "adj-n" then
return "n"
end
return nil
end
-- generate inflected forms given pattern, parameters, and full word
-- returned words do not contain links
function export.autoinflect(pattern, pargs, word)
if not pattern then
error("Declension pattern not specified")
end
if mw.ustring.match(pattern, "^{{{") then
pattern = "m-in"
end
if not patterns[pattern] then
error("Invalid declension pattern: " .. pattern)
end
return patterns[pattern](pargs, pargs["lemma"] or word)
end
local function make_substitutable_table(pargs, declinfo, preproc)
local tantum = normalize_tantum(pargs)
if mw.isSubsting() then
if tantum == "s" or tantum == "p" then
local tname = "sing"
if tantum == "p" then
tname = "pl"
end
local rows = {}
for i = 1, 7 do
local case_key = cases[i].key .. tantum
table.insert(rows, ("| <!-- %s --> %s"):format(case_key, m_links.remove_links(declinfo[case_key])))
end
return "{{pl-decl-noun-" .. tname .. "\n" .. table.concat(rows, "\n") .. "\n}}"
end
local rows = {}
for i = 1, 7 do
local case_skey = cases[i].key .. "s"
local case_pkey = cases[i].key .. "p"
table.insert(rows, ("| <!-- %s --> %s"):format(case_skey, m_links.remove_links(declinfo[case_skey])))
table.insert(rows, ("| <!-- %s --> %s"):format(case_pkey, m_links.remove_links(declinfo[case_pkey])))
end
return "{{pl-decl-noun\n" .. table.concat(rows, "\n") .. "\n}}"
else
local cols = noun_cols
if tantum == "s" then
cols = { noun_cols[1] }
elseif tantum == "p" then
cols = { noun_cols[2] }
end
cols = override_col_titles(pargs.heads, cols)
if pargs.nocat then
tantum = nil
end
return make_table(declinfo, cols, preproc, pargs.width, pargs.title, tantum, pargs.nolinks)
end
end
-- Generate declension table for a specified declension pattern
function export.template_decl_pattern(frame)
local args = frame.args
local pargs = frame:getParent().args
local pagetitle = mw.title.getCurrentTitle().fullText
-- support "num" as fallback for "tantum" to match Latin templates
local tantum = pargs.tantum or pargs.num
if tantum == "sg" then
tantum = "s"
elseif tantum == "pl" then
tantum = "p"
end
if get_mode() == 'demo' then
pargs = { "{{{1}}}", "{{{2}}}", "{{{3}}}", "{{{4}}}", "{{{5}}}" }
end
-- if args is empty, use pargs[1] as the pattern name and shift pargs
local offset = 0
local pattern = args[1]
if not pattern then
-- extreme brokenness: table.remove(pargs, 1) has absolutely no effect!
-- is this because pargs is somehow immutable?
pattern = pargs[1]
offset = -1
end
local fixed_pargs = {}
for key, parg in pairs(pargs) do
if type(key) == "number" then
local i = key + offset
if i >= 1 and parg then
fixed_pargs[i] = m_links.remove_links(parg)
end
else
fixed_pargs[key] = m_links.remove_links(parg)
end
end
declinfo = export.autoinflect(pattern, fixed_pargs, pagetitle)
return make_substitutable_table(pargs, declinfo, "linkify")
end
local function push_down_indices(tbl)
local ret = {}
for index, decl in ipairs(tbl) do
for k, v in pairs(decl) do
ret[k] = ret[k] or {}
table.insert(ret[k], v)
end
end
return ret
end
-- Generate declension table for a noun phrase
function export.template_decl_phrase(frame)
local args = frame.args
local pargs = frame:getParent().args
local page_title = mw.title.getCurrentTitle().fullText
local lemma = pargs["lemma"] or page_title
local words = {}
if get_mode() == "demo" then
pargs = { "adj", "n", "adj" }
lemma = "przykładowe wyrażenie rzeczownikowe"
end
-- split title into words
for t in mw.ustring.gmatch(lemma, "[^ ]+") do
table.insert(words, t)
end
local word_args = {}
for index, word in ipairs(words) do
-- parse arguments to declension patterns
word_args[index] = {}
local numkey = 1
local arg = pargs[index] or ""
for i in mw.ustring.gmatch(arg, "[^!]+") do
local param = mw.text.trim(i)
local k, v = mw.ustring.match(param, "^([^:]*):(.*)$")
if k and v then
word_args[index][k] = v
else
word_args[index][numkey] = param
numkey = numkey + 1
end
end
end
local adj_gender = nil
for index, word in ipairs(words) do
-- find the first gendered pattern and use it to match adjectives
if not adj_gender then
adj_gender = pattern_gender(word_args[index][1])
end
end
local result = {}
local result_raw = {}
for index, word in ipairs(words) do
local word_result = {}
local pattern = table.remove(word_args[index], 1)
if pattern == "adj" then
if adj_gender then
pattern = "adj-" .. adj_gender
else
error("Unable to guess adjective gender")
end
end
if not patterns[pattern] then
-- indeclinable
pattern = "indec"
end
local nolinks = word_args[index].nolinks or pargs.linkfull
result_raw[index] = export.autoinflect(pattern, word_args[index], word)
result[index] = linkify_info(result_raw[index], altsep, nolinks)
end
-- rearrange the table so that word indices are at the lower level
result_raw = push_down_indices(result_raw)
result = push_down_indices(result)
-- make table entries
for case, v in pairs(result_raw) do
local phrase = table.concat(v, " ")
if phrase == page_title then
-- bold self-link if the phrase is equal to the page title
result[case] = "[[" .. page_title .. "]]"
else
result[case] = table.concat(result[case], " ")
if pargs.linkfull then
-- do not split if linking full phrase declensions
result[case] = export.make_links(result[case], nil)
end
end
end
-- width determination
if not pargs.width then
local result_concat = {}
for case, v in pairs(result_raw) do
result_concat[case] = table.concat(v, " ")
end
pargs.width = guess_width(result_concat, noun_cols)
end
-- disable linkifying, since we already made per-word links
return make_substitutable_table(pargs, result, nil)
end
return export
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.