Модуль:Rex

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

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

-- Интерфейс к библиотеке lrexlib.
-- Экспортируется класс Rex.
-- Зависимость: Модуль:Class.
local Class = require ('Модуль:Class').create

local rex = Class ()
-- Флаги для компиляции:
rex.flags = 1 + 8 + 64 + 2048 -- CASELESS + EXTENDED + EXTRA + UTF8.
-- Локаль:
rex.locale = 'ru_RU.utf8'
-- подключение к библиотеке lrexlib:
local new_pcre = rex_pcre ().new
 
-- Конструктор.
-- Параметр (вызов с :) -- строка регулярного выражения, без //.
function rex:_init (regex)
	if (regex or '') ~= '' then
		self.compiled = new_pcre (regex, self.flags, self.locale)
	end
	-- self.compiled = nil if regex is not set.
end
 
-- Служебная функция итератора без состояния,
--     чтобы обойтись без замыкания в критическом коде.
-- Параметры: 1) неизменные параметры (регулярное выражение и строка),
--            2) текущее положение.
-- Возвращает: 1) новое текущее положение,
--             2) очередное найденное совпадение (массив подмасок):
function rex.stateless_iter (params, position)
	local captures = nil
	from, to, captures = params.rex:tfind (params.str, position.to + 1)
	if from then
		return {from = from, to = to}, captures
	end
	-- nil, nil returned if from == nil.
end

-- Функция, создающая служебный итератор, более удобный, чем rex_pcre.gmatch.
--     Параметр (вызов с :): строка.
--     Возвращает: 1) ссылку на фунцкцию итератора stateless_iter,
--                 2) скомпилированный образец и строку -- неизменные параметры итератора,
--                 2) исходное положение итератора:
function rex:gmatch (subj)
	return self.stateless_iter
	     , {rex = self.compiled, str = subj}
	       -- неизменные параметры итератора: строка и образец.
	     , {from = 1, to = 0} -- исходное положение итератора.
end
 
-- Функция, применяющая регулярное выражение к строке.
--     Параметры (вызов с :): 1) строка,
--                            2) название единственной подмаски
--                               при незаданной регулярке.
--     Возвращает: 1) двумерный массив совпадения × подмаски,
--                 2) массив позиций найденных совпадений.
function rex:match_all (subj, subpattern)
	if self.compiled then
		local matches = {}
		local offsets = {}
		-- Дополнительный счётчик для оптимизации:
		local i = 0
		-- Используется самописный итератор:
		for range, captures in self:gmatch (subj) do
			i = i + 1
			matches [i] = captures
			offsets [i] = range.from
		end
		return matches, offsets
	else
		-- регулярное выражение не задано. Возвращаем всю строку:
		return {{[(subpattern or 1)] = subj}}, {1}
	end
end

function rex:match (subj, init, flags)
	if self.compiled then
		return self.compiled:match (subj, init, flags)
	else
		return nil
	end
end	-- function rex:match (subj, init, flags)

function rex:tfind (subj, init, flags)
	if self.compiled then
		return self.compiled:tfind (subj, init, flags)
	else
		return nil
	end
end	-- function rex:tfind (subj, init, flags)

-- Экспорт:
return {['Rex'] = rex}