aboutsummaryrefslogtreecommitdiff
path: root/patok.lua
blob: d43efdd69d49e8515d392a8f4f0e9d2f6fcc37df (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
local id = function(ip) return function() return ip end end
local pa = function(pt) return function(ip) return ip:find(pt) end end

local meta = {}
function meta:__call(p)
	if p == nil then return self.out end
	for k, v in pairs(p) do
		-- we accept: string | { patterns..., [drop = true|false|string|func] }
		-- we output: { '^' .. patterns, drop = func, name = string }
		if type(v) == 'string' then
			v = { v }
		end
		-- assume table
		if v.drop == nil then
			v.drop = id(false)
		elseif type(v.drop) == 'string' then
			v.drop = pa(v.drop)
		elseif type(v.drop) == 'boolean' then
			v.drop = id(v.drop)
		end
		v.name = k

		for ii in ipairs(v) do v[ii] = '^' .. v[ii] end

		table.insert(self.out.tokens, v)
	end
	return self
end

function new (p)
	local out = {
		tokens = {},
		reset  = function (self, input)
			self.index = 1
			self.input = input
		end,
		next   = function (self)
			for _, v in ipairs(self.tokens) do
				for _, vv in ipairs(v) do
					local out = {string.find(self.input, vv, self.index)}
					if out[1] == self.index and out[2] >= out[1] then
						self.index = out[2]+1
						local match = {
							type  = v.name,
							start = out[1],
							stop  = out[2],
							value = string.sub(self.input, out[1], out[2])
						}
						if v.drop(match.value) then return self:next() end -- skip this one
						return match
					end
				end
			end
			-- we didn't find anything
			return nil -- feed more data! or better data. either one
		end,
	}
	local constructor = {out=out}
	setmetatable(constructor, meta)
	return constructor(p)
end

return new