Перайсці да зместу

Модуль:Grammar

З Вікіпедыі, свабоднай энцыклапедыі

-- Модуль «Граматыка»
-- Розныя граматычныя функцыі для беларускай мовы

local p = {}

-- Ці з’яўляецца дадзеная літара галоснай
local function isVowel( letter )
    if mw.ustring.match( mw.ustring.lower( letter ), "^[аеёіоуыэюя]$" ) then
        return true
    else
        return false
    end
end

-- Ці з’яўляецца аргумент аднаскладовым словам
-- Аргумент можа ўтрымліваць некалькі слоў —
-- улічвацца будзе толькі першае
local function isSingleSyllable( word )
    local spacePos = mw.ustring.find( word, "[%s%p]" )
    if spacePos then
        word = mw.ustring.sub( word, 1, spacePos )
    end
    
    local _,count = mw.ustring.gsub( mw.ustring.lower( word ), "[аеёіоуыэюя]", "" )

    if count == 1 then
        return true
    else
        return false
    end
end

-- Даведацца пра рэгістр літары
-- true — вялікі, false — малы
local function getCase( letter )
    if mw.ustring.match( letter, "^%l$" ) == nil then
        return true
    else
        return false
    end
end

-- Першая літара аргумента — галосная
function p.isFirstVowel( frame )
    local chr = mw.ustring.sub( frame.args[1], 0, 1 )
    if isVowel( chr ) then
        return "1"
    else
        return ""
    end
end

-- Апошняя літара аргумента — галосная
function p.isLastVowel( frame )
    local chr = mw.ustring.sub( frame.args[1], mw.ustring.len( frame.args[1] ) )
    if isVowel( chr ) then
        return "1"
    else
        return ""
    end
    return chr
end

-- Ставіць першай літарай у/ў па жаданьні выклікаючага
-- Змяняемае слова мусіць пачынацца з «у» альбо «ў»,
-- рэгістр захоўваецца.
-- mode: 1 — пасля галоснай, іншае — пасля зычнай
function p.convertShortU( frame )
    local first = mw.ustring.sub( frame.args[1], 0, 1 )
    if mw.ustring.match( first, "[УуЎў]" ) ~= first then -- працуем толькі з у/ў
        return frame.args[1]
    end
    
    local body = mw.ustring.sub( frame.args[1], 2 )
    local upperCase = getCase( first )
    
    if frame.args[2] == "1" then
        if upperCase then
            return "Ў" .. body
        else
            return "ў" .. body
        end
    else
        if upperCase then
            return "У" .. body
        else
            return "у" .. body
        end
    end
    return first
end

local function _ordinalGenderCase( gender, case, secondThird, animate )
    local switches = {
        ["мужчынскі"] = {
            ["назоўны"] = secondThird and "і" or "ы",
            ["родны"] = "га",
            ["давальны"] = "му",
            ["вінавальны"] = ( not animate ) and "ы" or "га",
            ["творны"] = "м",
            ["месны"] = "м"
        },
        ["жаночы"] = {
            ["назоўны"] = "я",
            ["родны"] = "й",
            ["давальны"] = "й",
            ["вінавальны"] = "ю",
            ["творны"] = "й",
            ["месны"] = "й"
        },
        ["ніякі"] = {
            ["назоўны"] = "е",
            ["родны"] = "га",
            ["давальны"] = "му",
            ["вінавальны"] = "е",
            ["творны"] = "м",
            ["месны"] = "м"
        }
    }
    
    if not switches[gender] then gender = "мужчынскі" end
    if not switches[gender][case] then case = "назоўны" end

    return switches[gender][case]
end

function p.ordinalNumber( frame )
    local args = {}
    for k, v in pairs( frame:getParent().args ) do
        if type( k ) == "string" then
            args[mw.ustring.lower( k )] = v
        else
            args[k] = v
        end
    end

    local numeral = mw.text.trim( args[1] )
    numeral = string.gsub(numeral, "%s+", "")
    local number = tonumber( numeral )
    if number == nil then return "" end

    local gender = args["род"] and ( mw.ustring.lower( mw.text.trim( args["род"] ) ) == "" and "мужчынскі" or mw.ustring.lower( mw.text.trim( args["род"] ) ) ) or "мужчынскі"
    local case = args["склон"] and ( mw.ustring.lower( mw.text.trim( args["склон"] ) ) == "" and "назоўны" or mw.ustring.lower( mw.text.trim( args["склон"] ) ) ) or "назоўны"
    local animate = args["жывы"] and ( ( mw.ustring.lower( mw.text.trim( args["жывы"] ) ) == "" or mw.ustring.lower( mw.text.trim( args["жывы"] ) ) == "0" ) and false or true ) or false
    
    local s = args[1] .. "-"

    if math.floor( ( number % 100 ) / 10 ) ~= 1 and ( number % 10 == 2 or number % 10 == 3 ) then
        s = s .. _ordinalGenderCase( gender, case, true, animate )
    else
        if number < 10 and ( number % 10 == 2 or number % 10 == 3 ) then
            s = s .. _ordinalGenderCase( gender, case, true, animate )
        else
            s = s .. _ordinalGenderCase( gender, case, false, animate )
        end
    end
    
    return s
end

return p