Module:ro-common

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