Модуль:Lexer

Материал из Указатель частей и соединений РККА 1941-1945
Перейти к:навигация, поиск

Для документации этого модуля может быть создана страница Модуль:Lexer/doc

local lexer = {}
local cargo = mw.ext.cargo
local global = mw.ext.luaglobal


local ending = { -- и = р,д,в,т,п,мн
['Гв.'] = { 'Гв.',   'Гв.',   'Гв.',   'Гв.',   'Гв.',   'Гв.',   },
['гв.'] = { 'гв.',   'гв.',   'гв.',   'гв.',   'гв.',   'гв.',   },
['и']   = { 'и',     'и',     'и',     'и',     'и',     'и',     },
['тд.'] = { 'тд.',   'тд.',   'тд.',   'тд.',   'тд.',   'тд.',   },
['ада'] = { 'ады',   'аде',   'аду',   'адой',  'аде',   'ады',   stop = 'ж', },    -- бригада
['аза'] = { 'азы',   'азе',   'азу',   'азой',  'азе',   'азы',   stop = 'ж', },    -- база
['аль'] = { 'аля',   'алю',   'аль',   'алем',  'але',   'али',   stop = 'м', },    -- госпиталь
['арк'] = { 'арка',  'арку',  'арк',   'арком', 'арке',  'арки',  stop = 'м', },    -- парк
['вод'] = { 'вода',  'воду',  'вод',   'водом', 'воде',  'воды',  stop = 'м', },    -- взвод
['езд'] = { 'езда',  'езду',  'езд',   'ездом', 'езде',  'езда',  stop = 'м', },    -- бронепоезд
['ено'] = { 'ена',   'ену',   'ено',   'еном',  'ене',   'енья',  stop = 'с', },    -- звено
['ерв'] = { 'ерва',  'ерву',  'ерв',   'ервом', 'ерве',  'ервы',  stop = 'м', },    -- резерв
['зия'] = { 'зии',   'зии',   'зию',   'зией',  'зии',   'зии',   stop = 'ж', },    -- дивизия
['илы'] = { 'ил',    'илам',  'илы',   'илами', 'илах',  'илы',   stop = 'х', },    -- силы
['ион'] = { 'иона',  'иону',  'ион',   'ионом', 'ионе',  'ионы',  stop = 'м', },    -- дивизион
['йон'] = { 'йона',  'йону',  'йон',   'йоном', 'йоне',  'йоны',  stop = 'м', },    -- район
['ище'] = { 'ища',   'ищу',   'ище',   'ищем',  'ище',   'ища',   stop = 'с', },    -- училище
['лад'] = { 'лада',  'ладу',  'лад',   'ладом', 'ладе',  'лады',  stop = 'м', },    -- склад
['лия'] = { 'лии',   'лии',   'лию',   'лией',  'лии',   'лии',   stop = 'ж', },    -- флотилия
['лот'] = { 'лота',  'лоту',  'лот',   'лотом', 'лоте',  'лоты',  stop = 'м', },    -- флот
['лья'] = { 'льи',   'лье',   'лью',   'льей',  'лье',   'льи',   stop = 'ж', },    -- эскадрилья
['мия'] = { 'мии',   'мии',   'мию',   'мией',  'мии',   'мии',   stop = 'ж', },    -- армия
['нда'] = { 'нды',   'нде',   'нду',   'ндой',  'нде',   'нды',   stop = 'ж', },    -- команда
['ние'] = { 'ния',   'нию',   'ние',   'нием',  'нии',   'ния',   stop = 'с', },    -- управление
['нкт'] = { 'нкта',  'нкту',  'нкт',   'нктом', 'нкте',  'нкты',  stop = 'м', },    -- пункт
['олк'] = { 'олка',  'олку',  'олк',   'олком', 'олке',  'олки',  stop = 'м', },    -- полк
['она'] = { 'оны',   'оне',   'ону',   'оной',  'оне',   'оны',   stop = 'ж', },    -- зона
['онт'] = { 'онта',  'онту',  'онт',   'онтом', 'онте',  'онты',  stop = 'м', },    -- фронт
['орт'] = { 'орта',  'орту',  'орт',   'ортом', 'орте',  'орты',  stop = 'м', },    -- транспорт
['ота'] = { 'оты',   'оте',   'оту',   'отой',  'оте',   'оты',   stop = 'ж', },    -- рота
['ппа'] = { 'ппы',   'ппе',   'ппу',   'ппой',  'ппе',   'ппы',   stop = 'ж', },    -- группа
['пус'] = { 'пуса',  'пусу',  'пус',   'пусом', 'пусе',  'пуса',  stop = 'м', },    -- корпус
['рет'] = { 'рета',  'рету',  'рет',   'ретом', 'рете',  'реты',  stop = 'м', },    -- лазарет
['рея'] = { 'реи',   'рее',   'рею',   'реей',  'рее',   'реи',   stop = 'ж', },    -- батарея
['рня'] = { 'рни',   'рне',   'рню',   'рней',  'рне',   'рни',   stop = 'ж', },    -- пекарня
['рон'] = { 'рона',  'рону',  'рон',   'роном', 'роне',  'роны',  stop = 'м', },    -- эскадрон
['рсы'] = { 'рсов',  'рсам',  'рсы',   'рсами', 'рсах',  'рсы',   stop = 'х', },    -- курсы
['руг'] = { 'руга',  'ругу',  'руг',   'ругом', 'руге',  'руга',  stop = 'м', },    -- округ
['ряд'] = { 'ряда',  'ряду',  'ряд',   'рядом', 'ряде',  'ряды',  stop = 'м', },    -- отряд
['ска'] = { 'ск',    'скам',  'ска',   'сками', 'сках',  'ска',   stop = 'х', },    -- войска
['сса'] = { 'ссы',   'ссе',   'ссу',   'ссой',  'ссе',   'ссы',   stop = 'ж', },    -- касса
['таб'] = { 'таба',  'табу',  'таб',   'табом', 'табе',  'табы',  stop = 'м', },    -- штаб
['ток'] = { 'тка',   'тку',   'ток',   'тком',  'тке',   'тки',   stop = 'м', },    -- участок
['тор'] = { 'тора',  'тору',  'тор',   'тором', 'торе',  'тора',  stop = 'м', },    -- сектор
['урт'] = { 'урта',  'урту',  'урт',   'уртом', 'урте',  'урты',  stop = 'м', },    -- гурт
['ция'] = { 'ции',   'ции',   'цию',   'цией',  'ции',   'ции',   stop = 'ж', },    -- Авиация
['ьон'] = { 'ьона',  'ьону',  'ьон',   'ьоном', 'ьоне',  'ьоны',  stop = 'м', },    -- батальон
['бая'] = { 'бой',   'бой',   'бую',   'бой',   'бой',   'бые',   },
['бый'] = { 'бого',  'бому',  'бый',   'бым',   'бом',   'бые',   },
['вая'] = { 'вой',   'вой',   'вую',   'вой',   'вой',   'вые',   },
['вое'] = { 'вого',  'вому',  'вое',   'вым',   'вом',   'вые',   },
['вой'] = { 'вого',  'вому',  'вой',   'вым',   'вом',   'вые',   },
['вый'] = { 'вого',  'вому',  'вый',   'вым',   'вом',   'вые',   },
['кая'] = { 'кой',   'кой',   'кую',   'кой',   'кой',   'кие',   stop = '?', },    -- мастерская
['кий'] = { 'кого',  'кому',  'кий',   'ким',   'ком',   'кие',   },
['кое'] = { 'кого',  'кому',  'кое',   'ким',   'ком',   'кие',   },
['кой'] = { 'кого',  'кому',  'кой',   'ким',   'ком',   'кие',   },
['лая'] = { 'лой',   'лой',   'лую',   'лой',   'лой',   'лые',   },
['лый'] = { 'лого',  'лому',  'лый',   'лым',   'лом',   'лые',   },
['ная'] = { 'ной',   'ной',   'ную',   'ной',   'ной',   'ные',   },
['ний'] = { 'него',  'нему',  'ний',   'ним',   'ном',   'ние',   },
['ное'] = { 'ного',  'ному',  'ное',   'ным',   'ном',   'ные',   },
['ной'] = { 'ного',  'ному',  'ной',   'ным',   'ном',   'ные',   },
['ные'] = { 'ных',   'ным',   'ные',   'ными',  'ных',   'ные',   },
['ный'] = { 'ного',  'ному',  'ный',   'ным',   'ном',   'ные',   },
['чая'] = { 'чей',   'чей',   'чую',   'чей',   'чей',   'чие',   },
['чья'] = { 'чьей',  'чьей',  'чью',   'чьей',  'чьей',  'чьи',   },
}
local adjnoon = {
['мастерская'] = 'ж',
}
local endingGv = { -- и,р,д,в,т,п
['м'] = { 'гвардейский',   'гвардейского',  'гвардейскому',  'гвардейский',   'гвардейским',   'гвардейском',   },
['ж'] = { 'гвардейская',   'гвардейской',   'гвардейской',   'гвардейскую',   'гвардейской',   'гвардейской',   },
['с'] = { 'гвардейское',   'гвардейского',  'гвардейскому',  'гвардейское',   'гвардейским',   'гвардейском',   },
['х'] = { 'гвардейские',   'гвардейских',   'гвардейским',   'гвардейские',   'гвардейскими',  'гвардейских',   },
}
local endingOtd = {
['м'] = { 'отдельный',   'отдельного',  'отдельному',  'отдельный',   'отдельным',   'отдельном',   },
['ж'] = { 'отдельная',   'отдельной',   'отдельной',   'отдельную',   'отдельной',   'отдельной',   },
['с'] = { 'отдельное',   'отдельного',  'отдельному',  'отдельное',   'отдельным',   'отдельном',   },
['х'] = { 'отдельные',   'отдельных',   'отдельным',   'отдельные',   'отдельными',  'отдельных',   },
}

function lexer.declension( str, form, skip_err )
	local words = mw.text.split( str, ' ' )
--	local err = {}
	local key, gender
	for i, word in ipairs( words ) do
		local x = mw.ustring.sub( word, -3, -1 )
		local u = ending[x]
		if u then
			if form ~= 0 then
				words[i] = mw.ustring.sub( word, 1, -4 ) .. u[form]
			end
			if u.stop then
				if u.stop == '?' then
					if adjnoon[word] then
						gender = adjnoon[word]
						key = words[i]
						break
					end
				else
					key = words[i]
					gender = u.stop
					break
				end
			end
		elseif not tonumber( word ) then
			if skip_err then
				return str
			else
				return nil, word
			end
--		elseif not skip_err and not tonumber( word ) then
--			if not tonumber( mw.ustring.sub( word, 1, 1 ) ) then
--				return nil, word
--			end
--		elseif skip_err then
--			return str
		end
	end
	if key or skip_err then
		return table.concat( words, ' ' ), key, gender
	end
	return nil, str
end

function lexer._declension( str, form, text, abbr )
	local report = require( 'Module:Report' )
	local unit = report.bigfuller( str )
	if text then
		if text == '!' then
			return unit
		end
	elseif abbr then
		text = report.shorter( unit )
	elseif form == 0 then
		text = unit
	else
		text = lexer.declension( unit, form )
	end
	global.add( 'UNIT-IN-TEXT', unit )
	return '<span class=unit-in-text data-unit="' .. unit .. '">[[' .. unit .. '|' .. ( text or '<span class=error>(Ошибка! Не удалось просклонять)</span>' ) .. ']]</span>'
end

function lexer.Declension( frame )
	local args = require( 'Module:Tools' ).checkargs( frame:getParent().args, {
			true, true
--			form = 0  -- форма (падеж) задается в шаблоне, а не в вызове
		} )
	-- падеж задается в шаблоне
	-- в вызове задаются
	-- первый параметр — юнит (к нему мы применяем fuller)
	-- второй параметр — либо точка (тогда мы к юниту применим shorter), либо "!" (тогда мы вернем юнит без склонения и ссылки)
	local form = tonumber( frame.args.form or 0 )
	local text = args[2]
	local abbr = text == '.'
	if abbr then
		text = nil
	end
	return lexer._declension( args[1], form, text, abbr )
end

function lexer.Check( frame )
	local cq
	local out = {}
	local offset = 0
	repeat
		cq = cargo.query( 'unitpages', '_pageName, unit,special', { offset = offset, limit = 5000, orderBy = 'unit,special' } )
		for _, u in ipairs( cq ) do
			local unit = u.unit
			local v, err = lexer.declension( unit, 1 )
			if v then
				table.insert( out, unit .. ' / ' .. v )
			else
				table.insert( out, unit .. ': <span class=error>' .. err .. '</span>' )
			end
--[[
			local ctg = lexer.category( unit ) or '—'
			local ctgGood = categories.names[ctg] or { group = '—' }
			local abbr = lexer.shorter( unit ) or '—'
			if abbr == unit then
				local unitLow = mw.ustring.lower( mw.ustring.sub( unit, 1, 1 ) ) .. mw.ustring.sub( unit, 2, -1 )
				abbr = lexer.shorter( unitLow )
			end
			table.insert( out, unit .. '/' .. ctg .. '/' .. ctgGood.group .. '/' .. abbr )
			lexer.gene = nil
--]]
		end
		offset = offset + #cq
	until #cq == 0
	return table.concat( out, '<br>' )
end



return lexer