Модуль:inflection-data

Материал из Викисловаря
Документация

Этот модуль никак не связан с Модуль:inflection. В будущем планируется инкапсулировать его в последний.

-- Inflection v1.5.2
-- 2015-07-04

local export = {}
local data
local base
local args
local forms
local affixes

-- Utility function to clone table
local function clone(original)
    local copy = {}
    for key, value in pairs(original) do
        copy[key] = value
    end
    return copy
end

-- Utility function to get current PAGENAME and related
local function get_base()
	local PAGENAME = mw.title.getCurrentTitle().text
	local SUBPAGENAME = mw.title.getCurrentTitle().subpageText
	local NAMESPACE = mw.title.getCurrentTitle().nsText
	
	if NAMESPACE == 'User' or NAMESPACE == 'Участник' then
		return SUBPAGENAME
	end
	return PAGENAME
end

-- Function to local corresponding data-module
local function load_data(frame)
	local data_name = frame.args['type']
	-- if data_name == '' then
	if data_name ~= 'uz-noun' then
		return nil
	end
	return mw.loadData("Module:inflection-data/data/" .. data_name);
end

-- Function to get value from argument (that was sent from template)
local function get_arg_value(arg_name)
	local arg_value = ''
	if args[arg_name] then
		arg_value = args[arg_name]
	end
	return arg_value
end

-- Function to get value from 'affixes'
local function get_affix_value(name)
	local value = ''
	if affixes[name] then
		value = affixes[name]
	end
	return value
end

local function apply_affixes(value)
	for affix_key, affix_value in pairs(affixes) do
		value = value:gsub("%<" .. affix_key .. "%>", affix_value)
	end
	return value
end

local function apply_forms(value)  -- TODO: join with function `apply_affixes`
	for form_key, form_value in pairs(forms) do
		value = value:gsub("%<" .. form_key .. "%>", form_value)
	end
	return value
end

-- Checking function (used in 'conditions') 
-- Checks last or pre-last letters of base word
local function check_last(param_name, param_value)
	-- put string into table (if we need it):
	if type(param_value) == 'string' then
		param_value = {param_value}
	end
	-- check all values:
	if param_name:match("_NOT$") ~= nil then
		for j, value in pairs(param_value) do
			if param_name == 'last_NOT' and base:match(value .. "$") ~= nil then
				return false
			elseif param_name == 'pre_last_NOT' and base:match(value .. ".$") ~= nil then
				return false
			end
		end
		return true
	else
		for j, value in pairs(param_value) do
			if param_name == 'last' and base:match(value .. "$") ~= nil then
				return true
			elseif param_name == 'pre_last' and base:match(value .. ".$") ~= nil then
				return true
			end
		end
		return false
	end
end

-- Checking function (used in 'conditions') 
-- Checks values of arguments (sent from template) or vars (from section 'affixes')
local function check_var(param_name, param_value)
	local NOT = false
	local var_name
	if param_name:match("_NOT$") ~= nil then
		NOT = true
		param_name = param_name:sub(1, -5)
		-- mw.log(param_name)
	end
	if param_name == 'arg' or param_name == 'var' then  -- arg = {'name', <values>}
		var_name = param_value[1]
		param_value = param_value[2]
	else
		var_name = param_name:sub(5)  -- arg_<name> = <values>
		param_name = param_name:sub(1, 3)
	end
	-- mw.log('--------')
	-- mw.log('param_name = ' .. param_name)
	-- mw.log('var_name = ' .. var_name)
	-- mw.log('NOT = ', NOT)
	-- put string into table (if we need it):
	if type(param_value) == 'string' then
		param_value = {param_value}
	end
	-- get value of argument (that was sent from template):
	local var_value = ''
	if param_name == 'arg' then
		var_value = get_arg_value(var_name)
		-- mw.log('arg_value = ' .. var_value)
	elseif param_name == 'var' then
		var_value = get_affix_value(var_name)
		-- mw.log('var_value = ' .. var_value)
	end
	-- mw.log('--------')
	-- check all values:
	if NOT then
		for j, value in pairs(param_value) do
			if value == var_value then
				return false
			end
		end
		return true
	else
		for j, value in pairs(param_value) do
			if value == var_value then
				return true
			end
		end
		return false
	end
end

-- Function for checking one entry from section 'condition'
local function check_condition(condition)
	for param_name, param_value in pairs(condition) do
		-- choose checking function
		local check_func = nil
		-- if param_name:match("^(pre_)?last(_NOT)?$") ~= nil then
		if param_name == 'last' or param_name == 'pre_last' or param_name == 'last_NOT' or param_name == 'pre_last_NOT' then
			check_func = check_last
		elseif param_name:match("^arg") ~= nil or param_name:match("^var") ~= nil then
			check_func = check_var
		end
		-- call checking function:
		if check_func ~= nil then
			if check_func(param_name, param_value) == false then
				return false  -- condition is False
			end
		end
	end
	return true  -- condition is True
end

-- Function for processing of section 'actions' (it can be inside section 'conditions')
local function process_action(action_params)
	local command = action_params[1]
	if command == 'set' then
		local var_name = action_params[2]
		local var_value = action_params[3]
		if type(var_value) == 'string' then
			affixes[var_name] = apply_affixes(var_value)
		elseif type(var_value) == 'table' then
			affixes[var_name] = process_action(var_value)
		end
	elseif command == 'replace' then
		local var_name = action_params[2]
		local pattern = action_params[3]
		local replace = action_params[4]
		local var_value = affixes[var_name]
		return var_value:gsub(pattern, replace)
	elseif command == 'substring' then
		local var_name = action_params[2]
		local from = action_params[3]
		local to = action_params[4]
		local var_value = affixes[var_name]
		return var_value:sub(from, to)
	end
end

-- Function for processing of section 'confitions'
local function process_conditions()
	local conditions = data['conditions']
	local class_names = {'common'}
	for i, condition in pairs(conditions) do
		local condition_satisfied = check_condition(condition)
		if condition_satisfied then
			-- mw.log('condition #' .. i .. ' satisfied')
			if condition['verdict'] then
				verdict = condition['verdict']
				table.insert(class_names, verdict['class_name']) 
			end
			if condition['actions'] then
				for j, action_params in pairs(condition['actions']) do
					process_action(action_params)
				end
			end
		end
	end	
	return class_names
end

-- Function for processing of section 'classes'
-- Generates values for inflection table
local function process_classes(class_names)
	local all_classes = data['classes']
	forms = {}
	for i, class_name in pairs(class_names) do
		for form_name, form_value in pairs(all_classes[class_name]) do
			forms[form_name] = apply_forms(apply_affixes(form_value))
		end
	end
	return forms
end

-- Function for processing of section 'utils' 
-- Just empty as for now
local function process_utils()
	local utils = data['utils']
	-- local u = require('Module:inflection/utils/reduce-three-letters')
	-- return "Hello, world!" .. u.process()
end

-- Main function
function export.get(frame)
	data = load_data(frame)
	if data == nil then
		return "Ошибка: не указан дата-модуль."
	end
	base = get_base()
	-- mw.log(base)
	if base:match('^[A-Za-z]') == nil then  -- TODO: check alphabet from special parameter
		return ''
	end
	args = frame:getParent().args
	-- mw.log(args['st'])
	-- mw.log(args['тип'])
	-- mw.log(args['type1'])
	
	affixes = clone(data['affixes'])
	affixes['base'] = base
	local class_names = process_conditions()
	process_classes(class_names)
	process_utils()  -- TODO
	-- mw.log(forms['type_expected'])
	return frame:expandTemplate{title=data['template'], args=forms}
end

return export

-- TODO: verdict.class_names (if we need to set several classes together)