Module:Calculated table
Documentation for this module may be created at Module:Calculated table/doc
local p = {} -- This is a simple Reverse Polish Notation evaluator. -- It's not infix because edsrzf is lazy and didn't want to write an infix -- parser. -- If you'd like to write one and replace this one, please feel free. local function evaluate(expr, env) local stack = {} local i = 1 while i <= #expr do local c = expr:sub(i, i) if c == '*' then local x = table.remove(stack) local y = table.remove(stack) table.insert(stack, x*y) elseif c == '/' then local x = table.remove(stack) local y = table.remove(stack) table.insert(stack, x/y) elseif c == '-' then local x = table.remove(stack) local y = table.remove(stack) table.insert(stack, x-y) elseif c == '+' then local x = table.remove(stack) local y = table.remove(stack) table.insert(stack, x+y) elseif tonumber(c) then local match = expr:match("^%d+", i) i = i + #match - 1 -- We'll add 1 more below table.insert(stack, tonumber(match)) elseif c:match("%a") then local match = expr:match("^%a+", i) i = i + #match - 1 -- We'll add 1 more below table.insert(stack, env[match]) end i = i + 1 end return table.remove(stack) end -- eval_func returns a function that evaluates the expression with a given environment. local function eval_func(expr) return function(env) return evaluate(expr, env) end end function p.table(frame) local i = 4 while i <= #frame.args do frame.args[i] = eval_func(frame.args[i]) i = i + 2 end return p._table(frame.args[1], frame.args[2], {style = frame.args.style}, unpack(frame.args, 3)) end function p._table(base_heading, rows, opts, ...) local headings = {base_heading} local calculations = {} for j = 1, rows do calculations[j] = {} end local i = 1 while i < arg.n do table.insert(headings, arg[i]) local formula = arg[i+1] for j, row in ipairs(calculations) do row[(i-1)/2] = formula({x = j}) end i = i + 2 end local result = {"{| "} local style = opts.style if style then table.insert(result, style) end table.insert(result, "\n|-\n| ") for i, heading in ipairs(headings) do if i > 1 then table.insert(result, " || ") end table.insert(result, heading) end for j, row in ipairs(calculations) do table.insert(result, "\n|-\n| ") table.insert(result, j) for i, col in ipairs(row) do table.insert(result, " || ") table.insert(result, col) end end table.insert(result, "\n|}") return table.concat(result) end return p