Module:ro-adjective
Jump to navigation
Jump to search
- The following documentation is located at Module:ro-adjective/documentation. [edit] Categories were auto-generated by Module:module categorization. [edit]
- Useful links: subpage list • links • transclusions • testcases • sandbox
This module implements {{ro-decl-adj}}
.
local export = {}
local data = {}
data.forms = {}
local form_names = {
"na_indef_sg_m",
"na_indef_sg_f",
"na_indef_pl_m",
"na_indef_pl_f",
"na_def_sg_m",
"na_def_sg_f",
"na_def_pl_m",
"na_def_pl_f",
"gd_indef_sg_m",
"gd_indef_sg_f",
"gd_indef_pl_m",
"gd_indef_pl_f",
"gd_def_sg_m",
"gd_def_sg_f",
"gd_def_pl_m",
"gd_def_pl_f",
}
local consonants = {
i = {
str = 'ștr';
st = 'șt';
sc = 'șt';
d = 'z';
s = 'ș';
t = 'ț';
x = 'cș';
},
e = {
sc = 'șt';
}
}
-- these adjectives have different defaults
local endings = {
{pattern = "(([stz])or)$", fs = "%2oare", mp = "%2ori", fp = "%2oare"},
{pattern = "os$", fs = "oasă", mp = "oși", fp = "oase"},
{pattern = "iesc$", fs = "iască", mp = "iești", fp = "iești"},
{pattern = "esc$", fs = "ească", mp = "ești", fp = "ești"},
{pattern = "(([iy])an)$", fs = "%2ană", mp = "%2eni", fp = "%2ene"},
{pattern = "ean$", fs = "eană", mp = "eni", fp = "ene"},
{pattern = "eț$", fs = "eață", mp = "eți", fp = "ețe"},
{pattern = "iu$", fs = "ie", mp = "ii", fp = "ii"},
}
local m_links = require("Module:links")
local lang = require("Module:languages").getByCode("ro")
local PAGENAME = mw.title.getCurrentTitle().text
local function make_definite(word, gender)
local definite
if gender == "m" or gender == "n" then
if word:find("u$") then
definite = word .. "l"
elseif word:find("e$") then
definite = word .. "le"
else
definite = word .. "ul"
end
elseif gender == "f" then
if word:find("ă$") then
definite = word:gsub("ă$", "a")
elseif mw.ustring.find(word, "[aeiouăâî]ie") then
definite = word:gsub("e$", "a")
elseif mw.ustring.find(word, "ie$") then
definite = word:gsub("e$", "a")
elseif mw.ustring.find(word, "e$") then
definite = word .. "a"
elseif mw.ustring.find(word, "a$") then
definite = word .. "ua"
end
else
error("Invalid or missing gender")
end
return definite
end
local function make_feminine(word)
local f
if word:find("e$") then
f = word
elseif word:find("[aăâiîeou]i$") then
f = word .. "e"
elseif word:find("iu$") then
f = mw.ustring.gsub(word, "u$", "e")
elseif word:find("u$") then
f = word:sub(1, -2) .. "ă"
elseif word:match("[cg]h?i$") then
f = word:sub(1, -2) .. "e"
elseif word:match("[^aioăâî]$") then
f = word .. "ă"
else
error("Feminine of \"" .. word .. "\" could not be generated automatically")
end
if f and f:match("[âei]ă$") then
f = f:gsub("ă$", "e")
end
return f
end
local function split(word)
local stem, cons
if word:match('[aeiouăâî][iu]$') then
stem, cons = word:match('^(.-[aeiouăâî]-)([iu])$')
else
stem, cons = word:match('^(.-[aeiouăâî]-)([bcdfghj-np-tv-zșț]-)$')
end
return stem, cons
end
local function find_cons(cons, mode)
for i = -3, -1 do
if consonants[mode][mw.ustring.sub(cons, i)] and not mw.ustring.match(mw.ustring.sub(cons, 1, i-1), "^[șj]$") then
cons = mw.ustring.sub(cons, 1, i-1) .. consonants[mode][mw.ustring.sub(cons, i)]
break
end
end
return cons
end
local function make_plural(word, g)
local pl
local suf1, suf2, pre1 = mw.ustring.sub(word, -1), mw.ustring.sub(word, -2), mw.ustring.sub(word, 1, -2)
if g == 'm' then
if suf1 == 'i' then
pl = word
else
local stem, cons = split(word:match('^(.-)[eu]?$'))
cons = find_cons(cons, 'i')
pl = stem .. cons .. 'i'
end
elseif g == 'f' then
if suf1 == 'a' then
if suf2 == 'ea' then
pl = pre1 .. 'le'
elseif suf2 == 'ia' then
pl = pre1 .. 'ele'
else
pl = word .. 'le'
end
else
if suf1 == 'e' then
pl = word
elseif suf1 == 'ă' then
local stem, cons = split(word:match('^(.-)ă$'))
cons = find_cons(cons, 'e')
pl = stem .. cons .. 'e'
end
end
end
return pl
end
local function remove_duplicates(array)
local existing = {}
for i, val in ipairs(array) do
if existing[val] then
table.remove(array, i)
if array.maxindex then
array.maxindex = array.maxindex - 1
end
else
existing[val] = true
end
end
end
local function make_indef_sg_m(lemma, only)
--Try to recreate the masculine singular indefinite form if it's
--not the lemma. Many of these situations will never happen.
local ret = lemma
if only.def then
if only.pl then
if only.f then
--def-pl-f
ret = lemma:match("(.+)ele$")
else
--def-pl-m
ret = lemma:match("(.+)ii$")
end
else
if only.f then
--def-sg-f
ret = lemma:match("(.+)a$")
else
--def-sg-m
ret = lemma:match("(.+)ul$")
end
end
else
if only.pl then
if only.f then
--indef-pl-f
ret = lemma:match("(.+)e$")
else
--indef-pl-m
ret = lemma:match("(.+)i")
end
else
if only.f then
--indef-sg-f
ret = lemma:match("(.+)ă")
end
end
end
if not ret then
error("Could not recreate the masculine indefinite singular form.")
end
return ret
end
--also used in [[Module:ro-headword]]
function export.make_basic_forms(ms, fs, mp, fp, i_mode, only)
local base = make_indef_sg_m(ms[1], only)
local ending = false
local param_track = {redundant = false, needed = false}
for i, val in ipairs(endings) do
if base:match(val.pattern) then
local match = base:match(val.pattern)
require("Module:debug").track("ro-adjective/" .. match)
if fs[1] or mp[1] or fp[1] or i_mode then
require("Module:debug").track("ro-adjective/" .. match .. "/custom")
require("Module:debug").track("ro-adjective/custom")
else
require("Module:debug").track("ro-adjective/" .. match .. "/default")
require("Module:debug").track("ro-adjective/default")
end
ending = i
break
end
end
if not fs[1] then
if ending then
local form = mw.ustring.gsub(base, endings[ending].pattern, endings[ending].fs)
table.insert(fs, 1, form)
else
table.insert(fs, 1, make_feminine(base))
end
if only.def then
fs[1] = make_definite(fs[1], "f")
end
if fs.maxindex == 0 then
fs.maxindex = 1
end
remove_duplicates(fs)
else
if (ending and mw.ustring.gsub(base, endings[ending].pattern, endings[ending].fs)
or make_feminine(base)) == fs[1] then
param_track.redundant = true
else
param_track.needed = true
end
end
if not mp[1] then
if ending then
local form = mw.ustring.gsub(base, endings[ending].pattern, endings[ending].mp)
table.insert(mp, 1, form)
else
table.insert(mp, 1, make_plural(base, "m"))
end
if only.def then
mp[1] = mp[1] .. "i"
end
if mp.maxindex == 0 then
mp.maxindex = 1
end
remove_duplicates(mp)
else
if (ending and mw.ustring.gsub(base, endings[ending].pattern, endings[ending].mp)
or make_plural(base, "m")) == mp[1] then
param_track.redundant = true
else
param_track.needed = true
end
end
if i_mode then
--mw.clone does not work
for i = 1, mp.maxindex do
fp[i] = mp[i]
end
fp.maxindex = mp.maxindex
else
if only.def then
if not fp[1] then
table.insert(fp, 1, make_plural(make_feminine(base), "f") .. "le")
if fp.maxindex == 0 then
fp.maxindex = 1
end
end
else
--for each feminine singular form, generate a feminine plural form if
--one has not already been provided
local newindex = 0
for i, form in ipairs(fs) do
if fp[i] == "-" then
fp[i] = nil
else
newindex = i
if not fp[i] then
if ending and i == 1 then
local form = mw.ustring.gsub(base, endings[ending].pattern, endings[ending].fp)
table.insert(fp, 1, form)
else
table.insert(fp, i, make_plural(form, "f"))
end
if only.def then
fp[i] = fp[i] .. "le"
end
newindex = i
else
if ((ending and i == 1) and mw.ustring.gsub(base, endings[ending].pattern, endings[ending].fp)
or make_plural(form, "f")) == fp[i] then
param_track.redundant = true
else
param_track.needed = true
end
end
end
end
fp.maxindex = newindex
if fp.maxindex == 0 then
error("There must be at least one feminine plural form")
end
end
remove_duplicates(fp)
end
if param_track.redundant then
require("Module:debug").track("ro-adjective/parameters/redundant")
end
if param_track.needed then
require("Module:debug").track("ro-adjective/parameters/needed")
end
if not param_track.redundant and not param_track.needed then
require("Module:debug").track("ro-adjective/parameters/none")
end
end
--Process forms that were given explicitly
local function process_explicit_forms(data, extra_args)
for arg, val in pairs(extra_args) do
local arg_parts, count, valid = {}, 0, false
for i, part in ipairs(mw.text.split(arg, "_")) do
arg_parts[part] = true
count = count + 1
end
for i, form in ipairs(form_names) do
local counter = 0
for j, part in ipairs(mw.text.split(form, "_")) do
if arg_parts[part] then
counter = counter + 1
end
end
if count == counter then
if val == "-" then
data.forms[form] = nil
else
data.forms[form] = {val}
end
valid = true
end
end
if not valid then
error("The parameter \"" .. arg .. "\" is not used by this template.")
end
end
end
local function make_table(data)
data.info = table.concat(data.info, ", ")
if data.info == "" then data.info = nil end
local function show_form(form)
if not form then
return "—"
elseif type(form) ~= "table" then
error("a non-table value was given in the list of inflected forms.")
elseif #form == 0 then
return "—"
end
local ret = {}
for key, subform in ipairs(form) do
table.insert(ret, m_links.full_link({lang = lang, term = subform}))
end
return table.concat(ret, "<br/>")
end
local function repl(param)
if param == "lemma" then
return m_links.full_link({lang = lang, alt = data.lemma}, "term")
elseif param == "info" then
return data.info and " (" .. data.info .. ")" or ""
else
return show_form(data.forms[param])
end
end
local result = [=[
<div class="NavFrame">
<div class="NavHead" style="background:#b0bed3" align=center>Declension of {{{lemma}}}{{{info}}}</div>
<div class="NavContent">
{| border="1px solid #000000" style="border-collapse:collapse; width:100%; background:#F0F0F0; text-align:center" class="inflection-table"
|-
! colspan="2" style="background:#b0bed3;width:28%" |
! colspan="3" style="background:#b0bed3;width:36%" | singular
! colspan="3" style="background:#b0bed3;width:36%" | plural
|-
! style="width:20%; background:#c0cfe4" |
! style="width:16%; background:#d0d0d0" |
! style="width:8%; background:#d0d0d0" | masculine
! style="width:8%; background:#d0d0d0" | neuter
! style="width:16%; background:#d0d0d0" | feminine
! style="width:16%; background:#d0d0d0" | masculine
! style="width:8%; background:#d0d0d0" | neuter
! style="width:8%; background:#d0d0d0" | feminine
|-
! rowspan="2" style="height:4em;background:#c0cfe4" | nominative/ <br/> accusative
! style="background:#d0d0d0" | indefinite
| colspan="2" | {{{na_indef_sg_m}}}
| {{{na_indef_sg_f}}}
| {{{na_indef_pl_m}}}
| colspan="2" | {{{na_indef_pl_f}}}
|-
! style="background:#d0d0d0" | definite
| colspan="2" | {{{na_def_sg_m}}}
| {{{na_def_sg_f}}}
| {{{na_def_pl_m}}}
| colspan="2" | {{{na_def_pl_f}}}
|-
! rowspan="2" style="height:4em;background:#c0cfe4" | genitive/ <br/> dative
! style="background:#d0d0d0" | indefinite
| colspan="2" | {{{gd_indef_sg_m}}}
| {{{gd_indef_sg_f}}}
| {{{gd_indef_pl_m}}}
| colspan="2" | {{{gd_indef_pl_f}}}
|-
! style="background:#d0d0d0" | definite
| colspan="2" | {{{gd_def_sg_m}}}
| {{{gd_def_sg_f}}}
| {{{gd_def_pl_m}}}
| colspan="2" | {{{gd_def_pl_f}}}
|}</div></div>]=]
return (mw.ustring.gsub(result, "{{{([a-z0-9_]+)}}}", repl))
end
function export.show(frame)
local args = frame:getParent().args
if args[12] then
require("Module:debug").track("ro-decl-adj/old")
local params = {
[1] = {list = true, allow_holes = true},
}
args = require("Module:parameters").process(args, params)
data.info = {}
local form_order = {
"na_indef_sg_m",
"na_indef_sg_f",
"na_indef_pl_m",
"na_indef_pl_f",
"na_def_sg_m",
"na_def_sg_f",
"na_def_pl_m",
"na_def_pl_f",
"gd_def_sg_m",
"gd_def_sg_f",
"gd_def_pl_m",
"gd_def_pl_f",
}
for key, form in ipairs(form_order) do
data.forms[form] = {args[1][key]}
end
data.forms.gd_indef_sg_m = mw.clone(data.forms.na_indef_sg_m)
data.forms.gd_indef_sg_f = mw.clone(data.forms.na_indef_pl_f)
data.forms.gd_indef_pl_m = mw.clone(data.forms.na_indef_pl_m)
data.forms.gd_indef_pl_f = mw.clone(data.forms.na_indef_pl_f)
data.lemma = PAGENAME
else
require("Module:debug").track("ro-decl-adj/new")
local params = {
[1] = {},
["f"] = {list = true, allow_holes = true},
["mp"] = {list = true, allow_holes = true},
["fp"] = {list = true, allow_holes = true},
["pl"] = {list = true, allow_holes = true},
["lemma"] = {},
["only"] = {},
}
local extra_args
args, extra_args = require("Module:parameters").process(args, params, true)
data.lemma = args["lemma"] or PAGENAME
data.info = {}
data.only = {}
if args.only then
for i, val in ipairs(mw.text.split(args.only, "-")) do
data.only[val] = true
end
end
local f = data.forms
for i, form in ipairs(form_names) do
f[form] = {}
end
f.na_indef_sg_m = {make_indef_sg_m(data.lemma, data.only)}
local modes = {}
if args[1] then
for key, val in ipairs(mw.text.split(args[1], "-")) do
modes[val] = true
end
end
if modes.det then
data.only.indef = true
end
local only_modes = {
["indef"] = "indefinite",
["def"] = "definite",
["sg"] = "singular",
["pl"] = "plural",
["m"] = "masculine",
["f"] = "feminine",
}
if modes.inv then
table.insert(data.info, "invariable")
for key, form in ipairs(form_names) do
if form:find("indef") then
f[form] = {data.lemma}
end
end
else
f.na_indef_sg_f, f.na_indef_pl_m, f.na_indef_pl_f = args["f"], args["pl"].maxindex > 0 and args["pl"] or args["mp"], args["pl"].maxindex > 0 and args["pl"] or args["fp"]
export.make_basic_forms(f.na_indef_sg_m, f.na_indef_sg_f, f.na_indef_pl_m, f.na_indef_pl_f, modes.i, {})
if modes.det then
table.insert(data.info, "determiner declension")
f.gd_indef_sg_m = {f.na_indef_sg_m[1]:match("^(.*)[eu]?$") .. "ui"}
f.gd_indef_sg_f = {f.na_indef_sg_m[1]:match("^(.*)[eu]?$") .. "ei"}
f.gd_indef_pl_m = {f.na_indef_sg_m[1]:match("^(.*)[eu]?$") .. "or"}
f.gd_indef_pl_f = mw.clone(f.gd_indef_pl_m)
else
--forms derived from the masculine singular
f.na_def_sg_m = {make_definite(f.na_indef_sg_m[1], "m")}
f.gd_def_sg_m = {f.na_def_sg_m[1]:find("e$") and f.na_def_sg_m[1]:sub(1, -2) .. "ui" or f.na_def_sg_m[1] .. "ui"}
f.gd_indef_sg_m = {f.na_indef_sg_m[1]}
--forms derived from the feminine singular
for i = 1, f.na_indef_sg_f.maxindex do
if f.na_indef_sg_f[i] ~= nil then
table.insert(f.na_def_sg_f, make_definite(f.na_indef_sg_f[i], "f"))
end
end
--forms derived from the masculine plural
for i = 1, f.na_indef_pl_m.maxindex do
if f.na_indef_pl_m[i] ~= nil then
table.insert(f.na_def_pl_m, f.na_indef_pl_m[i] .. "i")
table.insert(f.gd_indef_pl_m, f.na_indef_pl_m[i])
table.insert(f.gd_def_pl_m, f.na_indef_pl_m[i] .. "lor")
end
end
--forms derived from the feminine plural
for i = 1, f.na_indef_pl_f.maxindex do
if f.na_indef_pl_f[i] ~= nil then
table.insert(f.na_def_pl_f, f.na_indef_pl_f[i] .. "le")
table.insert(f.gd_indef_sg_f, f.na_indef_pl_f[i])
table.insert(f.gd_indef_pl_f,f.na_indef_pl_f[i])
table.insert(f.gd_def_pl_f, f.na_indef_pl_f[i] .. "lor")
if f.na_indef_pl_f[i]:find("[^aăâeiîou]ii$") then
--this could cause issues if the feminine singular and
--feminine plural are not in sync
table.insert(f.gd_def_sg_f, f.na_indef_sg_f[i] .. "i")
else
table.insert(f.gd_def_sg_f, f.na_indef_pl_f[i] .. "i")
end
end
end
end
process_explicit_forms(data, extra_args)
end
for key, name in pairs(only_modes) do
if data.only[key] then
table.insert(data.info, name .. " only")
for i, form in ipairs(form_names) do
if not ("_" .. form .. "_"):find("_" .. key .. "_") then
f[form] = nil
end
end
end
end
end
return make_table(data)
end
return export