local function q(q)local w=proxy[q].spans local M,Q=w[0][1],w[0][2]if Q<=M then return string.format("\077\097\116\099\104 \040\037\100\046\046\037\100\044 \101\109\112\116\121\041",M,Q-1)end return string.format("\077\097\116\099\104 \040\037\100\046\046\037\100\041\058 \037\115",M,Q-1,utf8_sub(w.input,M,Q))end local function w(w,M,Q,z)w.source,w.input=Q,z local b=newproxy(true)local g=getmetatable(b)g.__metatable=lockmsg g.__index=setmetatable(w,match_m)g.__tostring=q proxy[b]={name="\077\097\116\099\104";spans=w,group_id=M}return b end match_m.group=check_re("\077\097\116\099\104","\103\114\111\117\112",function(q,w)local M=q.spans[type(w)=="\110\117\109\098\101\114"and w or q.group_id[w]]if not M then return nil end return utf8_sub(q.spans.input,M[1],M[2])end)match_m.span=check_re("\077\097\116\099\104","\115\112\097\110",function(q,w)local M=q.spans[type(w)=="\110\117\109\098\101\114"and w or q.group_id[w]]if not M then return nil end return M[1],M[2]-1 end)match_m.groups=check_re("\077\097\116\099\104","\103\114\111\117\112\115",function(q)local w=q.spans if w.n>0 then local q=table.create(w.n)for M=0,w.n,1 do local Q=w[M]if Q then q[M]=utf8_sub(w.input,Q[1],Q[2])end end return table.unpack(q,1,w.n)end return utf8_sub(w.input,w[0][1],w[0][2])end)match_m.groupdict=check_re("\077\097\116\099\104","\103\114\111\117\112\100\105\099\116",function(q)local w=q.spans local M={}for q,Q in pairs(q.group_id)do Q=w[Q]if Q then M[q]=utf8_sub(w.input,Q[1],Q[2])end end return M end)match_m.grouparr=check_re("\077\097\116\099\104","\103\114\111\117\112\100\105\099\116",function(q)local w=q.spans local M=table.create(w.n)for q=0,w.n,1 do local Q=w[q]if Q then M[q]=utf8_sub(w.input,Q[1],Q[2])end end M.n=w.n return M end)
--[[ Matches ]]
--
local function match_tostr(self)
	local spans = proxy[self].spans
	local s_start, s_end = spans[0][1], spans[0][2]
	if s_end <= s_start then
		return string.format("Match (%d..%d, empty)", s_start, s_end - 1)
	end
	return string.format("Match (%d..%d): %s", s_start, s_end - 1, utf8_sub(spans.input, s_start, s_end))
end

local function new_match(span_arr, group_id, re, str)
	span_arr.source, span_arr.input = re, str
	local object = newproxy(true)
	local object_mt = getmetatable(object)
	object_mt.__metatable = lockmsg
	object_mt.__index = setmetatable(span_arr, match_m)
	object_mt.__tostring = match_tostr

	proxy[object] = { name = "Match", spans = span_arr, group_id = group_id }
	return object
end

match_m.group = check_re("Match", "group", function(self, group_id)
	local span = self.spans[type(group_id) == "number" and group_id or self.group_id[group_id]]
	if not span then
		return nil
	end
	return utf8_sub(self.spans.input, span[1], span[2])
end)

match_m.span = check_re("Match", "span", function(self, group_id)
	local span = self.spans[type(group_id) == "number" and group_id or self.group_id[group_id]]
	if not span then
		return nil
	end
	return span[1], span[2] - 1
end)

match_m.groups = check_re("Match", "groups", function(self)
	local spans = self.spans
	if spans.n > 0 then
		local ret = table.create(spans.n)
		for i = 0, spans.n do
			local v = spans[i]
			if v then
				ret[i] = utf8_sub(spans.input, v[1], v[2])
			end
		end
		return table.unpack(ret, 1, spans.n)
	end
	return utf8_sub(spans.input, spans[0][1], spans[0][2])
end)

match_m.groupdict = check_re("Match", "groupdict", function(self)
	local spans = self.spans
	local ret = {}
	for k, v in pairs(self.group_id) do
		v = spans[v]
		if v then
			ret[k] = utf8_sub(spans.input, v[1], v[2])
		end
	end
	return ret
end)

match_m.grouparr = check_re("Match", "groupdict", function(self)
	local spans = self.spans
	local ret = table.create(spans.n)
	for i = 0, spans.n do
		local v = spans[i]
		if v then
			ret[i] = utf8_sub(spans.input, v[1], v[2])
		end
	end
	ret.n = spans.n
	return ret
end)
