|
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")
-- (find-LATEX "dednat6/rect.lua" "Rect")
--
-- torect = function (o)
-- if otype(o) == "Rect" then return o end
-- if type(o) == "string" then return Rect.from(o) end
-- if type(o) == "new" then return Rect.from(o) end
-- error()
-- end
torect = function (o) return Rect.from(o) 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 Rect(copy(o)) -- o needs to be a list of strings
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,
__div = function (r1, r2) return torect(r1):above(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 = Rect.from "a\nbb\nccc"
r = (Rect.from "a\nbb\nccc") / "dddd\neeeee"
r = (Rect.from "a\nbb\nccc") / {"dddd", "eeeee"}
= 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: