Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- Warning: this file uses "regmatch", defined in my (edrx's) modified -- version of rtt's regexp libs... -- (find-angg "lua-4.0/src/libdllua/lrexlib-new.c") -- (find-angg "lua-4.0/src/libdllua/lrexlib-new.c" "regmatch") -- (find-angg "LATEX/Makefile" "dednat.lua") -- (find-angg "LATEX/Makefile" "dn_to_dnt") regcomp = regex treestuff = {} -- «.store_macro» (to "store_macro") -- «.substitute_str» (to "substitute_str") -- «.hsplit» (to "hsplit") -- «.nodes_intersecting» (to "nodes_intersecting") -- «.hsplit_do_node» (to "hsplit_do_node") -- «.preprocess_tree_node» (to "preprocess_tree_node") -- «.preprocess_tree_rule» (to "preprocess_tree_rule") -- «.iprint_do_node» (to "iprint_do_node") -- «.iprint_do_tree» (to "iprint_do_tree") -- «.generate_tree_TeX_code» (to "generate_tree_TeX_code") -- «.tatsuta_do_node» (to "tatsuta_do_node") -- «.tatsuta_do_tree» (to "tatsuta_do_tree") -- «.buss_do_node» (to "buss_do_node") -- «.buss_do_node» (to "buss_do_node") -- «.tatsuta» (to "tatsuta") -- «.buss» (to "buss") -- «.getline» (to "getline") -- «.preprocess» (to "preprocess") -- «.preprocess_on» (to "preprocess_on") -- «.preprocess_off» (to "preprocess_off") -- «.process_macroline» (to "process_macroline") -- «.process_treeline» (to "process_treeline") -- «.process_lualine» (to "process_lualine") -- «.process_otherline» (to "process_otherline") -- «.process_line» (to "process_line") -- «.main_loop» (to "main_loop") --# How this program works (from the programmer's point of view): --# It has a "main_loop" function that gets lines and processes them. --# If a line is of the form "%:*...*...*" process it with "store_macro"; --# if not, and if it is of the form "%:...", process it as a part of --# a tree diagram, with hsplit. --# Hsplit splits the "..." in "%:..." in words, and processes each --# of them as a "node"; for each "%:..." line, say the line linenum --# (where we start counting from 1), treestuff[linenum] is an array --# containing all the nodes from line linenum; for non-"%:..." --# lines treestuff[linenum] is nil. --# The processing of each node is done by the function "f_store", --# that is given as an argument to hsplit; f_store is usually --# hsplit_do_node. This processing includes adding the node (as a --# table with fields {str, p1, p2, linenum} -- other fields may be --# added later) to treestuff[linenum]. --# If a node is of the form "^..." then it is a label with the --# name of a tree, and processing it is a complex task. We --# describe the other case first. --# If a node (say, "thisnode") is not the name of a tree then --# just build (with "nodes_intersecting") the array "aboves" of --# all the nodes in the preceding line that intersect thisnode, --# i.e., an array with the nodes that have some column in common --# with thisnode. If the array "aboves" turns out to be non-empty --# then set thisnode.aboves = aboves. Note that we are not yet --# doing anything special to distinguish nodes that are real tree --# nodes and nodes that are rules ("----..." or "====..."). --# Each "^..." node points to another node, two lines above, that --# is the root of a tree. Issue an error if this tree-root node --# does not exist, and if it exists start the preprocessing of --# the tree -- note that now we will be able to determine which --# nodes are "tree node" nodes and which are "rule" nodes. --# Process these "tree node/rule" nodes recursively, preparing a --# field node.TeXstr for each of them; for "tree node" nodes this --# field is the result of running substitute_str on node.str, but --# for rule nodes node.str is split in a "rule" part (a sequence --# of "-"s or a sequence of "="s -- the field node.rulechar says --# which char) and a "right string" part, node.rightstr, --# containing the rest; for rule nodes node.TeXstr is the result --# of substitute_str(node.rightstr). --# If a tree node has a rule above it then it will have a --# "node.uprule" field pointing to the node of the rule. A rule --# node don't have any special field to point to the tree nodes --# above it; this data is in the field "node.aboves" (that for --# every node is always either nil or a non-empty array). --# The "^..." nodes get a "treelabel" field, containing the "..." --# string; after the preprocessing is done the function --# generate_tree_TeX_code is called, with the "^..." node as its --# only parameter. I haven't written generate_tree_TeX_code yet. --### --# --# Functions to take care of macro substitution. --# Store_macro will use the fields of a "%:*...*...*" line to update --# the array of macros; substitute_str will apply all the --# substitutions in the "macros" array on str. --# --### macros = {} -- «store_macro» (to ".store_macro") store_macro = function(fromstr, tostr) local n = macros[fromstr] -- macros may be redefined local qfromstr = gsub(fromstr, "([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1") local fun = function (str) return gsub(str, %qfromstr, %tostr) end if n then macros[n].tostr = tostr macros[n].fun = fun else tinsert(macros, {fromstr=fromstr, tostr=tostr, fun=fun}) macros[fromstr] = getn(macros) end end -- «substitute_str» (to ".substitute_str") substitute_str = function(str) if str=="" then return str end -- trivial optimization local i for i=1,getn(macros) do str = macros[i].fun(str) end return str end --### --# --# Functions to process "%:..." lines. --# The outside will call hsplit for each "%:..." line; the functions --# in this block will call generate_tree_TeX_code for each "^..." --# node, after all the required preprocessing having been done. --# --### -- «hsplit» (to ".hsplit") hsplit_re = regcomp("[^ ]+") hsplit = function(linestr, arr, f_store) local pos, offset, newpos, str = 0 f_store = f_store or hsplit_do_node while 1 do offset, str = regmatch(hsplit_re, linestr, pos) if offset==nil then return arr end f_store(arr, str, pos+offset, pos+offset+strlen(str)) pos = pos+offset+strlen(str) end end -- «nodes_intersecting» (to ".nodes_intersecting") -- Return an array with the nodes of "ts" (i.e., ts[1], ts[2], etc) -- that "intersect" the range (p1,p2). The array may be ={}. function nodes_intersecting(p1, p2, ts) local arr, i, node = {} if ts then for i=1,getn(ts) do node = ts[i] if not (node.p2<=p1 or p2<=node.p1) then tinsert(arr, node) end end end return arr end -- «hsplit_do_node» (to ".hsplit_do_node") treelabel_re = regcomp("^\\^(.+)") hsplit_do_node = function(arr, str, p1, p2) local linenum, thisnode, pos, m0, treelabel, treeroot, aboves linenum = arr.linenum thisnode = {str=str, p1=p1, p2=p2, linenum=linenum} tinsert(arr, thisnode) pos, m0, treelabel = regmatch(treelabel_re, str) if pos then thisnode.treelabel = treelabel treeroot = nodes_intersecting(p1, p2, treestuff[linenum - 2])[1] if not treeroot then printf("Tree name points to no root: %q, line %d\n", str, linenum) exit(1) end thisnode.treeroot = treeroot preprocess_tree_node(treeroot) generate_tree_TeX_code(thisnode) else aboves = nodes_intersecting(p1, p2, treestuff[linenum - 1]) if getn(aboves)>0 then thisnode.aboves = aboves end end end -- «preprocess_tree_node» (to ".preprocess_tree_node") preprocess_tree_node = function(node) node.TeXstr = substitute_str(node.str) if node.aboves then node.uprule = node.aboves[1] preprocess_tree_rule(node.uprule) end end -- «preprocess_tree_rule» (to ".preprocess_tree_rule") preprocess_tree_rule_re = regcomp("^(-+|=+)(.*)") preprocess_tree_rule = function(node) local pos, m0, rule, rightstr = regmatch(preprocess_tree_rule_re, node.str) if not pos then printf("Rule has no bar: %q, line %d\n", node.str, node.linenum) exit(1) end node.rulechar = strsub(rule, 1, 1) node.TeXstr = substitute_str(rightstr) if node.aboves then foreachi(node.aboves, function(i,node) preprocess_tree_node(node) end) end end --### --# --# Emitting trees (in TeX or in some debugging form) --# --### function spaces(n) return strrep(" ", n) end -- «iprint_do_node» (to ".iprint_do_node") function iprint_donode(indent, node) local uprule, i, upnode uprule = node.uprule if uprule then print(spaces(indent+2)..strrep(uprule.rulechar,4).." "..uprule.TeXstr) if uprule.aboves then for i=1,getn(uprule.aboves) do iprint_donode(indent+4, uprule.aboves[i]) end end end end -- «iprint_do_tree» (to ".iprint_do_tree") function iprint_do_tree(treelabelnode) print(treelabelnode.str) iprint_donode(2, treelabelnode.treeroot) return "" end TeX_trees = {} default_do_tree = iprint_do_tree -- «generate_tree_TeX_code» (to ".generate_tree_TeX_code") generate_tree_TeX_code = function(treelabelnode) tinsert(TeX_trees, default_do_tree(treelabelnode)) end --### --# --# Functions to generate TeX code for already-preprocessed trees --# --### mathstrut = "\\mathstrut " -- «tatsuta_do_node» (to ".tatsuta_do_node") -- (find-es "tex" "tatsutaproof") function tatsuta_do_node(indent, node) local uprule = node.uprule if uprule then local modifier = "" if uprule.rulechar == "=" then modifier = "=" end if uprule.TeXstr ~= "" then modifier = modifier .. "[{" .. uprule.TeXstr .. "}]" end local upnodes = uprule.aboves or {} local arr = {} local i for i=1,getn(upnodes) do tinsert(arr, "\n"..tatsuta_do_node(indent + 1, upnodes[i]).." ") end return format("%s\\infer%s{ %s %s }{%s}", spaces(indent), modifier, mathstrut, node.TeXstr, join(arr, "&")) else return spaces(indent) .. mathstrut .. node.TeXstr end end -- «tatsuta_do_tree» (to ".tatsuta_do_tree") function tatsuta_do_tree(treelabelnode) return format("\\defded{%s}{\n%s }\n", treelabelnode.treelabel, tatsuta_do_node(1, treelabelnode.treeroot)) end -- «buss_do_node» (to ".buss_do_node") function buss_do_node(indent, node) local uprule = node.uprule local sp, sp1 = spaces(indent), spaces(indent + 1) local thispstring = mathstrut .. node.TeXstr if uprule then local modifier = "" if uprule.rulechar == "=" then modifier = "\\doubleLine " end if uprule.TeXstr ~= "" then modifier = modifier.."\\RightLabel{\\( "..uprule.TeXstr.." \\)} " end local upnodes = uprule.aboves or {} local n = getn(upnodes) local upstr = "" local i if n == 0 then return sp.."\\AxiomC{} "..modifier .. "\\UnaryInfC{\\( "..thispstring.." \\)}\n" elseif n == 1 then return buss_do_node(indent + 1, upnodes[1]) .. sp..modifier.."\\UnaryInfC{\\( "..thispstring.." \\)}\n" elseif n == 2 then return buss_do_node(indent + 1, upnodes[1]) .. buss_do_node(indent + 1, upnodes[2]) .. sp..modifier.."\\BinaryInfC{\\( "..thispstring.." \\)}\n" elseif n == 3 then return buss_do_node(indent + 1, upnodes[1]) .. buss_do_node(indent + 1, upnodes[2]) .. buss_do_node(indent + 1, upnodes[3]) .. sp..modifier.."\\TrinaryInfC{\\( "..thispstring.." \\)}\n" elseif n > 3 then return "\\AxiomC{!!!!(n>3)!!!!}\n" end else return sp.."\\AxiomC{\\( "..thispstring.." \\)}\n" end end -- «buss_do_node» (to ".buss_do_node") function buss_do_tree(treelabelnode) printf("\\defded{%s}{\n%s \\DisplayProof\n}\n", treelabelnode.treelabel, buss_do_node(1, treelabelnode.treeroot)) end --### --# --# Functions to set the environment to use a certain TeX output --# function (tatsuta_do_tree or buss_do_tree), a certain input file --# and a certain output file --# --### -- «tatsuta» (to ".tatsuta") tatsuta = function(srcfname, destfname, pp_destfname) default_do_tree = tatsuta_do_tree file_as_string = readfile(srcfname) TeX_trees.destfname = destfname pped_lines.destfname = pp_destfname end -- «buss» (to ".buss") buss = function(srcfname, destfname, pp_destfname) default_do_tree = buss_do_tree file_as_string = readfile(srcfname) TeX_trees.destfname = destfname pped_lines.destfname = pp_destfname end --### --# --# The main loop --# --### file_as_string = "" -- we set it later file_pos = 0 file_linebeg = 0 linenum = 0 lines = {} -- «getline» (to ".getline") getline_re = regex("^([^\n]*)(\n?)") getline = function() file_linebeg = file_pos local p, all, bulk, nl = regmatch(getline_re, file_as_string, file_pos) if all=="" then return nil end linenum = linenum + 1 file_pos = file_pos + strlen(all) tinsert(lines, bulk) return bulk end -- «preprocess» (to ".preprocess") -- «preprocess_on» (to ".preprocess_on") -- «preprocess_off» (to ".preprocess_off") pped_lines = {} -- array of preprocessed lines (opt field: destfile) preprocess_subst = function(linestr) tinsert(pped_lines, substitute_str(linestr)) end preprocess_nochange = function(linestr) tinsert(pped_lines, linestr) end preprocess = preprocess_nochange preprocess_on = function() preprocess = preprocess_subst end preprocess_off = function() preprocess = preprocess_nochange end -- «process_macroline» (to ".process_macroline") macroline_re = regcomp("^%:*([^*]+)*([^*]*)*(.*)") process_macroline = function(linestr) local p, all, fromstr, tostr, rest = regmatch(macroline_re, linestr) if p then store_macro(fromstr, tostr) return "processed" end end -- (eev "cd ~/LATEX/; touch tmp.tex; make tmp.auto.dnt") -- (eev "cd ~/LATEX/; mylua -f ~/dednat/dednat2.lua 'tatsuta(arg[2],arg[3])' tmp.tex tmp.dnt") -- «process_treeline» (to ".process_treeline") treeline_re = regcomp("^%:(.*)") process_treeline = function(linestr) local pos, all, bulk = regmatch(treeline_re, linestr) if pos then treestuff[linenum] = {linenum=linenum} hsplit(untabify_line(" "..bulk), treestuff[linenum]) return "processed" end end -- «process_lualine» (to ".process_lualine") bigluacode = "" lualine_re = regcomp("^(.*?)%lua([^ \t]*)(.*)") process_lualine = function(linestr) local pos, all, pre, special, luacode = regmatch(lualine_re, linestr) if pos then if special=="/" then -- allow glueing lines before running the code bigluacode = bigluacode.."\n"..luacode else bigluacode = luacode dostring(bigluacode) end return "processed" end end -- «process_otherline» (to ".process_otherline") process_otherline = function(linestr) preprocess(linestr) return "processed" end -- «process_line» (to ".process_line") process_line = function(linestr) local dummy = process_macroline(linestr) or process_treeline(linestr) or process_lualine(linestr) or process_otherline(linestr) end -- «main_loop» (to ".main_loop") main_loop = function() local linestr while 1 do linestr = getline() if linestr==nil then break end process_line(linestr) end end --### --# --# a test --# --### file_as_string = [[ %:*aa*<a>* %: %: == %: aa bb %: ------aa %: cc %: %: ^test ]] if arg then dostring(arg[1]) end -- (eev "cd ~/LUA/; mylua dednat2.lua") -- (eev "mylua -f ~/dednat/dednat2.lua 'tatsuta(arg[2],arg[3])' ~/LATEX/tmp.tex /tmp/o") main_loop() if TeX_trees.destfname then writefile(TeX_trees.destfname, join(TeX_trees)) end if pped_lines.destfname then writefile(pped_lines.destfname, join(pped_lines, "\n")) end print("finished.")