Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: -- http://angg.twu.net/LUA/Prad1.lua.html -- http://angg.twu.net/LUA/Prad1.lua -- (find-angg "LUA/Prad1.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- -- (defun l () (interactive) (find-angg "LUA/Prad1.lua")) -- (defun o () (interactive) (find-angg "LUA/Pis1.lua")) -- «.PradOutput» (to "PradOutput") -- «.PradOutput-tests» (to "PradOutput-tests") -- «.PradContext» (to "PradContext") -- «.PradContext-tests» (to "PradContext-tests") -- «.PradStruct» (to "PradStruct") -- «.PradStruct-tests» (to "PradStruct-tests") -- «.PradClass» (to "PradClass") -- «.PradClass-tests» (to "PradClass-tests") spaces = function (n) return string.rep(" ", n) end delnewline = function (str) return (str:gsub("\n$", "")) end -- ____ _ ___ _ _ -- | _ \ _ __ __ _ __| |/ _ \ _ _| |_ _ __ _ _| |_ -- | |_) | '__/ _` |/ _` | | | | | | | __| '_ \| | | | __| -- | __/| | | (_| | (_| | |_| | |_| | |_| |_) | |_| | |_ -- |_| |_| \__,_|\__,_|\___/ \__,_|\__| .__/ \__,_|\__| -- |_| -- «PradOutput» (to ".PradOutput") -- The "print"s that are run by a Prad object -- are "redirected" to a PradOutput object. -- PradOutput = Class { new = function () return PradOutput({}) end, type = "PradOutput", __tostring = function (po) return po:tostring("contract") end, __index = { add0 = function (po, line) table.insert(po, line) return po end, add1 = function (po, ctx, line, suffix) return po:add0(ctx.indent .. line .. (suffix or ctx.suffix) .. "\n") end, -- contractible0 = function (po, i) -- if it ends with a "{\n" return po[i]:match("^(.*{)%%?\n$") -- then return its left part end, contractible1 = function (po, j, n) if po[j]:sub(1, n) == spaces(n) -- if its starts with n spaces then return po[j]:sub(n+1) -- then return its right part end end, contractifpossible = function (po, i) local a = po:contractible0(i) local b = a and po:contractible1(i + 1, #a) if b then po[i] = a po[i+1] = b end end, contract = function (po) local po = copy(po) for i=#po-1,1,-1 do po:contractifpossible(i) end return po end, -- tostring = function (po, contract) if contract then po = po:contract() end return delnewline(table.concat(po)) end, }, } -- «PradOutput-tests» (to ".PradOutput-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Prad1.lua" po = PradOutput({ "abcd{%\n", " foo\n" }) PPP(po) = po:tostring() = po:tostring("contract") = po --]] -- ____ _ ____ _ _ -- | _ \ _ __ __ _ __| |/ ___|___ _ __ | |_ _____ _| |_ -- | |_) | '__/ _` |/ _` | | / _ \| '_ \| __/ _ \ \/ / __| -- | __/| | | (_| | (_| | |__| (_) | | | | || __/> <| |_ -- |_| |_| \__,_|\__,_|\____\___/|_| |_|\__\___/_/\_\\__| -- -- «PradContext» (to ".PradContext") -- PradContext = Class { type = "PradContext", new = function (indent, suffix) return PradContext {indent=(indent or ""), suffix=(suffix or "")} end, __tostring = mytostringp, __index = { copy = function (pc) return copy(pc) end, set = function (pc, key, val) pc[key] = val; return pc end, copyset = function (pc, key, val) return pc:copy():set(key, val) end, copyindent = function (pc, extraindent) return pc:copyset("indent", pc.indent .. (extraindent or " ")) end, }, } -- «PradContext-tests» (to ".PradContext-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Prad1.lua" = PradContext.new() = PradContext.new():copyindent() = PradContext.new():copyindent(" ") = PradContext.new():copy() = PradContext.new():copy():set("foo", "bar") = PradContext.new():copyset("foo", "bar") --]] -- ____ _ ____ _ _ -- | _ \ _ __ __ _ __| / ___|| |_ _ __ _ _ ___| |_ -- | |_) | '__/ _` |/ _` \___ \| __| '__| | | |/ __| __| -- | __/| | | (_| | (_| |___) | |_| | | |_| | (__| |_ -- |_| |_| \__,_|\__,_|____/ \__|_| \__,_|\___|\__| -- -- «PradStruct» (to ".PradStruct") -- The class PradStruct implements a way to print -- the low-level structure of a Prad object... like this: -- -- > a = PradList {"aa", PradSub {b="BEGIN", e="END", 20, 24}, "aaa"} -- > = a:tostruct() -- PradList {( -- 1 = "aa", -- 2 = PradSub {( -- b = "BEGIN", -- e = "END", -- 1 = 20, -- 2 = 24 -- )}, -- 3 = "aaa" -- )} PradStruct = Class { type = "PradStruct", tostring = function (o, ctx) return PradStruct.print(o, nil, ctx):tostring() end, -- comparekeys = function (key1, key2) local type1, type2 = type(key1), type(key2) if type1 ~= type2 then return type1 > type2 else return key1 < key2 end end, sortedkeys = function (A) local lt = PradStruct.comparekeys return sorted(keys(A), lt) end, keyprefix = function (key) if key == nil then return "" end return format("%s = ", key) end, genkvpcs = function (A) return cow(function () local keys = PradStruct.sortedkeys(A) for i,key in ipairs(keys) do local val = A[key] local keyprefix = PradStruct.keyprefix(key) local comma = (i < #keys) and "," or "" coy(key, val, keyprefix, comma) end end) end, be = function (o, keyprefix, comma) keyprefix = keyprefix or "" comma = comma or "" if type(o) ~= "table" then error() end if getmetatable(o) == nil then return keyprefix.."{", "}"..comma end local b = format("%s%s {(", keyprefix, otype(o)) local e = format(")}%s", comma) return b,e end, -- printitem = function (o, out, ctx, key, comma) if type(o) == "table" then local keyprefix = PradStruct.keyprefix(key) local b,e = PradStruct.be(o, keyprefix, comma) local newctx = ctx:copyindent(" ") out:add1(ctx, b) for key,val,keyprefix,comma in PradStruct.genkvpcs(o) do PradStruct.printitem(val, out, newctx, key, comma) end out:add1(ctx, e) else local keyprefix = PradStruct.keyprefix(key) out:add1(ctx, keyprefix..mytostring(o)..(comma or "")) end end, print = function (o, out, ctx, key, comma) if type(ctx) == "string" then ctx = PradContext.new(ctx) end out = out or PradOutput.new() ctx = ctx or PradContext.new() PradStruct.printitem(o, out, ctx, key, comma) return out end, -- __index = { }, } -- «PradStruct-tests» (to ".PradStruct-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Prad1.lua" a = {b="BB", e="EE", "a", "aa", 42} b = PradSub {b="BB", e="EE", "a", "aa", 42} c = PradList {b, 333, {"foo", 200}} PP(PradStruct.sortedkeys(a)) for key,val,keyprefix,comma in PradStruct.genkvpcs(a) do print(key,val,keyprefix,comma) end PP(PradStruct.be(a)) PP(PradStruct.be(a, "foo = ", ",")) PP(PradStruct.be(b)) PP(PradStruct.be(b, "foo = ", ",")) out = PradOutput.new() ctx = PradContext.new() PradStruct.print(c, out, ctx) PradStruct.print("foo", out, ctx) PradStruct.print("foo", out, ctx, "k", ",") = out = PradStruct.print(c) = PradStruct.print(c):tostring() = PradStruct.print(c, nil, ":: "):tostring() = PradStruct.tostring(c) = PradStruct.tostring(c, ":: ") --]] -- ____ _ ____ _ -- | _ \ _ __ __ _ __| |/ ___| | __ _ ___ ___ -- | |_) | '__/ _` |/ _` | | | |/ _` / __/ __| -- | __/| | | (_| | (_| | |___| | (_| \__ \__ \ -- |_| |_| \__,_|\__,_|\____|_|\__,_|___/___/ -- -- «PradClass» (to ".PradClass") -- Our printable algebraic datatypes are objects of classes that -- inherit from PradClass. An example: -- -- > = PradList {"aa", PradSub {b="BEGIN", e="END", "20", "42"}, "aaa"} -- aa -- BEGIN -- 20 -- 42 -- END -- aaa -- PradClass = Class { type = "PradClass", from = function (classtable) Class(classtable) setmetatable(classtable.__index, { __index = PradClass.__index }) return classtable end, __index = { add0 = function (prad, out, ctx, line) return out:add0(line) end, add1 = function (prad, out, ctx, line, suffix) return out:add0(ctx.indent .. line .. (suffix or ctx.suffix) .. "\n") end, -- printitem = function (prad, out, ctx, item) if type(item) == "string" then prad:add1(out, ctx, item) else item:print(out, ctx) end end, printitems = function (prad, out, ctx) for i,item in ipairs(prad) do prad:printitem(out, ctx, item) end end, -- tostring = function (prad, out, ctx) return prad:tooutput(out, ctx):tostring("contract") end, tooutput = function (prad, out, ctx) if type(ctx) == "string" then ctx = PradContext.new(ctx) end out = out or PradOutput.new() ctx = ctx or PradContext.new() prad:print(out, ctx) return out end, tostruct = function (prad) return PradStruct.tostring(prad) end, }, } PradList = PradClass.from { type = "PradList", __tostring = function (pl) return pl:tostring() end, __index = { print = function (pl, out, ctx) pl:printitems(out, ctx) end, }, } PradSub = PradClass.from { type = "PradSub", __tostring = function (ps) return ps:tostring() end, __index = { print = function (ps, out, ctx) local newctx = ctx:copyindent() ps:add1(out, ctx, (ps.b or "{")) ps:printitems(out, newctx) ps:add1(out, ctx, (ps.e or "}")) end, }, } -- «PradClass-tests» (to ".PradClass-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Prad1.lua" a = PradList {"aa", "aaa"} b = PradList {"bb", a, "bbb"} c = PradSub {"cc", "ccc"} d = PradList {"dd", b, c, "ddd"} e = PradSub {b="BEGIN", e="END", "ee", d, "eee"} = a = b = c = d = d:tostring(nil, ":: ") = e = PradStruct.tostring(e) = PradList {"aa", PradSub {b="BEGIN", e="END", "20", "42"}, "aaa"} --]] -- Local Variables: -- coding: utf-8-unix -- End: