mirror of
https://github.com/osmarks/random-stuff
synced 2025-12-18 20:08:05 +00:00
add CC projects
This commit is contained in:
228
computercraft/lua-adt.lua
Normal file
228
computercraft/lua-adt.lua
Normal file
@@ -0,0 +1,228 @@
|
||||
local function trim(str, chars)
|
||||
if chars == nil then
|
||||
chars = "%s*"
|
||||
end
|
||||
return string.match(str, "^"..chars.."(.-)"..chars.."$")
|
||||
end
|
||||
|
||||
local function split(str, delim)
|
||||
if delim == nil then
|
||||
delim = "\n"
|
||||
end
|
||||
local t = {}
|
||||
for s in string.gmatch(str, "([^"..delim.."]+)") do
|
||||
table.insert(t, trim(s))
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function find_multiple(str, patterns, offset)
|
||||
local ws = string.len(str)
|
||||
local we = we
|
||||
local wpattern = nil
|
||||
for i, pattern in pairs(patterns) do
|
||||
s, e = string.find(str, pattern, offset)
|
||||
if s ~= nil then
|
||||
if s < ws then
|
||||
ws = s
|
||||
we = e
|
||||
wpattern = pattern
|
||||
end
|
||||
end
|
||||
end
|
||||
return ws, we, wpattern
|
||||
end
|
||||
|
||||
local function balanced_end(str, word, offset)
|
||||
if offset == nil then
|
||||
offset = 1
|
||||
end
|
||||
local i = offset
|
||||
while true do
|
||||
local s, e, p
|
||||
if word == "then" then
|
||||
s, e, p = find_multiple(str, {"%smatch%s", "%sfunction%s", "%sthen%s", "%sdo%s", "%send%s", "%selseif%s"}, i)
|
||||
else
|
||||
s, e, p = find_multiple(str, {"%smatch%s", "%sfunction%s", "%sthen%s", "%sdo%s", "%send%s"}, i)
|
||||
end
|
||||
if p == "%send%s" then
|
||||
return e
|
||||
elseif p == "%selseif%s" then
|
||||
return e
|
||||
elseif p == nil then
|
||||
return "UNBAL"
|
||||
end
|
||||
i = balanced_end(str, string.sub(p, 3, -3), e)
|
||||
if i == "UNBAL" then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function get_decls(str)
|
||||
-- gather data declarations from source & remove
|
||||
local datas = {}
|
||||
local i = 0
|
||||
local strout = ""
|
||||
while true do
|
||||
local n, a = string.find(str, "%sdata [%w]+", i+1)
|
||||
if n == nil then
|
||||
strout = strout .. string.sub(str, i+1)
|
||||
break
|
||||
end
|
||||
strout = strout .. string.sub(str, i+1, n)
|
||||
local e, d = string.find(str, "end", i+1)
|
||||
local cont = string.sub(str, a+1, e-1)
|
||||
local data = {}
|
||||
for i, case in ipairs(split(cont)) do
|
||||
local c = {}
|
||||
local b, p = string.find(case, "%(")
|
||||
if b == nil then
|
||||
c.name = case
|
||||
c.args = 0
|
||||
else
|
||||
c.name = string.sub(case, 1, p-1)
|
||||
c.args = #split(case, ",")
|
||||
end
|
||||
table.insert(data, c)
|
||||
end
|
||||
i = d
|
||||
table.insert(datas, data)
|
||||
end
|
||||
return datas, strout
|
||||
end
|
||||
|
||||
local parseexprs, replace_case, replace_match
|
||||
local function parseexpr(str)
|
||||
local n, o, name, body = string.find(str, "(%w+)(%b())")
|
||||
if n == nil then
|
||||
local b = string.find(str, ",")
|
||||
if b == nil then
|
||||
return {type="var",name=str}, ""
|
||||
else
|
||||
return {type="var", name=string.sub(str, 0, b-1)}, string.sub(str,b+1)
|
||||
end
|
||||
end
|
||||
body = string.sub(body, 2, -2)
|
||||
local obj = {type="data", name=name, body=parseexprs(body)}
|
||||
local rem = string.sub(str, o+1)
|
||||
local b = string.find(rem, ",")
|
||||
if b == nil then
|
||||
return obj, ""
|
||||
else
|
||||
return obj, string.sub(rem,b+1)
|
||||
end
|
||||
end
|
||||
|
||||
parseexprs = function(str)
|
||||
local t = {}
|
||||
while str ~= "" do
|
||||
local obj
|
||||
obj, str = parseexpr(str)
|
||||
table.insert(t, obj)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function getCase(datas, data)
|
||||
for i, x in ipairs(datas) do
|
||||
for i, case in ipairs(x) do
|
||||
if case.name == data then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function comparison(datas, var, pattern)
|
||||
if pattern.type == "data" then
|
||||
local out = var .. ".case == " .. getCase(datas, pattern.name)
|
||||
for i, x in ipairs(pattern.body) do
|
||||
if x.type == "data" then
|
||||
out = out .. " and " .. comparison(datas, var .. "[" .. i .. "]", x)
|
||||
end
|
||||
end
|
||||
return out
|
||||
else
|
||||
return "true"
|
||||
end
|
||||
end
|
||||
|
||||
local function destructure(datas, var, pattern)
|
||||
if pattern.type == "var" then
|
||||
return "local " .. pattern.name .. " = " .. var
|
||||
else
|
||||
local out = ""
|
||||
for i, x in ipairs(pattern.body) do
|
||||
out = out .. "\n" .. destructure(datas, var .. "[" .. i .. "]", x)
|
||||
end
|
||||
return out
|
||||
end
|
||||
end
|
||||
|
||||
replace_match = function(datas, str)
|
||||
while true do
|
||||
local m, b, var = string.find(str, "%smatch (%w+)%s")
|
||||
if m == nil then
|
||||
return str
|
||||
end
|
||||
local e = balanced_end(str, "match", b)
|
||||
local cont = string.sub(str, b, e-4)
|
||||
str = string.sub(str, 1, m) .. replace_case(datas, cont, var) .. string.sub(str, e, -1)
|
||||
end
|
||||
end
|
||||
|
||||
replace_case = function(datas, out, var)
|
||||
local str = out
|
||||
local count = 0
|
||||
while true do
|
||||
local m
|
||||
local b
|
||||
local p
|
||||
m, b, p = string.find(str, "%scase ([^%s]+) do%s")
|
||||
if m == nil then
|
||||
for i=1,count do
|
||||
str = str .. "\nend"
|
||||
end
|
||||
return str
|
||||
end
|
||||
count = count + 1
|
||||
local e = balanced_end(str, "do", b)
|
||||
local cont = string.sub(str, b, e-5)
|
||||
local pattern = parseexpr(p)
|
||||
local bool = comparison(datas, var, pattern)
|
||||
local body = destructure(datas, var, pattern)
|
||||
str = string.sub(str, 1, m) .. "\nif " .. bool .. " then\n" .. body .. cont .. "\nelse\n" .. string.sub(str, e, -1)
|
||||
end
|
||||
end
|
||||
|
||||
local function printpattern(pattern)
|
||||
if pattern.type == "data" then
|
||||
io.write(pattern.name)
|
||||
io.write("(")
|
||||
for i, v in ipairs(pattern.body) do
|
||||
printpattern(v)
|
||||
io.write(",")
|
||||
end
|
||||
io.write(")")
|
||||
else
|
||||
io.write(pattern.name)
|
||||
end
|
||||
end
|
||||
|
||||
local function writeheaders(datas)
|
||||
local out = ""
|
||||
for i, x in ipairs(datas) do
|
||||
for i, case in ipairs(x) do
|
||||
out = out .. "\nlocal function " .. case.name .. "(...) return {case=" .. i .. ",...} end"
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
function preprocess(str)
|
||||
local decls, str0 = get_decls(str)
|
||||
local b = replace_match(decls, str0)
|
||||
local h = writeheaders(decls)
|
||||
return h .. b
|
||||
end
|
||||
Reference in New Issue
Block a user