Module:Transform infobox declarations

local exports = {};

local ERROR = "Infobox syntax error.";

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

function concat(array, array2, start) return print_table(array) .. print_table(array2); end

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

function print_table(node) if type(node) ~= "table" then return "\"" .. tostring(node) .. "\""; end out = "{"; for key, value in pairs(node) do       out = out .. tostring(key) .. " = " .. tostring(value); end return out .. "}"; end

function closeall(out, variable_stack, depth) out = out .. "(" .. variable_stack .. ")"; while depth > 0 do       if variable_stack[depth - 1] == "|L" then out = out .. "($D)"; elseif variable_stack[depth - 1] 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 out = out .. current:sub(1, close2 - 1) .. "($D)"; depth = depth - 1; if (previous_variable_stack ~= {} or variable_stack ~= {}) and unpack((depth < 0 and {(previous_variable_stack[#previous_variable_stack + depth + 1] ~= "|L" or not variable_stack[depth])}) or {(variable_stack[depth] ~= "|L" or not variable_stack[depth])}) then return closeall(out, concat(previous_variable_stack, variable_stack), previous_depth + depth) .. error("'&#93;&#93;' without matching '&#91;&#91;'.", 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); variable_stack[depth] = true; 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); variable_stack[depth] = false; 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("'&#125;&#125;' or '&#125;&#125;&#125;' without matching '&#123;&#123;' or '&#123;&#123;&#123;'.", frame), "", true; end depth = depth - 1; var = (previous_variable_stack ~= {} or variable_stack ~= {}) and unpack((depth < 0 and {previous_variable_stack[#previous_variable_stack + depth + 1]}) or {variable_stack[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 not return_on and 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 not return_on and 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;