Модуль:Grammar

Зьвесткі зь Вікіпэдыі — вольнай энцыкляпэдыі
 
Дакумэнтацыя модулю Дакумэнтацыя модулю[прагляд] [рэдагаваць] [гісторыя] [абнавіць]

Гэты модуль прызначаны для вырашэньня некаторых праблемаў у беларускага правапісу.

Публічныя мэтады

isFirstVowel

Вызначае, ці зьяўляецца першая літара дадзенага слова галоснай. Мэтад прызначаны для простага выкарыстаньня ў канструкцыях парсэра, таму, калі першая літара — галосная, то вяртае 1, інакш пусты радок.

  • Беларусь → Не.
  • краіна → Так!
* Беларусь → <tt>{{#if: {{#invoke:Grammar|isFirstVowel|Беларусь}} | Так! | Не. }}</tt>
* Украіна → <tt>{{#if: {{#invoke:Grammar|isFirstVowel|Украіна}} | Так! | Не. }}</tt>

isLastVowel

Вызначае, ці зьяўляецца апошняя літара дадзенага слова галоснай. Мэтад прызначаны для простага выкарыстаньня ў канструкцыях парсэра, таму, калі апошняя літара — галосная, то вяртае 1, інакш пусты радок.

  • Беларусь → Не.
  • Украіна → Так!
* Беларусь → <tt>{{#if: {{#invoke:Grammar|isLastVowel|Беларусь}} | Так! | Не. }}</tt>
* Украіна → <tt>{{#if: {{#invoke:Grammar|isLastVowel|Украіна}} | Так! | Не. }}</tt>

convertShortU

Калі дадзенае слова (1-ы аргумэнт) пачынаецца на у або ў, то зьмяняе першую літару ў залежнасьці ад выбару (2-і аргумэнт), інакш вяртае тое, што было дадзена. Калі 2-і аргумэнт роўны 1, першая літара замяняецца на ў, інакш на у, пры гэтым захоўваецца першапачатковы рэгістар літары. Адпаведна, у 2-і аргумэнт можна закладваць значэньне з мэтаду isLastVowel.

  • ва Ўкраіне
* ва <tt>{{#invoke:Grammar|convertShortU|Украіне|{{#invoke:Grammar|isLastVowel|ва}}}}</tt>

softenPrepo

Зьмякчае прыназоўнік (1-ы парамэтар) перад наступным словам (2-і парамэтар). Калі наступнае слова пачынаецца з [і], то будзе зьмякчаны толькі прыназоўнік бяз (сыходзячы з даверу зьвесткам, што да націску на наступным складзе). Функцыя выдае толькі прыназоўнік.

  • з Германіі
  • бязь візы
  • бязь зьвестак
  • з Індыі
  • бязь індэксу
* <tt>{{#invoke:Grammar|softenPrepo|з|Германіі}}</tt> Германіі // сьвісьцячыя перад мяккімі г/к/х не асымілююцца
* <tt>{{#invoke:Grammar|softenPrepo|бяз|візы}}</tt> візы
* <tt>{{#invoke:Grammar|softenPrepo|бяз|зьвестак}}</tt> зьвестак
* <tt>{{#invoke:Grammar|softenPrepo|з|Індыі}}</tt> Індыі // не спрацавала, бо націск невядомы
* <tt>{{#invoke:Grammar|softenPrepo|бяз|індэксу}}</tt> індэксу // спрацавала, бо ўжытая пераднаціскная форма прыназоўніка

Прыватныя мэтады

isVowel

getCase

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

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

function p.softenPrepo( frame )
    local prepo = frame.args[1]
    local word = frame.args[2]

    if mw.ustring.match( word, "^[Г㥴КкХх]" ) or ( not mw.ustring.match( prepo, "[Зз]$" ) ) then
        return prepo
    end
    
    -- Іі пасьля зычных ня ўлічваецца, бо няма зьвестак пра націск,
    -- таму поўная адпаведнасьць правілам не дасягаецца
    if mw.ustring.match( word, "^[БбВвЗзЛлМмНнПпСсФфЦц][ЕеЁёІіЮюЯяь]" )
        or mw.ustring.match( word, "^[Дд][Зз][ЕеЁёІіЮюЯяь]" )
        or mw.ustring.match( word, "^[ЕеЁёЮюЯя]" ) then
        prepo = prepo .. "ь"
    
    -- Калі прыназоўнік — бяз або слова аднаскладовае, то ў выпадку з пачатковай «і»
    -- можна меркаваць пра націск
    elseif ( mw.ustring.match( prepo, "^[Бб]яз" ) or isSingleSyllable( word ) )
        and mw.ustring.match( word, "^[Іі]" ) then
        prepo = prepo .. "ь"
    end
    
    return prepo
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 number = tonumber( mw.text.trim( args[1] ) )
    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 = tostring( number ) .. "-"

    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