Module:Transform infobox declarations

local exports = {};

local ERROR = "Infobox syntax error.";

function error(error_, frame, noprefix) return ""; end

function concat(array, array2) local out = {}; local index = 1; for _, value in ipairs(array) do index = index + 1; out[index] = value; end for _, value in ipairs(array2) do index = index + 1; out[index] = value; end return out; end

function contains(list, value) for _, item in pairs(list) do       if item == value then return true; end end return false; end

function closeall(out, variable_stack, depth) while depth > 0 do       if variable_stack[depth] == "|L" then out = out .. "($D)"; elseif variable_stack[depth] then out = out .. "}}}";       else out = out .. "}}";       end depth = depth - 1; end return out; end

function unpack(value) if type(value) == "table" then return value[1]; end return value; end

function _main(text, return_on, frame, var_parameters, previous_variable_stack, previous_depth) local out = ""; local current = text; local depth = 0; local variable_stack = {}; local on_return = {}; local open; local close; local open2; local close2; local other; local arg; local random; local var; previous_variable_stack = previous_variable_stack or {}; previous_depth = previous_depth or 0; while current:find("") or current:find("%[%[") or current:find("%]%]") do       if depth < 0 then return out .. error(ERROR, frame), current, true; end open, _ = current:find("") or 5000000; open2, _ = current:find("%[%[") or 5000000; close2, _ = current:find("%]%]") or 5000000; if open2 < open and open2 < close and open2 < close2 then out = out .. current:sub(1, open2 - 1) .. "($C)"; current = current:sub(open2 + 2); variable_stack[depth] = "|L"; depth = depth + 1; arg, current, error_ = _main(current, true, frame, var_parameters, concat(previous_variable_stack, variable_stack), previous_depth + depth); if error_ then return out .. arg, "", true; end out = out .. arg; if current:sub(1, 1) == "|" then out = out .. "($E)"; current = current:sub(2); end elseif close2 < open and close2 < close and close2 < open2 then depth = depth - 1; out = out .. current:sub(1, close2 - 1) .. "($D)"; if (previous_variable_stack ~= {} or variable_stack ~= {}) and unpack((depth < -1 and {(previous_variable_stack[#previous_variable_stack - depth] and previous_variable_stack[#previous_variable_stack - depth] ~= "|L")}) or {(variable_stack[(depth < 0 and depth + 1) or depth] and variable_stack[(depth < 0 and depth + 1) or depth] ~= "|L")}) then return closeall(out, concat(previous_variable_stack, variable_stack), previous_depth + depth) .. error(ERROR, frame), "", true; end current = current:sub(close2 + 2); if depth >= 0 then variable_stack[depth] = "|L"; elseif depth == -1 then variable_stack[0] = "|L"; else previous_variable_stack[#previous_variable_stack + depth + 2] = "|L"; end elseif open < close then out = out .. current:sub(1, open - 1); current = current:sub(open); if current:sub(3, 3) == "{" and current:sub(4, 4) ~= "{" then out = out .. "{{__IB_SUBST:#if:"; current = current:sub(4); arg, current = _main(current, true, frame, var_parameters, concat(previous_variable_stack, variable_stack), previous_depth + depth + 1); if error_ then return out .. arg, "", true; end if contains({"{", "[", "}", "}"}, arg:sub(1, 1)) then return closeall(out, concat(previous_variable_stack, variable_stack), previous_depth + depth + 1) .. error("Cannot use templates, links, or other parameters within parameter accesses.", frame), "", true; end variable_stack[depth] = arg; arg = var_parameters[arg]; random = frame:expandTemplate({title="Ident4"}); out = out .. ((arg and "BOOLEAN_CHECK_" .. random) or "") .. "|echo"; else out = out .. "{{";               current = current:sub(3); if current:sub(1, 8):match("[Ii]nfobox ") then if contains({"group", "panel", "section"}, current:sub(9, current:find("|") - 1)) then out = out .. "subst:"; elseif current:sub(9, current:find("|") - 1) == "label" then out = out .. "__IB_SUBST:" .. current:sub(1, current:find("|")); arg, current = _main(current:sub(current:find("|") + 1), true, frame, var_parameters, concat(previous_variable_stack, variable_stack), previous_depth + depth + 1); if error_ then return out .. arg, "", true; end current = current:sub(2); out = out .. arg .. "|{{ib:{{"; on_return[depth] = "}}}}"; elseif current:sub(9, current:find("|") - 1) == "image" then out = out .. "__IB_SUBST:"; out = out .. current:sub(1, current:find("|")); arg, current = _main(current:sub(current:find("|") + 1), true, frame, var_parameters, concat(previous_variable_stack, variable_stack), previous_depth + depth + 1); if error_ then return out .. arg, "", true; end out = out .. "{{ib:{{" .. arg .. "}}}}";                   else out = out .. "__IB_SUBST:"; out = out .. current:sub(1, current:find("|")) .. "{{ib:{{"; current = current:sub(current:find("|") + 1); on_return[depth] = "}}}}"; end else out = out .. "__IB_SUBST:"; end variable_stack[depth] = false; end depth = depth + 1; else out = out .. current:sub(1, close - 1); current = current:sub(close); if not return_on and depth == 0 then return closeall(out, concat(previous_variable_stack, variable_stack), previous_depth + depth) .. error("Unclosed '&#125;&#125;' without matching '&#123;&#123;'.", frame), "", true; end depth = depth - 1; var = (previous_variable_stack ~= {} or variable_stack ~= {}) and unpack((depth < -1 and {previous_variable_stack[#previous_variable_stack - depth]}) or {variable_stack[(depth < 0 and depth + 1) or depth]}); if var then if depth >= 0 and var == "|L" then return closeall(out, concat(previous_variable_stack, variable_stack), previous_depth + depth + 1) .. error(ERROR, frame), "", true; end if depth >= 0 and current:sub(3, 3) ~= "}" then return closeall(out, concat(previous_variable_stack, variable_stack), previous_depth + depth + 1) .. error(ERROR, frame), "", true; end current = current:sub(4); out = out .. "|";           else current = current:sub(3); if depth >= 0 then variable_stack[depth] = false; elseif depth == -1 then variable_stack[0] = false; else previous_variable_stack[#previous_variable_stack + depth + 2] = false; end end out = out .. "}}";           if on_return[depth] then out = out .. on_return[depth]; on_return[depth] = nil; end end if return_on and depth == 0 then break elseif return_on and depth == -1 then if variable_stack[0] == "|L" then out = out:sub(1, -5); current = "]]" .. current; elseif variable_stack[0] then out = out:sub(1, -4); current = "}}}" .. current; else out = out:sub(1, -3); current = "}}" .. current; end depth = depth + 1; break; end end if depth > 0 then return closeall(out, concat(previous_variable_stack, variable_stack), previous_depth + depth) .. error("Unclosed templates, links, variables, and/or parser functions remain.", frame), "", true; elseif depth < 0 then return closeall(out, concat(previous_variable_stack, variable_stack), previous_depth + depth) .. error("Internal error: Negative depth.", frame, true), "", true; end return out, current, false; end

function exports.main(frame) local var_parameters = {}; for key, value in pairs(frame.args) do       if type(key) == "number" then var_parameters[tostring(key - 1)] = value; else var_parameters[key] = value; end end out, current, _ = _main(mw.text.decode(frame:preprocess("")), false, frame, var_parameters); return out .. current; end

exports.parse = _main;

return exports;