Module:Calculated table: Difference between revisions
From Ashenzari's Archive
More actions
imported>Edsrzf m Fix bug |
imported>Edsrzf Add option to format cells |
||
| 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}, unpack(frame.args, 3)) | return p._table(frame.args[1], frame.args[2], {style = frame.args.style, format = frame.args.format}, unpack(frame.args, 3)) | ||
end | end | ||
| Line 82: | Line 82: | ||
end | end | ||
table.insert(result, heading) | 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 | end | ||
for j, row in ipairs(calculations) do | for j, row in ipairs(calculations) do | ||
| Line 88: | Line 95: | ||
for i, col in ipairs(row) do | for i, col in ipairs(row) do | ||
table.insert(result, " || ") | table.insert(result, " || ") | ||
table.insert(result, col) | table.insert(result, format(col)) | ||
end | end | ||
end | end | ||
Revision as of 02:50, 1 July 2015
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, format = frame.args.format}, 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
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, j)
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