Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: -- http://angg.twu.net/LUA/Rect.lua.html -- http://angg.twu.net/LUA/Rect.lua -- (find-angg "LUA/Rect.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2021sep14 -- -- This is another copy of the Rect class. See: -- (find-angg "LUA/lua50init.lua" "Rect") -- (find-dn6 "rect.lua" "Rect") -- -- This copy is the best place for tests, clean-ups, and mess-ups. -- «.Rect» (to "Rect") -- «.Rect-tests» (to "Rect-tests") -- «.SynTree» (to "SynTree") -- «.SynTree-tests» (to "SynTree-tests") -- «.DedTree» (to "DedTree") -- «.UndTree» (to "UndTree") -- «.UndTree-tests» (to "UndTree-tests") -- «.undtolatex» (to "undtolatex") -- «.undtolatex-tests» (to "undtolatex-tests") -- -- «.Rect-ded-tests» (to "Rect-ded-tests") -- ____ _ -- | _ \ ___ ___| |_ -- | |_) / _ \/ __| __| -- | _ < __/ (__| |_ -- |_| \_\___|\___|\__| -- -- «Rect» (to ".Rect") -- Also here: (find-angg "LUA/lua50init.lua" "Rect") torect = function (o) if otype(o) == "Rect" then return o end if type(o) == "string" then return Rect.new(o) end error() end Rect = Class { type = "Rect", new = function (str) return Rect(splitlines(str)) end, rep = function (str, n) local r=Rect{}; for i=1,n do r[i]=str end; return r end, from = function (o) if type(o) == "string" then return Rect.new(o) end if type(o) == "number" then return Rect.new(tostring(o)) end return o -- missing: test otypeness end, -- -- A hack to let us build syntax trees very quickly: syntree = function (op, a1, ...) if not a1 then return Rect.from(op) end local r = Rect.from(a1):syn1(op) for _,an in ipairs({...}) do r = r:synconcat(Rect.from(an)) end return r end, -- __tostring = function (rect) return rect:tostring() end, __concat = function (r1, r2) return torect(r1):concat(torect(r2)) end, __index = { tostring = function (rect) return table.concat(rect, "\n") end, copy = function (rect) return copy(rect) end, width = function (rect) return rect.w or foldl(max, 0, map(string.len8, rect)) end, push1 = function (rect, str) table.insert(rect, 1, str); return rect end, push2 = function (rect, str1, str2) return rect:push1(str2):push1(str1) end, pad0 = function (rect, y, w, c, rstr) rect[y] = ((rect[y] or "")..(c or " "):rep(w)):sub(1, w)..(rstr or "") return rect end, lower = function (rect, n, str) for i=1,n do rect:push1(str or "") end return rect end, concat = function (r1, r2, w, dy) r1 = r1:copy() w = w or r1:width() dy = dy or 0 for y=#r1+1,#r2+dy do r1[y] = "" end for y=1,#r2 do r1:pad0(y+dy, w, nil, r2[y]) end return r1 end, prepend = function (rect, str) return Rect.rep(str, #rect)..rect end, above = function (r1, r2) local r = copy(r1) for i=1,#r2 do table.insert(r, r2[i]) end return r end, -- -- Low-level methods for building syntax trees: -- syn1 draws a "|" above a rect and draws the opname above it, -- synconcat draws two syntax trees side by side and joins them with "_"s. syn1 = function (r1, opname, v) return r1:copy():push2(opname or ".", v or "|") end, synconcat = function (r1, r2, v) return r1:copy():pad0(1, r1:width()+2, "_") .. r2:copy():push2(".", v or "|") end, -- -- Low-level methods for building deduction trees: -- dedconcat draws two deduction trees side by side, -- dedsetbar draws or redraws the bar above the conclusion, -- dedaddroot adds a bar and a conclusion below some trees drawn -- side by side. dedconcat = function (r1, r2) local w = r1:width() + 2 if #r1 < #r2 then return r1:copy():lower(#r2-#r1):concat(r2, w) end if #r1 == #r2 then return r1:copy():concat(r2, w) end if #r1 > #r2 then return r1:copy():concat(r2, w, #r1-#r2) end end, dedsetbar = function (r, barchar, barname) if #r == 1 then table.insert(r, 1, "") end local trim = function (str) return (str:match("^(.-) *$")) end local strover = trim(r[#r-2] or "") -- the hypotheses above the bar local strunder = trim(r[#r]) -- the conclusion below the bar local len = max(#strover, #strunder) local bar = (barchar or "-"):rep(len) r[#r-1] = bar..(barname or "") return r end, dedaddroot = function (r, rootstr, barchar, barname) table.insert(r, "") -- The bar will be here. table.insert(r, rootstr) -- Draw the conclusion, return r:dedsetbar(barchar, barname) -- and then set the bar. end, }, } -- «Rect-tests» (to ".Rect-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Rect.lua" r = Rect.new "a\nbb\nccc" = r PP(r) = r:width() = r:copy():pad0(1, 4, nil, "d") = r:copy():pad0(1, 4, "_", "d") = r:copy():push2("op", "|") = r:copy():push2("op", "|"):pad0(1, r:width()+1, "_") = r:copy():push2("op", "|"):pad0(1, r:width()+1, "_")..r:copy():push2(".", "|") = "This => "..r.." <=" --]] -- ____ _____ -- / ___| _ _ _ _|_ _| __ ___ ___ -- \___ \| | | | '_ \| || '__/ _ \/ _ \ -- ___) | |_| | | | | || | | __/ __/ -- |____/ \__, |_| |_|_||_| \___|\___| -- |___/ -- -- «SynTree» (to ".SynTree") -- Also here: (find-angg "LUA/lua50init.lua" "SynTree") -- SynTree = Class { type = "SynTree", from = function (A) return deepcopymt(A, SynTree) end, tabletorect = function (o) local op = o[0] if type(op) == "number" then op = tostring(op) end if #o == 0 then return Rect.new(op or ".") end local r = SynTree.torect(o[1]):syn1(op) for i=2,#o do r = r:synconcat(SynTree.torect(o[i])) end return r end, torect = function (o) if type(o) == "number" then return Rect.new(o) end if type(o) == "string" then return Rect.new(o) end if type(o) == "table" then return SynTree.tabletorect(o) end end, __tostring = function (o) return o:torect():tostring() end, __index = { torect = function (o) return SynTree.torect(o) end, }, } -- «SynTree-tests» (to ".SynTree-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Rect.lua" abc = Rect.new "a\nbb\nccc" = abc PP(abc) = abc:syn1("op") = abc:syn1("op"):synconcat(abc) = abc:syn1("op"):synconcat(Rect.from "d") = abc:syn1("op"):synconcat(Rect.from(abc)) = abc:syn1("op", "?"):synconcat(Rect.from(abc), "::") syntree = Rect.syntree = syntree "a" = syntree("a", "b") = syntree(abc) = syntree("a", abc) = syntree("a", abc, "d") = syntree("a", abc, "d", abc) * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Rect.lua" s0 = {[0]="+", {[0]="*", "2", "3"}, {[0]="*", "4", "5"}} s0 = {[0]="+", {[0]="*", "2", "3"}, {[0]="*", "4", "5"}, {6, 7, 8}} s1 = SynTree.from(s0) = s1 PPPV(s1) PPPV(s1[1]) = mytostringpv(s1) = s1[0] = s1[1] --]] -- ____ _ _____ -- | _ \ ___ __| |_ _| __ ___ ___ -- | | | |/ _ \/ _` | | || '__/ _ \/ _ \ -- | |_| | __/ (_| | | || | | __/ __/ -- |____/ \___|\__,_| |_||_| \___|\___| -- -- «DedTree» (to ".DedTree") -- Also here: (find-angg "LUA/lua50init.lua" "DedTree") -- DedTree = Class { type = "DedTree", from = function (A) return deepcopymt(A, DedTree) end, torect = function (o) if type(o) == "number" then return Rect.new(o) end if type(o) == "string" then return Rect.new(o) end if type(o) == "table" then if #o == 0 then local r = DedTree.torect(o[0] or "?") r:dedsetbar(o.bar, o.label) return r else r = DedTree.torect(o[1]) for i=2,#o do r = r:dedconcat(dedtorect(o[i])) end return r:dedaddroot(o[0] or "?", o.bar, o.label) end end error() end, __tostring = function (o) return o:torect():tostring() end, __index = { torect = function (o) return DedTree.torect(o) end, }, } --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Rect.lua" d = DedTree.from d = DedTree.torect = d "a" = d {[0]="a"} = d {[0]="a", "b", "c"} = d {[0]="a", "b", {"c"}} = d {[0]="a", "b", {[0]="?", "c"}} = d {[0]="a", "b", {[0]="?"}} = d {[0]="a", "b", {[0]="c"}} = d {[0]="a", "b", {[0]="c", bar="-"}} = d {[0]="a", "b", {[0]="c", label="foo"}} = d {[0]="a", "b", {[0]="c", label="foo", bar="=", "d", "e"}} = d {[0]="a", "b", {[0]="c", label="foo", "d", "e"}} = d {[0]="a", "b", {[0]="c", "d", "e"}} A = {[0]="a", "b", {[0]="c", label="foo", bar="=", "d", "e"}} = DedTree.from(A) = DedTree.from(A)[0] = DedTree.from(A)[1] = DedTree.from(A)[2] = DedTree.from(A)[2].bar = DedTree.from(A)[2].label --]] -- _ _ _ _____ -- | | | |_ __ __| |_ _| __ ___ ___ -- | | | | '_ \ / _` | | || '__/ _ \/ _ \ -- | |_| | | | | (_| | | || | | __/ __/ -- \___/|_| |_|\__,_| |_||_| \___|\___| -- -- «UndTree» (to ".UndTree") -- UndTree = Class { type = "UndTree", from = function (A) return deepcopymt(A, UndTree) end, torect = function (o) if type(o) == "number" then return Rect.new(o) end if type(o) == "string" then return Rect.new(o) end if type(o) == "table" then return UndTree.from(o):utorect() end error() end, -- __tostring = function (o) return o:torect():tostring() end, -- __tostring = function (o) return UndTree.u8ify(o:torect():tostring()) end, u8ify1 = function (str) return "╰"..("─"):rep(#str - 2).."╯" end, u8ify = function (str) return (str:gsub("`%-*'", UndTree.u8ify1)) end, -- __index = { torect = function (o) return UndTree.torect(o) end, -- sep = " ", utorect0 = function (o) local r = UndTree.torect(o[1]) for i=2,#o do r = r..o.sep..UndTree.torect(o[i]) end return r end, utorect1 = function (o, width) local a,b,c,d = "`", "-", "'", "-" if width >= 2 then return Rect.from(a..b:rep(width-2)..c) end return Rect.from(d:rep(width)) end, utorect = function (o) local r0 = (#o == 0) and Rect.from(" ") or o:utorect0(1) local r2 = (o[0]) and Rect.from(o[0]) or Rect.from("") local w = max(r0:width(), r2:width()) local r1 = o:utorect1(w) return r0:above(r1):above(r2) end, }, } -- «UndTree-tests» (to ".UndTree-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Rect.lua" = UndTree.u8ify("`--'") = UndTree.from({[0]=4, 11, 22}):utorect() = UndTree.from({[0]=4, 11, 22}):utorect0() = UndTree.from({[0]=4, 11, 22}):utorect() = UndTree.from({[0]=4 }):utorect() = UndTree.from({[0]=nil, 11, 22}):utorect() = UndTree.from({ }):utorect() A = {[0]=nil, 11, 22} B = {[0]=3, 44, 55} B = {[0]=3, 44, A} C = {[0]=nil, A, B} = UndTree.from(A) = UndTree.from(C) PPP(UndTree.from(C)) -- (find-es "lua5" "install-5.1.5") = UndTree.__index:utorect1(4) = UndTree.__index:utorect1(2) = UndTree.__index:utorect1(1) = UndTree.__index:utorect1(0) r0, r1, r2 = UndTree.from({[0]=4, 11, 22}):utorect() = r0 = r1 = r2 A = Rect.from("a\nabc") B = Rect.from("|\na\nabcd") = A = B = A:above(B) u = UndTree.from {11, 222} = u:utorect0() r = Rect.from("") PPPV(r) = r:width() --]] -- «undtolatex» (to ".undtolatex") undtolatex = function (o, pre) if type(o) == "string" then return o end if type(o) == "number" then return tostring(o) end local s = " " local f = function (o) return undtolatex(o, pre..s).."\n"..pre..s end pre = pre or "" local upper = mapconcat(f, o, "") local lower = "}{"..o[0].."}" return "\\und{"..upper..lower end -- «undtolatex-tests» (to ".undtolatex-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Rect.lua" A = {[0]=22, 33, 44, 55} B = {[0]=66} C = {[0]=77, 88, A, B, 99} = undtolatex(A) = ".."..undtolatex(A, "..") = undtolatex(B) = undtolatex(C) = ".."..undtolatex(C, "..") --]] -- «Rect-ded-tests» (to ".Rect-ded-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Rect.lua" abc = Rect.new("a b\n----\nc") defgh = Rect.new(" d\n -\ne f g\n-------\nh") = abc = defgh = abc:dedconcat(defgh) = defgh:dedconcat(abc) = defgh:dedconcat(abc):dedaddroot("i") = defgh:dedconcat(abc):dedaddroot("i", "=") = defgh:dedconcat(abc):dedaddroot("i", "=", "foo") = defgh:dedconcat(abc):dedaddroot("iiiiiiiii", "=", "foo") = defgh:dedconcat(abc):dedaddroot("iiiiiiiiii", "=", "foo") = defgh:dedconcat(abc):dedaddroot("iiiiiiiiiii", "=", "foo") = Rect.new("") = Rect.new(""):dedaddroot("iiiii", "=", "foo") --]] -- See: (find-dn6 "treesegs.lua" "allsegments-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Rect.lua" dedtorect = DedTree.torect dedtorect = DedTree.from = dedtorect "a" = dedtorect {[0]="a"} = dedtorect {[0]="a", "b", "c"} = dedtorect {[0]="a", "b", {"c"}} = dedtorect {[0]="a", "b", {[0]="c"}} = dedtorect {[0]="a", "b", {[0]="c", bar="-"}} = dedtorect {[0]="a", "b", {[0]="c", label="foo"}} = dedtorect {[0]="a", "b", {[0]="c", label="foo", bar="=", "d", "e"}} = dedtorect {[0]="a", "b", {[0]="c", label="foo", "d", "e"}} = dedtorect {[0]="a", "b", {[0]="c", "d", "e"}} A = {[0]="a", "b", {[0]="c", label="foo", bar="=", "d", "e"}} = DedTree.from(A) A = {[0]="a", "b", {[0]="c", label="foo", bar="=", "d", "e"}} = DedTree.torect(A) = mytostringpv(DedTree.from(A)) A = {[0]="a", "b", {[0]="c", label="foo", bar="=", "d", "e"}} = mytostringpv(DedTree.torect(A)) = dedtorect(A) = DedTree.from(A) = DedTree.torect(A) --]] -- Local Variables: -- coding: utf-8-unix -- End: