Advertisement
osmarks

potatOS lua-adt by baidicoot

Jul 2nd, 2020
1,113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local function trim(str, chars)
  2.     if chars == nil then
  3.         chars = "%s*"
  4.     end
  5.     return string.match(str, "^"..chars.."(.-)"..chars.."$")
  6. end
  7.  
  8. local function split(str, delim)
  9.     if delim == nil then
  10.         delim = "\n"
  11.     end
  12.     local t = {}
  13.     for s in string.gmatch(str, "([^"..delim.."]+)") do
  14.         table.insert(t, trim(s))
  15.     end
  16.     return t
  17. end
  18.  
  19. local function find_multiple(str, patterns, offset)
  20.     local ws = string.len(str)
  21.     local we = we
  22.     local wpattern = nil
  23.     for i, pattern in pairs(patterns) do
  24.         s, e = string.find(str, pattern, offset)
  25.         if s ~= nil then
  26.             if s < ws then
  27.                 ws = s
  28.                 we = e
  29.                 wpattern = pattern
  30.             end
  31.         end
  32.     end
  33.     return ws, we, wpattern
  34. end
  35.  
  36. local function balanced_end(str, word, offset)
  37.     if offset == nil then
  38.         offset = 1
  39.     end
  40.     local i = offset
  41.     while true do
  42.         local s, e, p
  43.         if word == "then" then
  44.             s, e, p = find_multiple(str, {"%smatch%s", "%sfunction%s", "%sthen%s", "%sdo%s", "%send%s", "%selseif%s"}, i)
  45.         else
  46.             s, e, p = find_multiple(str, {"%smatch%s", "%sfunction%s", "%sthen%s", "%sdo%s", "%send%s"}, i)
  47.         end
  48.         if p == "%send%s" then
  49.             return e
  50.         elseif p == "%selseif%s" then
  51.             return e
  52.         elseif p == nil then
  53.             return "UNBAL"
  54.         end
  55.         i = balanced_end(str, string.sub(p, 3, -3), e)
  56.         if i == "UNBAL" then
  57.             return i
  58.         end
  59.     end
  60. end
  61.  
  62. local function get_decls(str)
  63.     -- gather data declarations from source & remove
  64.     local datas = {}
  65.     local i = 0
  66.     local strout = ""
  67.     while true do
  68.         local n, a = string.find(str, "%sdata [%w]+", i+1)
  69.         if n == nil then
  70.             strout = strout .. string.sub(str, i+1)
  71.             break
  72.         end
  73.         strout = strout .. string.sub(str, i+1, n)
  74.         local e, d = string.find(str, "end", i+1)
  75.         local cont = string.sub(str, a+1, e-1)
  76.         local data = {}
  77.         for i, case in ipairs(split(cont)) do
  78.             local c = {}
  79.             local b, p = string.find(case, "%(")
  80.             if b == nil then
  81.                 c.name = case
  82.                 c.args = 0  
  83.             else
  84.                 c.name = string.sub(case, 1, p-1)
  85.                 c.args = #split(case, ",")
  86.             end
  87.             table.insert(data, c)
  88.         end
  89.         i = d
  90.         table.insert(datas, data)
  91.     end
  92.     return datas, strout
  93. end
  94.  
  95. local parseexprs, replace_case, replace_match
  96. local function parseexpr(str)
  97.     local n, o, name, body = string.find(str, "(%w+)(%b())")
  98.     if n == nil then
  99.         local b = string.find(str, ",")
  100.         if b == nil then
  101.             return {type="var",name=str}, ""
  102.         else
  103.             return {type="var", name=string.sub(str, 0, b-1)}, string.sub(str,b+1)
  104.         end
  105.     end
  106.     body = string.sub(body, 2, -2)
  107.     local obj = {type="data", name=name, body=parseexprs(body)}
  108.     local rem = string.sub(str, o+1)
  109.     local b = string.find(rem, ",")
  110.     if b == nil then
  111.         return obj, ""
  112.     else
  113.         return obj, string.sub(rem,b+1)
  114.     end
  115. end
  116.  
  117. parseexprs = function(str)
  118.     local t = {}
  119.     while str ~= "" do
  120.         local obj
  121.         obj, str = parseexpr(str)
  122.         table.insert(t, obj)
  123.     end
  124.     return t
  125. end
  126.  
  127. local function getCase(datas, data)
  128.     for i, x in ipairs(datas) do
  129.         for i, case in ipairs(x) do
  130.             if case.name == data then
  131.                 return i
  132.             end
  133.         end
  134.     end
  135. end
  136.  
  137. local function comparison(datas, var, pattern)
  138.     if pattern.type == "data" then
  139.         local out = var .. ".case == " .. getCase(datas, pattern.name)
  140.         for i, x in ipairs(pattern.body) do
  141.             if x.type == "data" then
  142.                 out = out .. " and " .. comparison(datas, var .. "[" .. i .. "]", x)
  143.             end
  144.         end
  145.         return out
  146.     else
  147.         return "true"
  148.     end
  149. end
  150.  
  151. local function destructure(datas, var, pattern)
  152.     if pattern.type == "var" then
  153.         return "local " .. pattern.name .. " = " .. var
  154.     else
  155.         local out = ""
  156.         for i, x in ipairs(pattern.body) do
  157.             out = out .. "\n" .. destructure(datas, var .. "[" .. i .. "]", x)
  158.         end
  159.         return out
  160.     end
  161. end
  162.  
  163. replace_match = function(datas, str)
  164.     while true do
  165.         local m, b, var = string.find(str, "%smatch (%w+)%s")
  166.         if m == nil then
  167.             return str
  168.         end
  169.         local e = balanced_end(str, "match", b)
  170.         local cont = string.sub(str, b, e-4)
  171.         str = string.sub(str, 1, m) .. replace_case(datas, cont, var) .. string.sub(str, e, -1)
  172.     end
  173. end
  174.  
  175. replace_case = function(datas, out, var)
  176.     local str = out
  177.     local count = 0
  178.     while true do
  179.         local m
  180.         local b
  181.         local p
  182.         m, b, p = string.find(str, "%scase ([^%s]+) do%s")
  183.         if m == nil then
  184.             for i=1,count do
  185.                 str = str .. "\nend"
  186.             end
  187.             return str
  188.         end
  189.         count = count + 1
  190.         local e = balanced_end(str, "do", b)
  191.         local cont = string.sub(str, b, e-5)
  192.         local pattern = parseexpr(p)
  193.         local bool = comparison(datas, var, pattern)
  194.         local body = destructure(datas, var, pattern)
  195.         str = string.sub(str, 1, m) .. "\nif " .. bool .. " then\n" .. body .. cont .. "\nelse\n" .. string.sub(str, e, -1)
  196.     end
  197. end
  198.  
  199. local function printpattern(pattern)
  200.     if pattern.type == "data" then
  201.         io.write(pattern.name)
  202.         io.write("(")
  203.         for i, v in ipairs(pattern.body) do
  204.             printpattern(v)
  205.             io.write(",")
  206.         end
  207.         io.write(")")
  208.     else
  209.         io.write(pattern.name)
  210.     end
  211. end
  212.  
  213. local function writeheaders(datas)
  214.     local out = ""
  215.     for i, x in ipairs(datas) do
  216.         for i, case in ipairs(x) do
  217.             out = out .. "\nlocal function " .. case.name .. "(...) return {case=" .. i .. ",...} end"
  218.         end
  219.     end
  220.     return out
  221. end
  222.  
  223. function preprocess(str)
  224.     local decls, str0 = get_decls(str)
  225.     local b = replace_match(decls, str0)
  226.     local h = writeheaders(decls)
  227.     return h .. b
  228. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement