Модуль:SummaryII/test

Материал из свободной русской энциклопедии «Традиция»
Перейти к навигации Перейти к поиску

Онтология

Умолчания

Несколько параметров

Ошибка Lua на строке 61: attempt to index field 'serialize' (a nil value).

Несколько параметров

Ошибка Lua на строке 61: attempt to index field 'serialize' (a nil value).

Сильные форматы

Составные форматы

Ошибка Lua на строке 61: attempt to index field 'serialize' (a nil value).

URL

Ошибка Lua на строке 61: attempt to index field 'serialize' (a nil value).

Единица измерения перед числом

Ошибка Lua на строке 61: attempt to index field 'serialize' (a nil value).

Количество на примере массы

Ошибка Lua на строке 61: attempt to index field 'serialize' (a nil value).

Слабые форматы (текст, страница)

Ошибка Lua на строке 61: attempt to index field 'serialize' (a nil value).


--[[
Тесты SummaryII.
--]]

local table_and_array_functions = require "Модуль:Array"
local merge 					= table_and_array_functions.table_merge
local service					= require "Модуль:SummaryII/service"
local strip						= service.strip
local strip_number				= service.strip_number

-- Эта функция добавляет к явно заданным параметрам умолчания: которые можно перезаписать, дополнить или защищённые:
local function make_params (explicit, overwriteable_defaults, appendable_defaults, protected_defaults)
	local params = {}
	-- Перезаписываемые умолчания:
	for name, default in pairs (overwriteable_defaults or {}) do
		params [strip (name)] = default
	end
	-- Дополняемые умолчания:
	for name, values in pairs (appendable_defaults or {}) do
		for i, value in ipairs (values) do
			params [name .. '_999' .. tostring (i)] = value
		end
	end
	local protected_defaults = protected_defaults or {}
	-- Явно заданные параметры:
	for name, value in pairs (explicit) do
		local stripped = strip_number (tostring (name))
		if params [stripped] then
			params [stripped] = nil
		end
		if not protected_defaults [stripped] then
			params [name] = value
		end
	end
	-- Защищённые умолчания:
	for name, value in pairs (protected_defaults) do
		params [name] = value
	end
	return params
end		-- local function make_params (explicit, overwriteable_defaults, appendable_defaults, protected_defaults)

--[[
Class TemplateProcessor.

Зависимости:
	Модуль:Class,
	Модуль:Array,
	Модуль:SummaryII/service
	lpeg
	Модуль:Re
--]]
local Class = require ('Модуль:Class').create

-- Accelerators:
local Array						= table_and_array_functions.Array

local lpeg		= lpeg
local Ct		= lpeg.Ct
local cartesian	= require "Модуль:Array".cartesian

local deserialise_lpeg	= lpeg.serialize.load
local gsub				= mw.ustring.gsub

local TemplateProcessor = Class {
	lines		= {}
  , vectors		= {}
  , flat		= {}
  , separators	= {}
}

function TemplateProcessor:_init (serialised_parsers)
	self.lpeg = lpeg.P (false)
	for _, parser in ipairs (serialised_parsers) do
		self.lpeg = self.lpeg + deserialise_lpeg (parser)
	end
end		-- function TemplateProcessor:_init (serialised_parsers)

function TemplateProcessor:_call (params)
	local cartesian_append = Array.cartesian_append
	for name, value in pairs (params) do
		local id, index, line, vectors, separator = self:single (name, value)
		self.vectors [index] = self.vectors [index] or {lines = {}, vectors = {}}
		self.vectors [index].lines		[id] = line
		self.vectors [index].vectors	[id] = vectors
		
		self.flat [index] = (self.flat [index] or Array ()):cartesian_append (vectors)
		
		self.lines [id] = self.lines [id] or {}
		self.lines [id] [index] = line
		
		self.separators [id] = separator
	end	-- for name, value in pairs (params)
	return self.lines, self.flat, self.vectors
end		-- function TemplateProcessor:_call (params)
		
function TemplateProcessor:single (name, value)
	local glued = self:glue_param (name, value)
	local captures = Ct (self.lpeg):match (glued)
	if captures and type (captures) == 'table' then
		
		local index = captures.index or 1
		
		local line = ''
		local ordered_values = {}
		
		-- Initialise intravectors:
		local complete_vectors = Array ()
		local polyvector = {}
		local last_no = 0
		
		local separator = ', '
		for i, affixed in ipairs (captures) do
			
			-- Choose normalised SMW value:
			affixed.value = affixed.processed [2] or affixed.processed [1]
			-- Choose alias:
			affixed.alias = affixed.alias or affixed.processed [1]
			
			-- Append pure property list for later use:
			-- TODO: ordering is not needed any more.
			ordered_values [#ordered_values + 1] = {
				property	= affixed.property
			  , value		= affixed.value
			}
			
			-- Form intravectors:
			local no			= tonumber (affixed.no)
			local new_vectors	= {}
			local inject		= nil

			if no < last_no then
				-- New intravector:
				new_vectors = cartesian (polyvector)
				polyvector = {}				
				inject = captures.inject
			end
			
			polyvector [affixed.property] = polyvector [affixed.property] or {}
			polyvector [affixed.property] [#polyvector [affixed.property] + 1] = affixed.value
			last_no = no
			
			-- Append output line:
			line = line	.. self.substitute (affixed.output, affixed)

			if i == #captures then
				-- Last intravector:
				new_vectors = cartesian (polyvector)
				inject = captures.inject
			end
			
			if inject then
				for _, vector in ipairs (new_vectors) do
					line = line .. self.substitute (inject, vector)
				end
			end
							
			complete_vectors:append2self (new_vectors)
			
			separator = affixed.separtor or separator

		end	-- for _, affixed in ipairs (captures)
		
		-- Attach tail:
		line = line .. (captures.tail or '')
		
		for _, vector in ipairs (complete_vectors) do
			-- Infer properties:
			if captures.inferred then
				for property, value in pairs (captures.inferred) do
					vector [property] = self.substitute (value, vector)
				end
			end	-- if captures.inferred
		end	-- for _, vector in ipairs (complete_vectors)

		return captures.id, index, line, complete_vectors, separator --, captures, ordered_values
	else
		return 'Not matched', name .. ' = ' .. value
	end	-- if captures and type (captures) == 'table'
end	-- function TemplateProcessor:single (name, value)

function TemplateProcessor.substitute (format, values)
	return gsub (format, '@([^@]+)@', values)
end		-- function TemplateProcessor:substitute (format, values)

function TemplateProcessor.glue (args)
	return table.concat (args, mw.ustring.char (0))
end		-- function TemplateProcessor.glue (args)

function TemplateProcessor:glue_param (name, value)
	return strip (tostring (name)) .. '=' .. mw.text.trim (value)
end		-- function TemplateProcessor:glue_param (name, value)

-- end of class TemplateProcessor

local function tester (parser, args)
	local serialise = require ('Модуль:Test').serialise
	local serialised = {parser:serialise ()}
	local processor = TemplateProcessor (serialised)
	local ret = [==[
{| class="wikitable"
! Строка !! Захваты
]==]
	for name, value in pairs (args) do
		ret = ret .. '\n|-\n|\n<code><nowiki>' .. name .. ' = ' .. value .. '</nowiki></code>\n| '
				  .. serialise ({processor:single (name, value)})
	end
	ret = ret .. '\n|}'
	return ret
end		-- local function tester (parser, args)


local spaces = lpeg.S '  ' ^ 0
local html_tags = lpeg.P {
	'tags'
  , tags	= (lpeg.P '<' * (1 - lpeg.P '>') ^ 0 * lpeg.P '>') ^ 1
}
local balanced_parentheses = lpeg.P {'(' * ((1 - lpeg.S '()') + lpeg.V (1))^0 * ')'}
local separators = html_tags + lpeg.S ',;:*#\n' ^ 1

-- Module interface
local m = {}
m.test_weak = function (frame)
	local parser = require "Модуль:SummaryII/parsers".parser
	local str = parser ({'Название'}, 'string', 'Title', separators)
	return frame:preprocess (tester (str, frame.args))
end
m.test_mass = function (frame)
	local parser = require "Модуль:SummaryII/parsers".parser
	local mass = parser ({'Масса'}, 'quantity', 'Mass', separators, {units = {'kg', 'g', 'tonne', 'tonnes', 'mg', 'mkg'}, default_unit = 'kg'})
	return frame:preprocess (tester (mass, frame.args))
end
m.test_money = function (frame)
	local parser = require "Модуль:SummaryII/parsers".parser
	local cost = parser ({'Стоимость'}, 'quantity', 'Cost', separators, {units = {'руб.', 'долл.', 'USD', 'евро'}, preunits = {'$', '€', '£'}, default_unit = 'руб.'})
	return frame:preprocess (tester (cost, frame.args))
end
m.test_url = function (frame)
	local parser = require "Модуль:SummaryII/parsers".parser
	local url = parser ({'Ссылка'}, 'URL', 'URL', separators, {default_protocol = 'http'})
	return frame:preprocess (tester (url, frame.args))
end
m.test_date = function (frame)
	local parser = require "Модуль:SummaryII/parsers".parser
	local date = parser ({'Дата создания', 'создание'}, 'date', 'создания', separators)
	return frame:preprocess (tester (date, frame.args))
end
m.test_params = function (frame)
	local serialise = require ('Модуль:Test').serialise
	local factory = require "Модуль:SummaryII/parsers".parser
	local grammars = {
		factory ({'Название'}, 'string', 'Title', separators):serialise ()
	  , factory ({'Дата создания', 'создание'}, 'date', 'создания', separators):serialise ()
	  , factory ({'Масса'}, 'quantity', 'Mass', separators, {units = {'kg', 'g', 'tonne', 'tonnes', 'mg', 'mkg'}, default_unit = 'kg'}):serialise ()
	  , factory ({'Ссылка'}, 'URL', 'URL', separators, {default_protocol = 'http'}):serialise ()
	}
	local parser = TemplateProcessor (grammars)
	local ret = [==[
{| class="wikitable"
! Параметры !! Возврат
|-
|
]==]
	for name, value in pairs (frame.args) do
		ret = ret .. '\n <nowiki>' .. tostring (name) .. ' = ' .. value .. '</nowiki>'
	end
	local params = make_params (
		frame.args
	  , {['датасоздания']	= '1 октября 2016'}
	  , {['датасоздания']	= {'1 сентября 2016'}}
	  , {['название']		= 'Я сам знаю, какое название лучше'}
	)
	ret = ret .. '\n|\n ' .. serialise ({parser (params)}) .. '\n|}'
	return frame:preprocess (ret)
end	

function m.test_make_params (frame)
	local serialise = require ('Модуль:Test').serialise
	local ret = [==[
{| class="wikitable"
! Параметры !! Новые параметры
|-
|
]==]
	ret = ret .. '\n ' .. serialise (frame.args) .. ''
	local params = make_params (
		frame.args
	  , {['датасоздания']	= '1 октября 2016'}
	  , {['датасоздания']	= {'1 сентября 2016'}}
	  , {['название']		= 'Я сам знаю, какое название лучше'}
	)
	ret = ret .. '\n|\n ' .. serialise (params) .. '\n|}'
	return frame:preprocess (ret)
end		-- function m.test_make_params (frame)

-- Обёртка для frame:expandTemplate, чтобы не передавать frame всю дорогу:
local function expandTemplate (template, params)
    return mw.getCurrentFrame ():expandTemplate{ title = template, args = params }
end
 
m.testask = function (frame)
	return serialise (mw.ext.smw.ask (frame.args))
end

m.locale = function (frame)
	local serialise = require ('Модуль:Test').serialise
	return serialise (lpeg.locale ())
end

return m