Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
#!/usr/bin/lua -f -- (find-es "lua" "dednat") -- (find-angg "LUA/inc.lua") -- (fooi "process_tatsuta" "tatsuta_process") -- (fooi "test_donode" "iprint_donode" "process_test" "iprint_process") -- (fooi "node_prepstrings" "prepstrings_node" "bar_prepstrings" "prepstrings_bar") -- «.part0» (to "part0") -- «.split_into_segments» (to "split_into_segments") -- «.segments_intersecting» (to "segments_intersecting") -- «.psegs» (to "psegs") -- «.part1» (to "part1") -- «.process_reeplspecline» (to "process_reeplspecline") -- «.collect_dednameseg» (to "collect_dednameseg") -- «.process_lines» (to "process_lines") -- «.process_stuff» (to "process_stuff") -- «.part2» (to "part2") -- «.traversal_helpers» (to "traversal_helpers") -- «.p_string» (to "p_string") -- «.nonrec_prepstrings_node» (to "nonrec_prepstrings_node") -- «.nonrec_prepstrings_bar» (to "nonrec_prepstrings_bar") -- «.prepstrings_node» (to "prepstrings_node") -- -- «.iprint_donode» (to "iprint_donode") -- «.iprint_process» (to "iprint_process") -- «.tatsuta_donode» (to "tatsuta_donode") -- «.tatsuta_process» (to "tatsuta_process") -- «.buss_donode» (to "buss_donode") -- «.buss_process» (to "buss_process") -- -- «.top_level» (to "top_level") -- dofile(getenv("HOME").."/LUA/inc.lua") -- We must arrange for inc.lua to be loaded before this file... -- (find-angg "LATEX/Makefile" "dednat.lua") -- -- DEDNATLUA = lua $(HOME)/LUA/inc.lua -f $(HOME)/LUA/dednat.lua -- DEDNATLUA_TATSUTA = $(DEDNATLUA) 'tatsuta(arg[2],arg[3])' -- DEDNATLUA_BUSS = $(DEDNATLUA) 'buss(arg[2],arg[3])' -- lines[1] = "%:*->*\\to *" -- lines[2] = "" -- lines[3] = " a " -- lines[4] = " -r " -- lines[5] = " b " -- lines[6] = "" -- lines[6] = " ^tree1 " -- repls[1].strfrom = "->" -- repls[1].strto = "\\to " -- repls[1].f = function (str) return gsub(str, "%-%>", "\\to ") end -- segments[1] = {} -- segments[2] = {} -- segments[3].string = "a" -- segments[3].string.pbeg = 2 -- segments[3].string.pend = 3 -- segments[3].string = {} -- strto = "\\to " ----- «part0» (to ".part0") ----- Part 0: basic functions for segments: split a line into ----- segments, check which segments of a line intersect a given ----- region, print a list of segments. ----- -- «split_into_segments» (to ".split_into_segments") -- split_into_segments(" aa bb ") --> {{string="aa", pbeg=2, pend=4}, ...} function split_into_segments(line) local from, arr, p1, p2 = 1, {} from = 1 while 1 do p1, p2 = strfind(line, "([^%s]+)", from) if not p1 then return arr end tinsert(arr, {string = strsub(line, p1, p2), pbeg = p1-1, pend = p2}) from = p2 + 1 end end -- «segments_intersecting» (to ".segments_intersecting") function segments_intersecting(segments, pbeg, pend) local isegments = {} if type(pbeg) == "table" then pbeg, pend = pbeg.pbeg, pbeg.pend end foreachi(segments, function (i, seg) if not (seg.pend <= %pbeg or %pend <= seg.pbeg) then tinsert(%isegments, seg) end end) return isegments end -- «psegs» (to ".psegs") -- Functions to print lists of segments (obsolete). -- function segimager(seg) return format("{string=%q pbeg=%d pend=%d}", seg.string, seg.pbeg, seg.pend) end function psegs(segs) print(arrtostr(segs, "", " ", "", segimager)) end ----- «part1» (to ".part1") ----- ----- -- «process_reeplspecline» (to ".process_reeplspecline") -- If a line has enough "^O"s process it as a replspec line and return -- ""; else return it unchanged (which means "process it further"). -- -- (find-node "(lua)Patterns" "magic") -- function process_replspecline(i) local _, strfrom, strto, qstrfrom if strsub(lines[i],1,2) ~= "%:" then return "" -- hack: discard non-"%:" line end _, _, strfrom, strto = strfind(lines[i], "^%%?:?*(.*)*(.*)*") if strfrom then qstrfrom = gsub(strfrom, "([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1") tinsert(repls, { strfrom = strfrom, strto = strto, f = function (str) return gsub(str, %qstrfrom, %strto) end }) return "" -- replspec lines should not be split into segments end return lines[i] -- return unchanged for further processing end -- «collect_dednameseg» (to ".collect_dednameseg") -- If a segment starts with "^" store it into dednamesegs, prepare the -- data structure that makes the thing above it into a deduction tree, -- and return the seg; if it doesn't start with "^", return nil. -- function collect_dednameseg(i, j) local seg, _, rest seg = segments[i][j] _, _, rest = strfind(seg.string, "^%^(.*)") if rest then tinsert(dednamesegs, seg) seg.dedname = rest seg.dedroot = segments_intersecting(segments[i-2], seg.pbeg, seg.pend)[1] if not seg.dedroot then printf("line %d col %d string \"%s\": no dedroot!\n", seg.line, seg.pbeg, seg.string) end return seg -- signal that we may want to process its tree end end -- «process_lines» (to ".process_lines") -- If a line is a replspec, process it accordingly; else split it into -- segments, and for each segment set some extra fields in it -- (segsabove and line) and submit it to collect_dednamesegs; if it -- was a dednameseg and travfunc was given then submit it to travfunc. -- function process_lines(travfunc) local travstring, i, j, line, segs, prevsegs, seg travstring = "" for i = 1, getn(lines) do line = process_replspecline(i) -- line="" if no further processing needed line = untabify_line(gsub(line, "^%%:", " ")) segments[i] = split_into_segments(line) segs = segments[i] prevsegs = segments[i-1] or {} for j = 1, getn(segs) do seg = segs[j] seg.line = i seg.segsabove = segments_intersecting(prevsegs, seg.pbeg, seg.pend) seg = collect_dednameseg(i, j) if seg then if travfunc then travstring = travstring .. travfunc(seg) end end end end return travstring end -- «process_stuff» (to ".process_stuff") -- Process a chunk of text (coming from a file or from an immediate -- string) in the standard way: reset the global variables lines, -- repls, segments and dednamesegs and invoke process_lines with -- argument travfunc; return the string that process_lines return, -- that is the concatenation of the results of doing travfunc on each -- dednameseg. -- -- (to "iprint_process") -- function process_stuff(fname, filecontents, travfunc) if fname then filecontents = readfile(fname) end lines = split1(filecontents, "\n") repls = {} segments = {} dednamesegs = {} return process_lines(travfunc) end ----- «part2» (to ".part2") ----- Part 2: traversals. Here we define the functions that will act ----- on deduction trees, recursively from the dedroot (but starting ----- at the dednameseg); these functions are fed to process_stuff to ----- process a chunk of text in a certain way and produce the TeX ----- code for its deduction trees. -- «traversal_helpers» (to ".traversal_helpers") -- Functions to help traversing a tree. -- function spaces(n) return strrep(" ", n) end function upbar(nodeseg) return nodeseg.segsabove and nodeseg.segsabove[1] end function upnodes(barseg) return barseg.segsabove end -- return {} if none -- «p_string» (to ".p_string") -- Apply all the replacement operations on a string. -- function p_string(str) local i for i = 1, getn(repls) do str = repls[i].f(str) end return str end -- «nonrec_prepstrings_node» (to ".nonrec_prepstrings_node") -- function nonrec_prepstrings_node(nodeseg) nodeseg.p_string = nodeseg.p_string or p_string(nodeseg.string) end -- «nonrec_prepstrings_bar» (to ".nonrec_prepstrings_bar") -- function nonrec_prepstrings_bar(barseg) if barseg.barchar then return end local _, barchar, rstr _, _, barstr, rstr = strfind(barseg.string, "^(-+)(.*)") if not barstr then _, _, barstr, rstr = strfind(barseg.string, "^(=+)(.*)") end if not barstr then printf("line %d col %d string \"%s\": bad bar!\n", barseg.line, barseg.pbeg, barseg.string) end barseg.barchar = strsub(barstr, 1, 1) barseg.rstring = rstr barseg.p_rstring = p_string(rstr) end -- «prepstrings_node» (to ".prepstrings_node") -- A function that recursively prepares the -- replaced strings for an entire tree. -- function prepstrings_node(nodeseg) nonrec_prepstrings_node(nodeseg) local upbarseg = upbar(nodeseg) if upbarseg then nonrec_prepstrings_bar(upbarseg) foreachi(upnodes(upbarseg), function (i, seg) prepstrings_node(seg) end) end end -- "iprint": a simple traversal that will print each node and bar in -- an indented way. -- -- «iprint_donode» (to ".iprint_donode") function iprint_donode(nodeseg, n) local upbarseg = upbar(nodeseg) print(spaces(n) .. nodeseg.p_string) if upbarseg then print(spaces(n+1) .. upbarseg.barchar .. " " .. upbarseg.p_rstring) foreachi(upnodes(upbarseg), function(i, x) iprint_donode(x, %n+2) end) end end -- «iprint_process» (to ".iprint_process") function iprint_process(fname, filecontents) return process_stuff(fname, filecontents, function (seg) prepstrings_node(seg.dedroot) iprint_donode(seg.dedroot, 1) return "" end) end -- A traversal that generates TeX code for the trees using the macros -- in Makoto Tatsuta's proof.sty package. -- (find-fline "~/LATEX/proof.edrx.sty" "infer[") mathstrut = "\\mathstrut " -- «tatsuta_donode» (to ".tatsuta_donode") function tatsuta_donode(nodeseg, indent) local upbarseg = upbar(nodeseg) if upbarseg then local modifier = "" if upbarseg.barchar == "=" then modifier = "=" end if upbarseg.p_rstring ~= "" then modifier = modifier .. "[" .. upbarseg.p_rstring .. "]" end local upnodesegs = upnodes(upbarseg) local uppers = {} local i for i = 1, getn(upnodesegs) do tinsert(uppers, "\n" .. tatsuta_donode(upnodesegs[i], indent + 1) .. " ") end return format("%s\\infer%s{ %s %s }{%s}", spaces(indent), modifier, mathstrut, nodeseg.p_string, join(uppers, "&")) else return spaces(indent) .. mathstrut .. nodeseg.p_string end end -- «tatsuta_process» (to ".tatsuta_process") function tatsuta_process(fname, filecontents) return process_stuff(fname, filecontents, function (seg) prepstrings_node(seg.dedroot) return format("\\defded{%s}{\n%s }\n", seg.dedname, tatsuta_donode(seg.dedroot, 1)) end) end -- (find-es "tex" "bussproofs") -- (find-shttpfile "www.math.ucla.edu/~asl/bussproofs.sty") -- (find-shttpfile "www.math.ucla.edu/~asl/bussproofs.sty" "doubleLine") -- (find-shttpfile "www.math.ucla.edu/~asl/bussproofs.sty" "The above proof") -- (find-shttpfile "www.math.ucla.edu/~asl/bussproofs.sty" "RightLabel{") -- «buss_donode» (to ".buss_donode") function buss_donode(nodeseg, indent) local upbarseg = upbar(nodeseg) local sp, sp1 = spaces(indent), spaces(indent + 1) if upbarseg then local modifier = "" if upbarseg.barchar == "=" then modifier = "\\doubleLine " end if upbarseg.p_rstring ~= "" then modifier = modifier.."\\RightLabel{\\( "..upbarseg.p_rstring.." \\)} " end local upnodesegs = upnodes(upbarseg) local n = getn(upnodesegs) local upstr = "" local thispstring = mathstrut .. nodeseg.p_string local i if n == 0 then return sp.."\\AxiomC{} "..modifier .. "\\UnaryInfC{\\( "..thispstring.." \\)}\n" elseif n == 1 then return buss_donode(upnodesegs[1], indent + 1) .. sp..modifier.."\\UnaryInfC{\\( "..thispstring.." \\)}\n" elseif n == 2 then return buss_donode(upnodesegs[1], indent + 1) .. buss_donode(upnodesegs[2], indent + 1) .. sp..modifier.."\\BinaryInfC{\\( "..thispstring.." \\)}\n" elseif n == 3 then return buss_donode(upnodesegs[1], indent + 1) .. buss_donode(upnodesegs[2], indent + 1) .. buss_donode(upnodesegs[3], indent + 1) .. sp..modifier.."\\TrinaryInfC{\\( "..thispstring.." \\)}\n" elseif n > 3 then return "\\AxiomC{!!!!(n>3)!!!!}\n" end else return sp.."\\AxiomC{\\( "..thispstring.." \\)}\n" end end -- «buss_process» (to ".buss_process") function buss_process(fname, filecontents) return process_stuff(fname, filecontents, function (seg) prepstrings_node(seg.dedroot) return format("\\defded{%s}{\n%s \\DisplayProof\n}\n", seg.dedname, buss_donode(seg.dedroot, 1)) end) end function demo () stuff = [[ *<->*\bij * %:*->*\to * - ee f g ======== a->b b<->c -----------A->B a->c ^d ]] print("The trivial traversal:") iprint_process(nil, stuff) print() print("The Tatsuta traversal:") print(tatsuta_process(nil, stuff)) print() print("The Buss traversal:") print(buss_process(nil, stuff)) print() end -- «top_level» (to ".top_level") -- (find-angg "LUA/inc.lua" "file_functions") -- function buss(fnamein, fnameout) writefile(fnameout, buss_process(fnamein)) end function tatsuta(fnamein, fnameout) writefile(fnameout, tatsuta_process(fnamein)) end if getn(arg) == 0 then demo() else -- print(tatsuta_process(arg[1])) dostring(arg[1]) end -- (find-fline "~/LATEX/tmp.dn") -- lua ~/LUA/dednat.lua -- fname = "/home/root/LATEX/tmp.dn" -- filecontents = readfile(fname) -- p(dednamesegs[1].dedroot) -- p(lines, "lines") -- p(repls, "repls") -- p(segments, "segments") -- (find-node "(lua)Patterns") -- (find-node "(lua)strfind") -- (find-node "(lua)foreachi") -- -- Local Variables: -- coding: no-conversion -- ee-anchor-format: "«%s»" -- ee-charset-indicator: "Ñ" -- ee-comment-format: "-- %s\n" -- End: