Модуль:по-слогам eo
Юнит-тест для модуля (на момент написания не работал по причине отсутствия модуля UnitTest): Обсуждение модуля:по-слогам eo/testcases
local mvorto = {};
--[[
Возвращает слог под указанным номером, либо пустую строку, если такого слога нет
Использование:
{{#invoke:по-слогам eo|getSilabo|слово|номер_слога}}
или
{{#invoke:по-слогам eo|getSilabo|vorto=слово|silabnumero=номер_слога}}
Параметры:
vorto: строка, в которой необходимо найти указанный слог
silabnumero: номер слога, который необходимо вернуть. Если не указано, то
будет возвращён первый слог
]]
function mvorto.getSilabo(frame)
local new_args = mvorto._getParameters( frame.args, {'vorto', 'silabnumero'} )
local vorto = new_args['vorto'] or ''
local silabnumero = tonumber(new_args['silabnumero']) or 1
local silaboj = mvorto.getSilaboj(vorto, false)
if type(silaboj[silabnumero]) ~= nil then
return silaboj[silabnumero]
else
return ''
end
end
--[[
Возвращает таблицу (массив) слогов указанного слова
Параметры:
s: слово, для разбора на слоги
onlysilaboj: вернуть только массив слогов (без ударений, дефисов и точек)
]]
function mvorto.getSilaboj(s, onlysilaboj)
local vortlongo = string.len(s)
local slogi = {}
if s ~= nil and s ~= '' then
if string.find( s, '-' ) == nil then
slogi = mvorto._getSl(s)
else
--Если есть дефис, резать по дефису и добавлять его как слог
for v in string.gmatch(s, "([^\\-]+)") do
if slogi == nil or #slogi == 0 then
slogi = mvorto._getSl(v)
else
if onlysilaboj ~= true then table.insert(slogi, '-') end
slogi = mvorto.mergeTables(slogi, mvorto._getSl(v))
end
end
end
if onlysilaboj ~= true then
finlitero = string.sub(s, vortlongo, vortlongo )
if #slogi < 2 then
slogi[#slogi] = mvorto.makeStress( slogi[#slogi] )
else
if finlitero == "'" then
slogi[#slogi] = mvorto.makeStress( slogi[#slogi] )
else
if slogi[#slogi-1] == '-' then
slogi[#slogi-2] = mvorto.makeStress( slogi[#slogi-2] )
else
slogi[#slogi-1] = mvorto.makeStress( slogi[#slogi-1] )
end
end
if string.len(slogi[#slogi]) == 1 and slogi[#slogi-1] ~= '-' then
table.insert(slogi, #slogi, '.')
end
if string.len(slogi[1]) == 1 and slogi[2] ~= '-' then
table.insert(slogi, 2, '.')
end
end
end
else
return {''}
end
return slogi
end
--[[
Заменяет все гласные на гласные под ударением
Параметры:
s: строка, для обработки
]]
function mvorto.makeStress(s)
s = string.gsub(s, "a", "á")
s = string.gsub(s, "A", "Á")
s = string.gsub(s, "o", "ó")
s = string.gsub(s, "O", "Ó")
s = string.gsub(s, "e", "é")
s = string.gsub(s, "E", "É")
s = string.gsub(s, "i", "í")
s = string.gsub(s, "I", "Í")
s = string.gsub(s, "u", "ú")
s = string.gsub(s, "U", "Ú")
return s;
end
function mvorto._getSl(s)
local vectors = mw.loadData("Module:по-слогам eo/kombinations")
local result = ""
local slogi = {}
local vesbukv = mw.loadData("Module:по-слогам eo/masses")
local notes = ""
--Так как некоторые спецефичные для алфавита эсперанто буквы (ĉ, ĝ, ŭ и др),
--а так же их заменяющие сочетания букв (cx, sx, ux и тд) занимают
--по 2 символа, то работаем не с набором символов, а с набором их сочетаний
local literoj = {}
local vortdlin = string.len(s)
local v = ''
local preterlasu = false
for i = 1,vortdlin do
if preterlasu then
preterlasu = false
else
if i+1 <= vortdlin then
v = string.lower(string.sub(s, i, i+1))
else
v = string.sub(s, i, i)
end
if v == 'ĉ' or v == 'ĝ' or v == 'ĥ' or v == 'ĵ' or v == 'ŝ' or
v == 'ŭ' or v == 'cx' or v == 'gx' or v == 'hx' or v == 'jx' or
v == 'sx' or v == 'ux' then
--так как проверка была по строчным быквам, берём сноваоригинал
v = string.sub(s, i, i+1)
preterlasu = true
else
v = string.sub(s, i, i)
if type(vesbukv[v]) == nil then
v = 'a'
end
end
table.insert(literoj, v)
end
end
for i,v in pairs(literoj) do
v = string.lower(v)
if v == 'ĉ' then
v = 'cx'
elseif v == 'ĝ' then
v = 'gx'
elseif v == 'ĥ' then
v = 'hx'
elseif v == 'ĵ' then
v = 'jx'
elseif v == 'ŝ' then
v = 'sx'
elseif v == 'ŭ' then
v = 'ux'
end
v = vesbukv[v]
if v == nil then
v = 1
end
notes = notes .. v
end
local prefx = '';
local postfx = '';
v = '';
local ia = 0;
local ib;
for i = 1,#literoj do
v = string.sub(notes, i, i);
if v == "3" then
if prefx == '' and #slogi == 0 then
ia = i
prefx = table.concat(literoj, '', 1, ia)
else
local vect
ib = i
local kombin = string.sub(notes, ia+1, ib-1)
if string.len(kombin) == 0 then
vect = 0
else
vect = vectors[kombin]
-- Если дифтонг, то сдвигаем вектор разреза слога
if vect == 0
and ( literoj[ia+1] == "ux"
or literoj[ia+1] == "j" ) then
vect = 1
end
end
if vect > 0 then
postfx = table.concat(literoj, '', ia+1, ia+vect)
else
postfx = ''
end
local newslog = prefx .. postfx
table.insert(slogi, newslog)
prefx = table.concat(literoj, '', ia+vect+1, ib)
ia = ib
ib = nil
end
end
end
if ia ~= vortdlin then
local newslog = prefx .. table.concat(literoj, '', ia+1, #literoj)
table.insert(slogi, newslog)
else
table.insert(slogi, prefx)
end
return slogi;
end
function mvorto.mergeTables( t1, t2 )
for k,s in pairs( t2 ) do table.insert( t1, s ) end
return t1;
end
function mvorto._getParameters( frame_args, arg_list )
local new_args = {};
local index = 1;
local value;
for i,arg in ipairs( arg_list ) do
value = frame_args[arg]
if value == nil then
value = frame_args[index];
index = index + 1;
end
new_args[arg] = value;
end
return new_args;
end
return mvorto