Module:User:Benwing2/cs-adjective
Appearance
- This module sandbox lacks a documentation subpage. Please create it.
- Useful links: root page • root page’s subpages • links • transclusions • testcases • sandbox
local export = {}
--[=[
Authorship: Ben Wing <benwing2>
]=]
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of case/gender/number.
Example slot names for adjectives are "gen_f" (genitive feminine singular) and
"nom_mp_an" (animate nominative masculine plural). Each slot is filled with zero or more forms.
-- "form" = The declined Czech form representing the value of a given slot.
-- "lemma" = The dictionary form of a given Czech term. Generally the nominative
masculine singular, but may occasionally be another form if the nominative
masculine singular is missing.
]=]
local lang = require("Module:languages").getByCode("cs")
local m_links = require("Module:links")
local m_table = require("Module:table")
local m_string_utilities = require("Module:string utilities")
local iut = require("Module:inflection utilities")
local com = require("Module:User:Benwing2/cs-common")
local current_title = mw.title.getCurrentTitle()
local NAMESPACE = current_title.nsText
local PAGENAME = current_title.text
local u = mw.ustring.char
local rsplit = mw.text.split
local rfind = mw.ustring.find
local rmatch = mw.ustring.match
local rgmatch = mw.ustring.gmatch
local rsubn = mw.ustring.gsub
local ulen = mw.ustring.len
local uupper = mw.ustring.upper
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
-- version of rsubn() that returns a 2nd argument boolean indicating whether
-- a substitution was made.
local function rsubb(term, foo, bar)
local retval, nsubs = rsubn(term, foo, bar)
return retval, nsubs > 0
end
-- All slots that are used by any of the different tables. The key is the slot and the value is a list of the tables
-- that use the slot. "" = regular, "plonly" = special=plonly in {{cs-adecl-manual}}, "dva" = special=dva in
-- {{cs-adecl-manual}}.
local input_adjective_slots = {
nom_m = {""},
nom_f = {""},
nom_n = {""},
nom_mp_an = {"", "plonly"},
nom_fp = {"", "plonly"},
nom_np = {"", "plonly"},
nom_mp = {"dva"},
nom_fnp = {"dva"},
gen_m = {""},
gen_f = {""},
gen_p = {"", "plonly", "dva"},
dat_m = {""},
dat_f = {""},
dat_p = {"", "plonly", "dva"},
acc_m_an = {""},
acc_m_in = {""},
acc_f = {""},
acc_n = {""},
acc_mfp = {"", "plonly"},
acc_np = {"", "plonly"},
acc_mp = {"dva"},
acc_fnp = {"dva"},
ins_m = {""},
ins_f = {""},
ins_p = {"", "plonly", "dva"},
loc_m = {""},
loc_f = {""},
loc_p = {"", "plonly", "dva"},
short_m = {""},
short_f = {""},
short_n = {""},
short_mp_an = {""},
short_fp = {""},
short_np = {""},
}
local output_adjective_slots = {
nom_m = "nom|m|s",
nom_m_linked = "nom|m|s", -- used in [[Module:cs-noun]]?
nom_f = "nom|f|s",
nom_n = "nom|n|s",
nom_mp_an = "an|nom|m|p",
nom_fp = "in|nom|m|p|;|nom|f|p",
nom_np = "nom|n|p",
nom_mp = "nom|m|p",
nom_fnp = "nom|f//n|p",
gen_m = "gen|m//n|s",
gen_f = "gen|f|s",
gen_p = "gen|p",
dat_m = "dat|m//n|s",
dat_f = "dat|f|s",
dat_p = "dat|p",
acc_m_an = "an|acc|m|s",
acc_m_in = "in|acc|m|s",
acc_f = "acc|f|s",
acc_n = "acc|n|s",
acc_mfp = "acc|m//f|p",
acc_np = "acc|n|p",
acc_mp = "acc|m|p",
acc_fnp = "acc|f//n|p",
ins_m = "ins|m//n|s",
ins_f = "ins|f|s",
ins_p = "ins|p",
loc_m = "loc|m//n|s",
loc_f = "loc|f|s",
loc_p = "loc|p",
short_m = "short|m|s",
short_f = "short|f|s",
short_n = "short|n|s",
short_mp_an = "short|an|m|p",
short_fp = "short|in|m|p|;|short|f|p",
short_np = "short|n|p",
}
local function get_output_adjective_slots(alternant_multiword_spec)
return output_adjective_slots
end
local function combine_stem_ending(stems, ending)
if stems == "?" then
return "?"
else
return stems .. ending
end
end
local function add(base, slot, stems, endings, footnote)
if stems then
stems = iut.combine_form_and_footnotes(stems, footnote)
end
iut.add_forms(base.forms, slot, stems, endings, combine_stem_ending)
end
local function add_normal_decl(base, stems,
nom_m, nom_f, nom_n, nom_mp_an, nom_fp, nom_np,
gen_m, gen_f, gen_p,
dat_m, dat_f, dat_p,
acc_f,
loc_m, loc_f, loc_p,
ins_m, ins_f, ins_p,
footnote)
if stems then
stems = iut.combine_form_and_footnotes(stems, footnote)
end
add(base, "nom_m", stems, nom_m)
add(base, "nom_f", stems, nom_f)
add(base, "nom_n", stems, nom_n)
add(base, "nom_mp_an", stems, nom_mp_an)
add(base, "nom_fp", stems, nom_fp)
add(base, "nom_np", stems, nom_np)
add(base, "gen_m", stems, gen_m)
add(base, "gen_f", stems, gen_f)
add(base, "gen_p", stems, gen_p)
add(base, "dat_m", stems, dat_m)
add(base, "dat_f", stems, dat_f)
add(base, "dat_p", stems, dat_p)
add(base, "acc_f", stems, acc_f)
add(base, "loc_m", stems, loc_m)
add(base, "loc_f", stems, loc_f)
add(base, "loc_p", stems, loc_p)
add(base, "ins_m", stems, ins_m)
add(base, "ins_f", stems, ins_f)
add(base, "ins_p", stems, ins_p)
end
local function add_short_decl(base, stems, m, f, n, mp_an, fp, np, footnote)
if stems then
stems = iut.combine_form_and_footnotes(stems, footnote)
end
add(base, "short_m", stems, m)
add(base, "short_f", stems, f)
add(base, "short_n", stems, n)
add(base, "short_mp_an", stems, mp_an)
add(base, "short_fp", stems, fp)
add(base, "short_np", stems, np)
end
local decls = {}
decls["normal"] = function(base)
local stem, suffix
-- hard in -ý
stem, suffix = rmatch(base.lemma, "^(.*)(ý)$")
if stem then
add_normal_decl(base, stem,
"ý", "á", "é", {}, "é", "á",
"ého", "é", "ých",
"ému", "é", "ým",
"ou",
"ém", "é", "ých",
"ým", "ou", "ými"
)
-- Do the nominative masculine animate plural separately since it may have a different stem (with the second
-- palatalization applied).
add_normal_decl(base, com.apply_second_palatalization(stem), nil, nil, nil, "í")
if base.short then
-- Examples of short adjectives:
-- bledý "pale" -> bled
-- bosý "barefoot" -> bos
-- pilný "hardworking, diligent" -> pilen (reducible)
-- veselý "funny, jolly" -> vesel
-- jistý "certain, sure" -> jist
-- vinný "guilty" -> vinen (reducible)
-- živý "alive, living" -> živ
-- tichý "quiet" -> tich; mp_an = tiši
-- vědomý "conscious, aware" -> vědom
-- rád "glad" (short only)
-- chudý "poor" -> chud
-- nevinný "innocent" -> nevinen (reducible)
-- silný "strong" -> silen (reducible)
-- známý "known" -> znám
-- mladý "young" -> mlád (note length); other forms have mlád- or mlad-
-- starý "old" -> stár (note length); other forms have stár- or star-; mp_an = stáři, staři
-- slabý "weak" -> sláb (note length); other forms only have sláb- (FIXME: check against a grammar)
-- zdravý "healthy" -> zdráv (note length); other forms only have zdráv- (FIXME: check against a grammar)
-- nemocný "ill" -> nemocen (reducible)
-- plný "full" -> pln
-- schopný "able, capable" -> schopen (reducible)
-- vděčný "grateful" -> vděčen (reducible)
-- věrný "faithful" -> věren (reducible)
-- šťastný "happy" -> šťasten (reducible)
-- křepký "strong" -> křepek (reducible); mp_an = křepci
-- hotový "ready, finished" -> hotov
-- němý "mute" -> něma
-- smutný "sad" -> smuten (reducible)
-- samotný "lonely" -> samoten (reducible)
-- bohatý "rich" -> bohat
-- chladný "cold" -> chladen (reducible)
-- dlužný "necessary?" -> dlužen (reducible)
-- povinný "mandatory" -> povinen (reducible)
-- zodpovědný "responsible" -> zodpověden (reducible)
-- udatný "brave" -> udaten (reducible)
-- náchylný "susceptible" -> náchylen (reducible)
for _, short_stem_obj in ipairs(base.short) do
add_short_decl(base, short_stem_obj.base, "")
add_short_decl(base, short_stem_obj.stem, nil, "a", "o", nil, "y", "a")
add_short_decl(base, com.apply_second_palatalization(short_stem_obj.stem.form), nil, nil, nil, "i",
short_stem_obj.stem.footnotes)
end
end
return
end
-- soft in -í
stem, suffix = rmatch(base.lemma, "^(.*)(í)$")
if stem then
add_normal_decl(base, stem,
"í", "í", "í", "í", "í", "í",
"ího", "í", "ích",
"ímu", "í", "ím",
"í",
"ím", "í", "ích",
"ím", "í", "ími"
)
return
end
-- possessive in -ův
stem, suffix = rmatch(base.lemma, "^(.*)(ův)$")
if stem then
add_normal_decl(base, stem,
"ův", "ova", "ovo", "ovi", "ovy", "ova",
"ova", "ovy", "ových",
"ovu", "ově", "ovým",
"ovu",
"ově", "ově", "ových",
"ovým", "ovou", "ovými"
)
return
end
-- possessive in -in
stem, suffix = rmatch(base.lemma, "^(.*)(in)$")
if stem then
add_normal_decl(base, stem,
"in", "ina", "ino", "ini", "iny", "ina",
"ina", "iny", "iných",
"inu", "ině", "iným",
"inu",
"ině", "ině", "iných",
"iným", "inou", "inými"
)
return
end
error("Unrecognized adjective lemma, should end in '-ý', '-í', '-ův' or '-in': '" .. base.lemma .. "'")
end
decls["irreg"] = function(base)
local stem, suffix
-- determiner like můj
stem, suffix = rmatch(base.lemma, "^(.*)(ůj)$")
if stem then
add_normal_decl(base, stem,
"ůj", {"á", "oje"}, {"e", "oje"}, {"í", "oji"}, {"é", "oje"}, {"á", "oje"},
"ého", {"é", "ojí"}, "ých",
"ému", {"é", "ojí"}, "ým",
{"ou", "oji"},
"ém", {"é", "ojí"}, "ých",
"ým", {"ou", "ojí"}, "ými"
)
return
end
-- determiner like [[ten]], [[tamten]], [[tamhleten]], [[tuten]], [[jeden]], [[onen]]
-- [[tento]] uses 'ten<irreg>to'
-- [[tenhle]] uses 'ten<irreg>hle'
-- [[tenhleten]] uses 'ten<irreg>hleten<irreg>'
stem, suffix = rmatch(base.lemma, "^(.*)(en)$")
if stem then
local nom_stem = stem .. suffix
if nom_stem == "jeden" then
stem = "jedn"
end
add_normal_decl(base, nom_stem, "")
add_normal_decl(base, stem,
nil, "a", "o", "i", "y", "a",
"oho", "é", "ěch",
"omu", "é", "ěm",
"u",
"om", "é", "ěch",
"ím", "ou", "ěmi"
)
return
end
-- [[náš]], [[váš]]
stem, suffix = rmatch(base.lemma, "^(.*)(áš)$")
if stem then
local nom_stem = stem .. suffix
stem = stem .. "aš"
add_normal_decl(base, nom_stem, "")
add_normal_decl(base, stem,
nil, "e", "e", "i", "e", "e",
"eho", "í", "ich",
"emu", "í", "im",
"i",
"em", "í", "ich",
"ím", "í", "imi"
)
return
end
if base.lemma == "jenž" then
local preposition_footnote = "the leading letter ''j-'' is changed to ''n-'' when the pronoun is preceded by a preposition, e.g. {{m|cs|[[s]] [[nímž]]}}, {{m|cs|[[k]] [[němuž]]}}, {{m|cs|[[bez]] [[níž]]}}"
preposition_footnote = "[" .. mw.getCurrentFrame():preprocess(preposition_footnote) .. "]"
-- Add the non-prepositional forms.
add_normal_decl(base, "",
"jenž", "jež", "jež", "již", "jež", "jež",
"jehož", "jíž", "jichž",
"jemuž", "jíž", "jimž",
"již",
nil, nil, nil,
"jímž", "jíž", "jimiž"
)
-- Add the prepositional forms. (FIXME: Maybe should go in a separate column in a special table.)
add_normal_decl(base, "",
nil, nil, nil, nil, nil, nil,
"něhož", "níž", "nichž",
"němuž", "níž", "nimž",
"niž",
"němž", "níž", "nichž",
"nímž", "níž", "nimiž",
preposition_footnote
)
-- Unusually, the accusative masculine animate singular is not the same as the genitive masculine singular,
-- and the accusative masculine inanimate singular is not the same as the nominative masculine singular.
add(base, "acc_m_an", "", {"jejž", "jehož"})
add(base, "acc_m_an", "", {"nějž", "něhož"}, preposition_footnote)
add(base, "acc_m_in", "", "jejž")
add(base, "acc_m_in", "", "nějž", preposition_footnote)
return
end
if base.lemma == "tentýž" then
add_normal_decl(base, "",
"tentýž", "tatáž", "totéž", "titíž", "tytéž", "tatáž",
"téhož", "téže", "týchž",
{"témuž", "tomutéž"}, "téže", "týmž",
"tutéž",
"tomtéž", "téže", "týchž",
"tímtéž", "toutéž", "týmiž"
)
return
end
if base.lemma == "týž" then
add_normal_decl(base, "",
"týž", "táž", nil, "tíž", nil, "tatáž",
"téhož", "téže", "týchž",
"témuž", "téže", "týmž",
"touž",
"témž", "téže", "týchž",
"týmž", "touž", "týmiž"
)
return
end
if base.lemma == "sám" then
-- This mixes long and short endings.
add_normal_decl(base, "sám", "")
add_normal_decl(base, "sam",
nil, "a", "o", "i", "y", "a",
"ého", "é", "ých",
"ému", "é", "ým",
"u",
"ém", "é", "ých",
"ým", "ou", "ými"
)
-- Unusually, the accusative masculine animate singular is not the same as the genitive masculine singular.
add(base, "acc_m_an", "sam", {"a", "ého"})
return
end
if base.lemma == "jejíž" then
add_normal_decl(base, "jej",
"íž", "íž", "íž", nil, "íž", "íž",
"íhož", "íž", "íchž",
"ímuvz", "íž", "ímž",
"íž",
"ímž", "íž", "íchž",
"ímž", "íž", "ímiž"
)
add_normal_decl(base, "jij", nil, nil, nil, "íž")
return
end
if base.lemma == "všechen" then
add_normal_decl(base, "",
"všechen", "všechna", {"všechno", "vše"}, "všichni", "všechny", "všechna",
"všeho", "vší", "všech",
"všemu", "vší", "všem",
{"všechnu", "vši"},
"všem", "vší", "všech",
"vším", "vší", "všemi"
)
return
end
if base.lemma == "všecek" then
add_normal_decl(base, "",
"všecek", "všecka", {"všecko", "vše"}, "všicci", "všecky", "všecka",
"všeho", "vší", "všech",
"všemu", "vší", "všem",
{"všecku", "vši"},
"všem", "vší", "všech",
"vším", "vší", "všemi"
)
return
end
if base.lemma == "všecken" then
add_normal_decl(base, "",
"všecken", "všeckna", {"všeckno", "vše"}, "všickni", "všeckny", "všeckna",
"všeho", "vší", "všech",
"všemu", "vší", "všem",
{"všecknu", "vši"},
"všem", "vší", "všech",
"vším", "vší", "všemi"
)
return
end
error("Unrecognized irregular lemma '" .. base.lemma .. "'")
end
local function fetch_footnotes(separated_group)
local footnotes
for j = 2, #separated_group - 1, 2 do
if separated_group[j + 1] ~= "" then
error("Extraneous text after bracketed footnotes: '" .. table.concat(separated_group) .. "'")
end
if not footnotes then
footnotes = {}
end
table.insert(footnotes, separated_group[j])
end
return footnotes
end
local function parse_indicator_spec(angle_bracket_spec)
local inside = rmatch(angle_bracket_spec, "^<(.*)>$")
assert(inside)
local base = {forms = {}}
if inside ~= "" then
local parts = rsplit(inside, ".", true)
for _, part in ipairs(parts) do
if part == "irreg" then
base.irreg = true
elseif part == "short" then
base.short = {{
base = {
form = "+",
},
stem = {
form = "+",
}
}}
elseif rfind(part, "^short:") then
part = rsub(part, "^short:%s*", "")
base.short = {}
local segments = iut.parse_balanced_segment_run(part, "[", "]")
local comma_separated_groups = iut.split_alternating_runs(segments, "%s*,%s*")
for _, comma_separated_group in ipairs(comma_separated_groups) do
if comma_separated_group[1] == "*" then
-- reducible
table.insert(base.short, {
base = {
form = "*",
footnotes = fetch_footnotes(comma_separated_group),
},
stem = {
form = "*",
footnotes = fetch_footnotes(comma_separated_group),
}
})
else
local slash_separated_groups = iut.split_alternating_runs(comma_separated_group, "%s*/%s*")
if #slash_separated_groups > 2 then
error("Too many slash-separated stems: '" .. inside .. "'")
end
local short_base = slash_separated_groups[1]
local short_stem = slash_separated_groups[2]
local short_base_obj = {
form = short_base[1],
footnotes = fetch_footnotes(short_base),
}
if short_stem then
local short_stem_obj = {
form = short_stem[1],
footnotes = fetch_footnotes(short_stem),
}
end
table.insert(base.short, {
base = short_base_obj,
stem = short_stem_obj,
})
end
iut.insert_form(forms, slot, formobj)
end
else
error("Unrecognized indicator '" .. part .. "': '" .. inside .. "'")
end
end
end
return base
end
local function normalize_all_lemmas(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
base.orig_lemma = base.lemma
base.orig_lemma_no_links = m_links.remove_links(base.lemma)
base.lemma = base.orig_lemma_no_links
end)
end
local function detect_indicator_spec(base)
if base.short then
if not base.lemma:find("ý$") then
error("Short forms can only be specified for lemmas ending in -ý, but saw '" .. base.lemma .. "'")
end
local stem = rmatch(base.lemma, "^(.*)ý$")
for _, short_spec in ipairs(base.short) do
if short_spec.base.form == "+" then
short_spec.base.form = stem
elseif short_spec.base.form == "*" then
short_spec.base.form = com.dereduce(stem)
if not short_spec.base.form then
error("Unable to construct non-reduced variant of stem '" .. stem .. "'")
end
end
if short_spec.stem.form == "+" or short_spec.stem.form == "*" then
short_spec.stem.form = stem
end
end
end
if base.irreg then
base.decl = "irreg"
else
base.decl = "normal"
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
detect_indicator_spec(base)
end)
end
local function decline_adjective(base)
if not decls[base.decl] then
error("Internal error: Unrecognized declension type '" .. base.decl .. "'")
end
decls[base.decl](base)
-- handle_derived_slots_and_overrides(base)
end
-- Process override for the arguments in `args`, storing the results into `forms`. If `do_acc`, only do accusative
-- slots; otherwise, don't do accusative slots.
local function process_overrides(forms, args, do_acc)
for slot, _ in pairs(input_adjective_slots) do
if args[slot] and not not do_acc == not not slot:find("^acc") then
forms[slot] = nil
if args[slot] ~= "-" and args[slot] ~= "—" then
local segments = iut.parse_balanced_segment_run(args[slot], "[", "]")
local comma_separated_groups = iut.split_alternating_runs(segments, "%s*,%s*")
for _, comma_separated_group in ipairs(comma_separated_groups) do
local formobj = {
form = comma_separated_group[1],
footnotes = fetch_footnotes(comma_separated_group),
}
iut.insert_form(forms, slot, formobj)
end
end
end
end
end
local function check_allowed_overrides(alternant_multiword_spec, args)
local special = alternant_multiword_spec.special or alternant_multiword_spec.surname and "surname" or ""
for slot, types in pairs(input_adjective_slots) do
if args[slot] then
local allowed = false
for _, typ in ipairs(types) do
if typ == special then
allowed = true
break
end
end
if not allowed then
error(("Override %s= not allowed for %s"):format(slot, special == "" and "regular declension" or
"special=" .. special))
end
end
end
end
local function set_accusative(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
local function copy_if(from_slot, to_slot)
if not forms[to_slot] then
iut.insert_forms(forms, to_slot, forms[from_slot])
end
end
copy_if("nom_n", "acc_n")
copy_if("gen_m", "acc_m_an")
copy_if("nom_m", "acc_m_in")
copy_if("nom_fp", "acc_mfp")
copy_if("nom_np", "acc_np")
end
local function add_categories(alternant_multiword_spec)
local cats = {}
local function insert(cattype)
table.insert(cats, "Czech " .. cattype .. " adjectives")
end
if not alternant_multiword_spec.manual then
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.decl == "poss" then
insert("possessive")
elseif rfind(base.lemma, "ци́?й$") then
insert("ц-stem")
elseif rfind(base.lemma, "ий$") then
insert("hard-stem stem-stressed")
elseif rfind(base.lemma, "и́й$") then
insert("hard-stem ending-stressed")
elseif rfind(base.lemma, "і́?й$") then
insert("soft-stem")
elseif rfind(base.lemma, "ї́?й$") then
insert("vowel-stem")
end
end)
end
alternant_multiword_spec.categories = cats
end
local function show_forms(alternant_multiword_spec)
local lemmas = {}
local lemmaform = alternant_multiword_spec.forms.nom_m or alternant_multiword_spec.forms.nom_mp or
alternant_multiword_spec.forms.nom_mp_an
if lemmaform then
for _, form in ipairs(lemmaform) do
table.insert(lemmas, form.form)
end
end
local props = {
lemmas = lemmas,
slot_table = get_output_adjective_slots(alternant_multiword_spec),
lang = lang,
}
iut.show_forms(alternant_multiword_spec.forms, props)
end
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
local function template_prelude(min_width)
return rsub([===[
<div>
<div class="NavFrame" style="display: inline-block; min-width: MINWIDTHem">
<div class="NavHead" style="background:#eff7ff">{title}{annotation}</div>
<div class="NavContent">
{\op}| border="1px solid #000000" style="border-collapse:collapse;background:#F9F9F9;text-align:center; min-width:MINWIDTHem" class="inflection-table"
|-
]===], "MINWIDTH", min_width)
end
local function template_postlude()
return [=[
|{\cl}{notes_clause}</div></div></div>]=]
end
local table_spec_sg = [=[
! style="background:#d9ebff" colspan=5 | singular
|-
! style="background:#d9ebff" |
! style="background:#d9ebff" | masculine animate
! style="background:#d9ebff" | masculine inanimate
! style="background:#d9ebff" | neuter
! style="background:#d9ebff" | feminine
|-
! style="background:#eff7ff" | nominative
| colspan=2 | {nom_m}
| {nom_n}
| {nom_f}
|-
! style="background:#eff7ff" | genitive
| colspan=3 | {gen_m}
| {gen_f}
|-
! style="background:#eff7ff" | dative
| colspan=3 | {dat_m}
| {dat_f}
|-
! style="background:#eff7ff" | accusative
| {acc_m_an}
| {acc_m_in}
| {acc_n}
| {acc_f}
|-
! style="background:#eff7ff" | locative
| colspan=3 | {loc_m}
| {loc_f}
|-
! style="background:#eff7ff" | instrumental
| colspan=3 | {ins_m}
| {ins_f}{short_sg_clause}
]=]
local table_spec_pl = [=[
! style="background:#d9ebff" colspan=5 | plural
|-
! style="background:#d9ebff" |
! style="background:#d9ebff" | masculine animate
! style="background:#d9ebff" | masculine inanimate
! style="background:#d9ebff" | neuter
! style="background:#d9ebff" | feminine
|-
! style="background:#eff7ff" | nominative
| {nom_mp_an}
| colspan=2 | {nom_fp}
| {nom_np}
|-
! style="background:#eff7ff" | genitive
| colspan=4 | {gen_p}
|-
! style="background:#eff7ff" | dative
| colspan=4 | {dat_p}
|-
! style="background:#eff7ff" | accusative
| colspan=3 | {acc_mfp}
| {acc_np}
|-
! style="background:#eff7ff" | locative
| colspan=4 | {loc_p}
|-
! style="background:#eff7ff" | instrumental
| colspan=4 | {ins_p}{short_pl_clause}
]=]
local table_spec = template_prelude("55") .. table_spec_sg .. "|-\n" .. table_spec_pl .. template_postlude()
local table_spec_plonly = template_prelude("55") .. table_spec_pl .. template_postlude()
local table_spec_dva = template_prelude("40") .. [=[
! style="width:40%;background:#d9ebff" colspan="2" |
! style="background:#d9ebff" colspan="2" | plural
|-
! style="width:40%;background:#d9ebff" colspan="2" |
! style="background:#d9ebff" | masculine
! style="background:#d9ebff" | feminine/neuter
|-
! style="background:#eff7ff" colspan="2" | nominative
| {nom_mp}
| {nom_fnp}
|-
! style="background:#eff7ff" colspan="2" | genitive
| colspan="2" | {gen_p}
|-
! style="background:#eff7ff" colspan="2" | dative
| colspan="2" | {dat_p}
|-
! style="background:#eff7ff" colspan="2" | accusative
| {acc_mp}
| {acc_fnp}
|-
! style="background:#eff7ff" colspan="2" | locative
| colspan="2" | {loc_p}
|-
! style="background:#eff7ff" colspan="2" | instrumental
| colspan="2" | {ins_p}
]=] .. template_postlude()
local short_sg_template = [=[
|-
! style="background:#eff7ff" | short
| colspan=2 | {short_m}
| {short_n}
| {short_f}]=]
local short_pl_template = [=[
|-
! style="background:#eff7ff" | short
| {short_mp_an}
| colspan=2 | {short_fp}
| {short_np}]=]
local notes_template = [===[
<div style="width:100%;text-align:left;background:#d9ebff">
<div style="display:inline-block;text-align:left;padding-left:1em;padding-right:1em">
{footnote}
</div></div>
]===]
if alternant_multiword_spec.title then
forms.title = alternant_multiword_spec.title
else
forms.title = 'Declension of <i lang="cs">' .. forms.lemma .. '</i>'
end
if alternant_multiword_spec.manual then
forms.annotation = ""
else
local ann_parts = {}
local decls = {}
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.decl == "irreg" then
m_table.insertIfNot(decls, "irregular")
elseif rfind(base.lemma, "ý$") then
m_table.insertIfNot(decls, "hard")
else
m_table.insertIfNot(decls, "soft")
end
end)
table.insert(ann_parts, table.concat(decls, " // "))
forms.annotation = " (" .. table.concat(ann_parts, ", ") .. ")"
end
forms.notes_clause = forms.footnote ~= "" and
m_string_utilities.format(notes_template, forms) or ""
forms.short_sg_clause = forms.short_m and forms.short_m ~= "—" and
m_string_utilities.format(short_sg_template, forms) or ""
forms.short_pl_clause = forms.short_mp_an and forms.short_mp_an ~= "—" and
m_string_utilities.format(short_pl_template, forms) or ""
return m_string_utilities.format(
alternant_multiword_spec.special == "plonly" and table_spec_plonly or
alternant_multiword_spec.special == "dva" and table_spec_dva or
table_spec, forms
)
end
-- Externally callable function to parse and decline an adjective given
-- user-specified arguments. Return value is WORD_SPEC, an object where the
-- declined forms are in `WORD_SPEC.forms` for each slot. If there are no values
-- for a slot, the slot key will be missing. The value for a given slot is a
-- list of objects {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(parent_args, pos, from_headword, def)
local params = {
[1] = {required = true, default = "си́ній"},
json = {type = "boolean"}, -- for use with bots
title = {},
}
for slot, _ in pairs(input_adjective_slots) do
params[slot] = {}
end
local args = require("Module:parameters").process(parent_args, params)
local parse_props = {
parse_indicator_spec = parse_indicator_spec,
allow_default_indicator = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(args[1], parse_props)
alternant_multiword_spec.title = args.title
alternant_multiword_spec.forms = {}
normalize_all_lemmas(alternant_multiword_spec)
detect_all_indicator_specs(alternant_multiword_spec)
check_allowed_overrides(alternant_multiword_spec, args)
local inflect_props = {
slot_table = get_output_adjective_slots(alternant_multiword_spec),
inflect_word_spec = decline_adjective,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
-- Do non-accusative overrides so they get copied to the accusative forms appropriately.
process_overrides(alternant_multiword_spec.forms, args)
set_accusative(alternant_multiword_spec)
-- Do accusative overrides after copying the accusative forms.
process_overrides(alternant_multiword_spec.forms, args, "do acc")
add_categories(alternant_multiword_spec)
if args.json and not from_headword then
return require("Module:JSON").toJSON(alternant_multiword_spec)
end
return alternant_multiword_spec
end
-- Externally callable function to parse and decline an adjective where all
-- forms are given manually. Return value is WORD_SPEC, an object where the
-- declined forms are in `WORD_SPEC.forms` for each slot. If there are no values
-- for a slot, the slot key will be missing. The value for a given slot is a
-- list of objects {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms_manual(parent_args, pos, from_headword, def)
local params = {
special = {},
json = {type = "boolean"}, -- for use with bots
title = {},
}
for slot, _ in pairs(input_adjective_slots) do
params[slot] = {}
end
local args = require("Module:parameters").process(parent_args, params)
local alternant_multiword_spec = {
special = args.special,
title = args.title,
forms = {},
manual = true,
}
check_allowed_overrides(alternant_multiword_spec, args)
-- Do non-accusative overrides so they get copied to the accusative forms appropriately.
process_overrides(alternant_multiword_spec.forms, args)
set_accusative(alternant_multiword_spec)
-- Do accusative overrides after copying the accusative forms.
process_overrides(alternant_multiword_spec.forms, args, "do acc")
add_categories(alternant_multiword_spec)
if args.json and not from_headword then
return require("Module:JSON").toJSON(alternant_multiword_spec)
end
return alternant_multiword_spec
end
-- Entry point for {{cs-adecl}}. Template-callable function to parse and decline
-- an adjective given user-specified arguments and generate a displayable table
-- of the declined forms.
function export.show(frame)
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
show_forms(alternant_multiword_spec)
return make_table(alternant_multiword_spec) .. require("Module:utilities").format_categories(alternant_multiword_spec.categories, lang)
end
-- Entry point for {{cs-adecl-manual}}. Template-callable function to parse and
-- decline an adjective given manually-specified inflections and generate a
-- displayable table of the declined forms.
function export.show_manual(frame)
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms_manual(parent_args)
show_forms(alternant_multiword_spec)
return make_table(alternant_multiword_spec) .. require("Module:utilities").format_categories(alternant_multiword_spec.categories, lang)
end
return export