Модуль:SummaryII/parser2

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

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

local lpeg = lpeg
	
local function make_lpeg (components)
	local P, Cg, Ct = lpeg.P, lpeg.Cg, lpeg.Ct
	local any = lpeg (1)
	local tail = Cg (any ^ 0, 'tail')
	local complex = tail
	for _, component in ipairs (components) do
		complex = component (component.property, component.format, component.brackets, separator) * complex
	end
	-- TODO: repeat with brackets.
	return Ct (complex)
end

-- components is a table.
--		Numbered components are placed in the order of their indices.
--		Named components can be anywhere between ordered ones.
--		A component may be a table in its turn.
local function complex (components)
	local ordered, scattered = {}, {}
	for key, value in pairs (components) do
		if tonumber (key) then
			ordered [key] = value
		else
			scattered [key] = value
		end
	end
end

local function component (property, format, brackets, separator)
	local C, Cg, Cc, Ct = lpeg.C, lpeg.Cg, lpeg.Cc, lpeg.Ct
	local variants = variant (format, separator) -- no brackets as a fallback.
	-- Bracketed variants:
	for _, bracket in ipairs (brackets) do
		variants = variant (format, separator, bracket.open, bracket.screen, bracket.alias, bracket.close) + variants
	end
	return Ct (Cg (Cc (property), 'property') * Cg (Ct (variant), 'captures') *  Cg (separator, 'separator'))
end

local function variant (format, separator, open, screen, alias, close)
	local Cg = lpeg.Cg
	local never, skip, any = lpeg.P (false), lpeg (true), lpeg (1)
	return Cg ((any - value) ^ 0, 'prefix')
		 * ((open or skip) * -(screen or never))
		 * Cg ((format or (any - (close and alias + close or separator)) ^ 1), 'value')
		 * (alias * Cg ((any - close) ^ 0, 'alias')) ^ -1
		 * (close or skip)
		 * Cg ((any - value - separator) ^ 0, 'suffix')
end
	
return {
	test = function (frame)
		local formats
		local serialise = require "Модуль:Test".serialise
		local str, format = frame.args [1], frame.args [2]
		return serialise (make_lpeg (formats [format]).match (str))
	end
}