Модул:inflection
Documentation for this module may be created at Модул:inflection/doc
-- 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_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)