Module:User:Surjection/templateparser

local export = {}

local parseTemplateSearchPattern = "(([{|}%[%]=<]).)" local parseTemplateSearchPatternNoEq = "(([{|}%[%]<]).)"

function export.parseTemplate(text) local text, ok = text:gsub("^$", "%1") if ok == 0 then return nil end local prev = 1 local pos = 1, mend, found, f1	local in_template = 0 local in_table = 0 local in_link = 0 local search = parseTemplateSearchPattern local has_key = false local eq_index = 1 local name = nil local args = {} local next_i = 1 local function add_param(x, has_key, eq) if name == nil then name = mw.text.trim(x) return end

if has_key then local key = mw.text.trim(x:sub(1, eq)) local value = mw.text.trim(x:sub(eq + 2)) local num = tonumber(key, 10) if num ~= nil and num > 0 then key = num end args[key] = value else args[next_i] = x			next_i = next_i + 1 end end

while true do		pos, mend, found, f1 = text:find(search, pos) if pos == nil then break end

if found == "{{" then -- start of subtemplate in_template = in_template + 1 pos = pos + 2 elseif found == "{|" then -- start of a table in_table = in_table + 1 pos = pos + 2 elseif found == "}}" then -- end of subtemplate if in_template > 0 then in_template = in_template - 1 end pos = pos + 2 elseif found == "|}" then -- end of table if in_table > 0 then in_table = in_table - 1 end pos = pos + 2 elseif found == "" then			-- start of link			in_link = in_link + 1			pos = pos + 2		elseif found == "" then -- end of link if in_link > 0 then in_link = in_link - 1 end pos = pos + 2 elseif found == "<n" and text:sub(pos, pos + 7) == " " then pos = text:find(" ", pos) if pos == nil then return nil end pos = pos + 8 elseif found == "<-" and text:sub(pos, pos + 3) == "", pos + 4)			if pos == nil then return nil end			pos = pos + 3		elseif in_template == 0 and in_table == 0 and in_link == 0 then			if f1 == "|" then				-- parameter separator				add_param(text:sub(prev, pos - 1), has_key, eq_index - prev)				has_key = false				search = parseTemplateSearchPattern -- allow equals sign again				prev = pos + 1			elseif f1 == "=" and not has_key then				-- parameter key/value separator				eq_index = pos				has_key = true				search = parseTemplateSearchPatternNoEq -- do not allow further equals signs			end			pos = pos + 1		else			pos = pos + 1		end	end

if in_template ~= 0 or in_table ~= 0 or in_link ~= 0 then error("Invalid syntax detected!") end add_param(text:sub(prev), has_key, eq_index - prev)

return name, args end

return export