-- This file: -- https://anggtwu.net/LUA/TreeSegs1.lua.html -- https://anggtwu.net/LUA/TreeSegs1.lua -- (find-angg "LUA/TreeSegs1.lua") -- Author: Eduardo Ochs -- -- The functions in this file handle the whitespace-sparated -- "segments" in "%:"-blocks, using data structures that are easy to -- print, but that need classes that can't be defined in a bottom-up -- fashion. -- -- Each "%:"-line becomes a "Segments" object. -- Each "Segments" object is a list of "Segment" objects. -- The "AllSegments" object is almost a list of "Segments" objects - -- "almost" because it can contains nils. -- -- To obtain the segments above a "Segment" object `seg' we use -- "seg:segsabove()", that takes the fields `y', `l', and `r' of -- `seg', looks at allsegments[y-1], and returns the segments that -- intersect the interval [l,r]. -- -- The code in heads["%:"] adds "Segments" objects to `allsegments', -- and for each `rootseg' of the form "^Name" it runs -- rootseg:rootnode():totreenode(), converts the resulting "TreeNode" -- object to LaTeX, and outputs LaTeX code of this form: -- -- \defded{Name}{...} -- -- To understand the data structures, run the tests in: -- (to "high-level-test") -- -- Supersedes: -- (find-dn6 "treesegs.lua") -- -- (defun e () (interactive) (find-angg "LUA/TreeSegs1.lua")) -- (defun o () (interactive) (find-dn6 "treesegs.lua")) -- -- «.TreeNode» (to "TreeNode") -- «.TreeNode-defded» (to "TreeNode-defded") -- «.TreeNode-tests» (to "TreeNode-tests") -- «.DefDed» (to "DefDed") -- «.DefDed-tests» (to "DefDed-tests") -- «.AllSegments» (to "AllSegments") -- «.allsegments» (to "allsegments") -- «.allsegments-tests» (to "allsegments-tests") -- «.segtotreenode» (to "segtotreenode") -- «.intersects» (to "intersects") -- «.Segment» (to "Segment") -- «.Segments» (to "Segments") -- «.tosegments» (to "tosegments") -- «.treesegtest» (to "treesegtest") -- «.high-level-test» (to "high-level-test") -- «.head» (to "head") -- «.head-:» (to "head-:") -- «.head-tests» (to "head-tests") require "DednatParse1" -- (find-angg "LUA/DednatParse1.lua") -- (find-angg "LUA/lua50init.lua" "DedTree") -- (find-dn6 "heads6.lua" "tree-head") -- _____ _ _ _ -- |_ _| __ ___ ___| \ | | ___ __| | ___ -- | || '__/ _ \/ _ \ \| |/ _ \ / _` |/ _ \ -- | || | | __/ __/ |\ | (_) | (_| | __/ -- |_||_| \___|\___|_| \_|\___/ \__,_|\___| -- -- «TreeNode» (to ".TreeNode") -- Based on: (find-dn6 "treetex.lua" "TreeNode") -- See: (find-dn6 "treetex.lua" "TreeNode" "format is much more strict") -- (find-angg "LUA/lua50init.lua" "DedTree") -- (find-angg "LUA/Rect.lua" "DedTree") -- TreeNode = Class { type = "TreeNode", from = function (o) if type(o) == "string" then return TreeNode {[0]=o} end if type(o) == "table" then local tn = {[0]=o[0], bar=o.bar, label=o.label} for i=1,#o do tn[i] = TreeNode.from(o[i]) end if #tn > 0 then tn.bar = tn.bar or "-" end return TreeNode(tn) end Error("TreeNode.from(o) failed") end, __tostring = function (tn) return tostring(tn:torect()) end, __index = { torect = function (tn) return dedtorect(tn) end, hasbar = function (tn) return tn.bar ~= nil end, barchar = function (tn) return tn.bar end, TeX_root = function (tn) return tn[0] end, TeX_label = function (tn) return tn.label end, nhyps = function (tn) return #tn end, hypslist = function (tn) return tn end, outputdefded = function (tn) DefDed.fromnameseg(tn):output() end, }, } -- «TreeNode-tests» (to ".TreeNode-tests") --[==[  (eepitch-lua51)  (eepitch-kill)  (eepitch-lua51) dofile "TreeSegs1.lua" ded = {[0]="a", "b", {[0]="c", "d", "e", bar="=", label="foo"}} ded = {[0]="a", "b", {[0]="c", "d", {[0]="e", bar="-"}, bar="=", label="foo"}} = dedtorect(ded) tn = TreeNode.from(ded) PPV(ded) PPV(tn) = tn = otype(tn) = otype(tn[1]) = otype(ded) = otype(ded[1]) TreeNode_deftree = tn:TeX_subtree("") = tn:TeX_subtree(" ") = tn:TeX_deftree("foo", "?") --]==] -- ____ __ ____ _ -- | _ \ ___ / _| _ \ ___ __| | -- | | | |/ _ \ |_| | | |/ _ \/ _` | -- | |_| | __/ _| |_| | __/ (_| | -- |____/ \___|_| |____/ \___|\__,_| -- -- «DefDed» (to ".DefDed") -- See: (find-angg "LUA/TreeTeX1.lua" "ProofSty" "Replaces:") DefDed = Class { type = "DefDed", fromnameseg = function (nameseg) local name = nameseg.t:gsub("^%^", "") local rootnode = nameseg:rootnode() local comment = tf and (" % "..tf:hyperlink()) or "" return DefDed {nameseg=nameseg, name=name, rootnode=rootnode, comment=comment} end, __index = { output_print = function (dd) print(dd.name..":") print(" "..dd.rootnode:totreenode():torect()) print() end, output_proofsty = function (dd) local p = proofsty:defded(dd.name, dd.rootnode:totreenode(), dd.comment) output(tostring(p)) end, output_ebproof = function (dd) local p = ebproof:defded(dd.name, dd.rootnode:totreenode(), dd.comment) output(tostring(p)) end, -- output = function (dd) return dd:output_print() end, }, } -- «DefDed-tests» (to ".DefDed-tests") --[==[  (eepitch-lua51)  (eepitch-kill)  (eepitch-lua51) require "TreeSegs1" = treesegtest [[ %: H %: - ... %: A B C E F \Pi %: =======r ::::\phi ... %: D G I %: ------------------- %: J %: %: ^bars ]] nameseg = allsegments[y-1][1] = nameseg dd = DefDed.fromnameseg(nameseg) = dd.rootnode = dd.rootnode:totreenode() dd:output() require "TreeTeX1" output = print dd:output_proofsty() DefDed.__index.output = function (dd) return dd:output_proofsty() end dd:output() DefDed.__index.output = function (dd) return dd:output_ebproof() end dd:output() --]==] -- _ _ _ ____ _ -- / \ | | / ___| ___ __ _ _ __ ___ ___ _ __ | |_ ___ -- / _ \ | | \___ \ / _ \/ _` | '_ ` _ \ / _ \ '_ \| __/ __| -- / ___ \| | |___) | __/ (_| | | | | | | __/ | | | |_\__ \ -- /_/ \_\_|_|____/ \___|\__, |_| |_| |_|\___|_| |_|\__|___/ -- |___/ -- -- «AllSegments» (to ".AllSegments") -- «allsegments» (to ".allsegments") AllSegments = Class { type = "AllSegments", __tostring = function (allsegs) return allsegs:tostring() end, __index = { last = function (allsegs, linenow) -- unused? for i=linenow,1,-1 do if allsegs[i] and allsegs[i][1] then return allsegs[i][1] end end end, lastlinen = function (allsegs) return table.reverse(sortedkeys(allsegments))[1] end, tostring = function (allsegs) local f = function (n) return pformat("%s: %s", n, allsegs[n]) end return mapconcat(f, seq(1, allsegs:lastlinen() or 0), "\n") end, }, } allsegments = AllSegments {} -- «allsegments-tests» (to ".allsegments-tests") -- See: (to "treesegtest-tests") --[==[  (eepitch-lua51)  (eepitch-kill)  (eepitch-lua51) dofile "TreeSegs1.lua" = treesegtest [[ %: %: a b %: ----? %: c %: %: ^C ]] = allsegments = allsegments[y-1] = allsegments[y-3] = allsegments[y-3][1] = allsegments[y-3][1]:totreenode() --]==] -- _ _ _ -- ___ ___ __ _| |_ ___ | |_ _ __ ___ ___ _ __ ___ __| | ___ -- / __|/ _ \/ _` | __/ _ \| __| '__/ _ \/ _ \ '_ \ / _ \ / _` |/ _ \ -- \__ \ __/ (_| | || (_) | |_| | | __/ __/ | | | (_) | (_| | __/ -- |___/\___|\__, |\__\___/ \__|_| \___|\___|_| |_|\___/ \__,_|\___| -- |___/ -- -- «segtotreenode» (to ".segtotreenode") -- See: (find-angg "LUA/TreeTeX1.lua" "TreeNode") segtotreenode = function (seg) local bar = seg:firstsegabove() if bar then local bart = bar.t local barchars = bart:match("^-+") or bart:match("^=+") or bart:match("^:+") or bart:match("^.+") if not barchars then Error("Bad bar: "..bart) end local barchar = bart:sub(1, 1) local label = bart:sub(1 + #barchars) local hyps = bar:segsabove() local T = map(segtotreenode, hyps) T[0] = seg.t T.bar = barchar T.label = label return TreeNode(T) end return TreeNode {[0]=seg.t} end -- «intersects» (to ".intersects") intersects = function (start1, end1, start2, end2) if end1 <= start2 then return false end if end2 <= start1 then return false end return true end -- ____ _ -- / ___| ___ __ _ _ __ ___ ___ _ __ | |_ -- \___ \ / _ \/ _` | '_ ` _ \ / _ \ '_ \| __| -- ___) | __/ (_| | | | | | | __/ | | | |_ -- |____/ \___|\__, |_| |_| |_|\___|_| |_|\__| -- |___/ -- -- «Segment» (to ".Segment") Segment = Class { type = "Segment", __tostring = function (seg) return seg:tostring() end, __index = { tostring = function (seg) return pformat("[y:%s i:%s l-r:%s-%s t:%s]", seg.y, seg.i, seg.l, seg.r, seg.t) end, iswithin = function (seg, l, r) return intersects(seg.l, seg.r, l, r) end, intersects = function (seg1, seg2) return intersects(seg1.l, seg1.r, seg2.l, seg2.r) end, segsabove_ = function (seg, dy) return allsegments[seg.y - dy] or Segments {} end, segsabove = function (seg) return seg:segsabove_(1):allintersecting(seg) end, firstsegabove = function (seg) return seg:segsabove()[1] end, rootnode = function (seg) return seg:segsabove_(2):firstwithin(seg.l, seg.l + 1) end, totreenode = function (seg) return segtotreenode(seg) end, torect = function (seg) return dedtorect(seg:totreenode()) end, }, } -- ____ _ -- / ___| ___ __ _ _ __ ___ ___ _ __ | |_ ___ -- \___ \ / _ \/ _` | '_ ` _ \ / _ \ '_ \| __/ __| -- ___) | __/ (_| | | | | | | __/ | | | |_\__ \ -- |____/ \___|\__, |_| |_| |_|\___|_| |_|\__|___/ -- |___/ -- -- «Segments» (to ".Segments") Segments = Class { type = "Segments", __tostring = function (segs) return segs:tostring() end, __index = { tostring = function (segs) local f = function (i) return pformat("%s=%s", i, segs[i]) end return mapconcat(f, sortedkeys(segs), " ") end, -- allwithin = function (segs, l, r) local segsw = Segments {} for _,seg in ipairs(segs) do if seg:iswithin(l, r) then table.insert(segsw, seg) end end return segsw end, firstwithin = function (segs, l, r) return segs:allwithin(l, r)[1] end, allintersecting = function (segs, seg) return segs:allwithin(seg.l, seg.r) end, firstintersecting = function (segs, seg) return segs:allwithin(seg.l, seg.r)[1] end, -- outputdefdeds = function (segs) for _,seg in ipairs(segs) do local name = seg.t:match("^%^(.*)") if name then DefDed.fromnameseg(seg):output() end end end, }, } -- «tosegments» (to ".tosegments") -- Uses: (find-angg "LUA/DednatParse1.lua" "setsubj") -- (find-angg "LUA/DednatParse1.lua" "getword") tosegments = function (str, y, pos_) local T = {} setsubj(untabify8(str), pos_) while getword() do table.insert(T, Segment {y=y, i=#T+1, l=startcol, r=endcol, t=word}) end return Segments(T) end -- «treesegtest» (to ".treesegtest") treesegtest = function (bigstr) y = 1 for _,li in ipairs(splitlines(bigstr)) do allsegments[y] = tosegments(li, y) y = y + 1 end return allsegments[y - 1][1] -- return first segment from last line end -- «high-level-test» (to ".high-level-test") --[==[  (eepitch-lua51)  (eepitch-kill)  (eepitch-lua51) dofile "TreeSegs1.lua" root = treesegtest [[ %: %: a b %: ====? %: c %: %: ^r ]] = otype(allsegments) = otype(allsegments[y-1]) = otype(allsegments[y-1][1]) = otype(root) = allsegments = allsegments[y-1] = allsegments[y-1][1] = root = root:rootnode() = root:rootnode():totreenode() = allsegments[3] = allsegments[3][1]:segsabove() = allsegments[3][1]:firstsegabove() = allsegments[6] = allsegments[6]:outputdefdeds() --]==] -- _ _ _ -- | | | | ___ __ _ __| | -- | |_| |/ _ \/ _` |/ _` | -- | _ | __/ (_| | (_| | -- |_| |_|\___|\__,_|\__,_| -- -- «head» (to ".head") -- «head-:» (to ".head-:") -- (find-dn6 "heads6.lua" "tree-head") registerhead = registerhead or function () return nop end registerhead "%:" { name = "tree", action = function () local i,j,treelines = tf:getblock() for k=i,j do allsegments[k] = tosegments(tf[k], k) allsegments[k]:outputdefdeds() end end, } -- «head-tests» (to ".head-tests") --[==[  (eepitch-lua51)  (eepitch-kill)  (eepitch-lua51) loaddednat7() dednat7oldheads() = heads = help(heads["%:"].action) bigstr = [[ %: - %: a b d e %: ====? ::::foo %: c f %: %: ^r ^s ]] tf = TeXFile.from("A", bigstr) texlines = tf = tf:info() pu("end") = tf:info() require "TreeSegs1" tf = TeXFile.from("A", bigstr) pu("end") require "TreeTeX1" tf = TeXFile.from("A", bigstr) pu("end") = help(heads["%:"].action) --]==] -- Local Variables: -- coding: utf-8-unix -- End: