Модуль:SummaryII/widget

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

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

--[[
	Class Widget.
	
	Dependencies:
		lpeg
		Модуль:Re
		Модуль:Class
--]]

local Class 	= require "Модуль:Class".create
local lpeg		= lpeg
local re		= require "Модуль:Re".compile
local regsub	= require "Модуль:Re".gsub


local Widget = Class {
	
	WDL = P {'wdl'
	  , wdl		= V 'grammar' + V 'expr'
	  , grammar	= Cg (Cc (true), 'G') * Cf (V 'def' / firstdef * Cg (V 'def') ^ 0, adddef) / Widget.adddefs
	  , def		= name * arrow * V 'expr'	  
	  , arrow	= S * P '<-' * S
	  , expr	= (V 'loop' + V 'token' + any) ^ 1
	  , loop	= P '<<' * V 'before' ^ -1 * V 'expr' * V 'after' ^ -1 * V 'instead' ^ -1 * P '>>'
	  , before	= expr * P '|'
	  , after	= P '|' * expr
	  , instead	= P '|' * expr
	}	-- WDL = P {'wdl', ...}
}

function Widget:_init (str)
	
	local P, R, V, C, Cg, Cc, Cf, Ct	= lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Cg, lpeg.Cc, lpeg.Cf, lpeg.Ct
	local any, space	= lpeg.P (1), lpeg.locale.space
	local S = space ^ 0
	local name	= C (R ('AZ', 'az', 'АЯ', 'ая', '__') * R ('AZ', 'az', 'АЯ', 'ая', '__', '09') ^ 0)
	local pipe	= P '|'


	local function loop_param (name)
		return P (name) * S * ':' * S * Cg (V 'expr', name)
	end		-- local function loop_param (name)	
	
	local function adddef (t, k, exp)
		if t [k] then
			error ("'"..k.."' already defined as a rule")
		else
			t [k] = exp
		end
		return t
	end		-- local function adddef (t, k, exp)
	
	local function firstdef (n, r)
		return adddef ({n}, n, r)
	end	-- local function firstdef (n, r)

	local function save_definition (acc, name, definition)
		if type (acc) == 'table' then
			acc [name] = definition
		else
			acc = {[name] = definition}
		end
		return acc
	end		-- local function save_definition (acc, name, definition)
	
	local function NT (n, b)
		if not b then
			error ("rule '"..n.."' used outside a grammar-type definition")
		else
			return self.definitions (n)
		end
	end		-- local function NT (n, b)

	self.wdl = P {'widget'
	  , widget		= V 'expr'
	  , loop		= Ct (open * V 'body' * (pipe * S * (before + sep + after + instead)) ^ 0 * close) / self.loop
	  , open		= P '<<'
	  , close		= P '>>'
	  , body		= Cg (V 'loop_expr', 'body')
	  , before		= loop_param 'before'
	  , sep			= loop_param 'separator'
	  , after		= loop_param 'after'
	  , instead		= loop_param 'instead'
	  , expr		= (V 'loop' + any) ^ 1
	  , loop_expr	= (V 'loop' + V 'field' + any) ^ 1
	  , field		= V 'dollar' * (any - V 'dollar') ^ 1 * V 'dollar'
	  , dollar		= P '$'
	}	-- self.wdl = P {'widget', ...}

	self.str = str or ''
end		-- function Widget:_init (str)

function Widget:_call (data)
	local newstr, oldstr = self.str, ''
	repeat
		oldstr = newstr
		local loop = function (captures)
			return self.loop (captures.before, captures.body, captures.after, captures.instead, data)
		end
		newstr = regsub (oldstr, self.loop_lpeg, loop)
	until newstr == self.str
	return newstr
end		-- function Widget:_call (data)

function Widget.loop (before, body, after, instead, data)
	-- TODO!
	return ''
end		-- function Widget.loop (before, body, after, instead, data)

-- end of class Widget

return Widget