Module:ro-common
Appearance
- This module lacks a documentation subpage. Please create it.
- Useful links: subpage list • links • transclusions • testcases • sandbox
local export = {}
local vowels = "aeiouăâî"
-- Split a word into stem, the last group of vowels and the last group of consonants
-- TODO: make sure this works for all modules
local function split(word)
local stem, vow, cons
if mw.ustring.match(word, "[" .. vowels .. "][iu]$") then
stem, vow, cons = mw.ustring.match(word, "^(.-)([" .. vowels .. "]-)([iu])$")
else
stem, vow, cons = mw.ustring.match(word, "^(.-)([" .. vowels .. "]-)([^" .. vowels .. "]-)$")
end
return stem, vow, cons
end
-- Split a "vowel" group into vowel and semivowels
local function split_vow(vow)
local pre, post = "", ""
if mw.ustring.len(vow) > 1 then
pre, vow, post = mw.ustring.match(vow, "^([iu]?)(.-)([iu]?)$")
end
return pre, vow, post
end
-- Isolate the changing vowels from the stem variations
-- TODO: somehow account for hiatus (deochea)
local function get_vow_changes(words, result)
local all_dupes = true
for _, val in ipairs(words) do
if val ~= words[1] then
all_dupes = false
break
end
end
if all_dupes then
table.insert(result, words[1])
return
else
local split_words = {}
for _, val in ipairs(words) do
if val == "" then
error("Cannot match stems, should only have different vowels")
end
local stem, pre, vow, post, cons
local res = {}
stem, vow, cons = split(val)
pre, vow, post = split_vow(vow)
table.insert(res, stem)
table.insert(res, pre)
table.insert(res, vow)
table.insert(res, post)
table.insert(res, cons)
table.insert(split_words, res)
end
local vowel_appearances, found_vowels = {}, {}
for i, val in ipairs(split_words) do
-- compare pre-vowel, post-vowel, cons
if val[5] ~= split_words[1][5] then
error("Stems differ in something other than main vowels: "
.. words[1] .. ", " .. words[i] .. ", "
.. (val[5] or "fjdfl") .. ", " .. (split_words[1][5] or " fda"))
end
if val[4] ~= split_words[1][4] then
error("Stems differ in something other than main vowels: "
.. words[1] .. ", " .. words[i] .. ", "
.. val[4] .. ", " .. split_words[1][4])
end
if val[2] ~= split_words[1][2] then
error("Stems differ in something other than main vowels: "
.. words[1] .. ", " .. words[i] .. ", "
.. val[2] .. ", " .. split_words[1][2])
end
-- add the vowel
vowel_appearances[val[3]] = true
end
for vow, _ in pairs(vowel_appearances) do
table.insert(found_vowels, vow)
end
table.sort(found_vowels)
-- replace words with stems
for key, _ in ipairs(words) do
words[key] = split_words[key][1]
end
get_vow_changes(words, result)
-- join pre-vowel to last consonant
result[#result] = result[#result] .. split_words[1][2]
-- add all the vowel variations
table.insert(result, table.concat(found_vowels, "-"))
-- add post-vowel + last cons
table.insert(result, split_words[1][4] .. split_words[1][5])
return
end
end
local function find_cons(cons, mode, conj_23, vow)
local n
-- ugly hack
if conj_23 and mode == "â" and cons == "t"
and mw.ustring.find(vow, "[eio]$") then
cons = "ț"
return cons
end
if conj_23 and consonants_23[mode] then
for _, p in ipairs(consonants_23[mode]) do
cons, n = mw.ustring.gsub(cons, p[1], p[2], 1)
if n >= 1 then
return cons
end
end
end
if consonants[mode] then
for _, p in pairs(consonants[mode]) do
cons, n = mw.ustring.gsub(cons, p[1], p[2], 1)
if n >= 1 then
return cons
end
end
end
return cons
end
-- Remove duplicates from an array
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
-- Get consonant changes when followed by -i or -e
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
-- Form the definite singular form of a noun or adjective
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
-- Vowel changes for various word endings
-- TODO: fix for adjectives
local vow_changes = {
-- sort order: aeiouâîă
["a-e"] = { -- zbiera/așeza, a variant of e-ea below
["-"] = "e",
["ă"] = "a",
["e"] = "e",
["i"] = "e",
},
["a-e-ă"] = { -- spăla
["-"] = "ă",
["ă"] = "a",
["e"] = "e",
["i"] = "e",
},
["a-ă"] = { -- arăta
["-"] = "ă",
["ă"] = "a",
["e"] = "a",
["i"] = "ă",
},
["e-ea"] = { -- încerca
["-"] = "e",
["ă"] = "ea",
["e"] = "e",
["i"] = "e",
},
["e-ea-2"] = { -- lepăda
["-"] = {"e", "ea"},
["ă"] = "ea",
["e"] = "e",
["i"] = "e",
},
["e-ă"] = { -- supăra
["-"] = "ă",
["ă"] = "ă",
["e"] = "e",
["i"] = "e",
},
["i-â"] = { -- vinde
["-"] = "â",
["ă"] = "â",
["e"] = "i",
["i"] = "i",
},
["o-oa"] = { -- toca
["-"] = "o",
["ă"] = "oa",
["e"] = "oa",
["i"] = "o",
},
}
-- get a list of stems for each ending
-- given a comma-separated list of slash-separated lists of stems
local function get_stems(stems)
local stem_types = {"-", "ă", "e", "i"}
local res = {}
for _, stype in ipairs(stem_types) do
res[stype] = {}
end
if not stems then
local stem = get_inf_stem()
for _, val in ipairs(stem_types) do
res[val] = stem
end
else
local stem_lists = mw.text.split(stems, " *, *")
for _, stem_set in ipairs(stem_lists) do
-- make a new resi table to hold all the stems
local resi = {}
local stems2, stem_parts = mw.text.split(stem_set, " */ *"), {}
get_vow_changes(stems2, stem_parts)
for _, stype in ipairs(stem_types) do
resi[stype] = {""}
for i = 1, #stem_parts, 2 do
for j, _ in ipairs(resi[stype]) do
resi[stype][j] = resi[stype][j] .. stem_parts[i]
end
-- which syllable this is, counting from the end
local syln = (#stem_parts - i) / 2
if stem_parts[i + 1] then
local vc = vow_changes[stem_parts[i + 1] .. "-" .. syln]
or vow_changes[stem_parts[i + 1]]
if not vc then
-- no vowel alternation found for these vowels
if not mw.ustring.find(stem_parts[i + 1], "\-") then
-- there's only one vowel, so use it
for k, stem in ipairs(resi[stype]) do
resi[stype][k] = stem .. stem_parts[i + 1]
end
else
-- multiple vowels not matching a known vowel alternation
error(stem_parts[i + 1] ..
" is not a valid vowel change")
end
elseif type(vc[stype]) == "string" then
-- only one vowel can be used with that ending
for k, stem in ipairs(resi[stype]) do
resi[stype][k] = stem .. vc[stype]
end
elseif type(vc[stype]) == "table" then
-- multiple vowels for that ending, so make a copy
-- of the partial stem for each one
local copy = resi[stype]
resi[stype] = {}
for _, vow in ipairs(vc[stype]) do
for _, stem in ipairs(copy) do
table.insert(resi[stype], stem .. vow)
end
end
end
end
end
end
-- add only the stems that are not already in res
for _, stype in ipairs(stem_types) do
for _, stemi in ipairs(resi[stype]) do
local is_new = true
for _, stem in ipairs(res[stype]) do
if stem == stemi then
is_new = false
break
end
end
if is_new then
table.insert(res[stype], stemi)
end
end
end
end
end
return res
end
return export