Difference between revisions of "Module:Calculated table"
(Add a default style) |
(Start calculating from 0; allow specifying inputs) |
||
Line 53: | Line 53: | ||
i = i + 2 | i = i + 2 | ||
end | end | ||
− | return p._table(frame.args[1], frame.args[2], {style = frame.args.style, format = frame.args.format}, unpack(frame.args, 3)) | + | local inputs = {} |
+ | if frame.args.inputs then | ||
+ | for str in frame.args.inputs:gmatch("[^,]+") do | ||
+ | table.insert(inputs, str) | ||
+ | end | ||
+ | end | ||
+ | return p._table(frame.args[1], frame.args[2], {style = frame.args.style, format = frame.args.format, inputs = inputs}, unpack(frame.args, 3)) | ||
end | end | ||
Line 62: | Line 68: | ||
calculations[j] = {} | calculations[j] = {} | ||
end | end | ||
+ | local inputs = opts.inputs or {} | ||
local i = 1 | local i = 1 | ||
while i < arg.n do | while i < arg.n do | ||
Line 67: | Line 74: | ||
local formula = arg[i+1] | local formula = arg[i+1] | ||
for j, row in ipairs(calculations) do | for j, row in ipairs(calculations) do | ||
− | row[(i+1)/2] = formula({x = j}) | + | row[(i+1)/2] = formula({x = inputs[j] or j-1}) |
end | end | ||
i = i + 2 | i = i + 2 | ||
Line 90: | Line 97: | ||
for j, row in ipairs(calculations) do | for j, row in ipairs(calculations) do | ||
table.insert(result, "\n|-\n| ") | table.insert(result, "\n|-\n| ") | ||
− | table.insert(result, j) | + | table.insert(result, inputs[j] or j-1) |
for i, col in ipairs(row) do | for i, col in ipairs(row) do | ||
table.insert(result, " || ") | table.insert(result, " || ") |
Latest revision as of 04:07, 1 July 2015
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 local inputs = {} if frame.args.inputs then for str in frame.args.inputs:gmatch("[^,]+") do table.insert(inputs, str) end end return p._table(frame.args[1], frame.args[2], {style = frame.args.style, format = frame.args.format, inputs = inputs}, 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 inputs = opts.inputs or {} 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 = inputs[j] or j-1}) end i = i + 2 end local result = {"{| "} local style = opts.style or [[cellpadding="4" cellspacing="0" border="1" align="center" style="text-align:center"]] table.insert(result, style) 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 local format = function(s) return s end if type(opts.format) == "function" then format = opts.format elseif type(opts.format) == "string" then local formatstr = opts.format format = function(s) return formatstr:format(s) end end for j, row in ipairs(calculations) do table.insert(result, "\n|-\n| ") table.insert(result, inputs[j] or j-1) for i, col in ipairs(row) do table.insert(result, " || ") table.insert(result, format(col)) end end table.insert(result, "\n|}") return table.concat(result) end return p