Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: -- http://anggtwu.net/LUA/ToTeX1.lua.html -- http://anggtwu.net/LUA/ToTeX1.lua -- (find-angg "LUA/ToTeX1.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- -- This file implements a way to converts ASTs to TeX code. -- It defines two classes: Subst, that is very low-level, and ToTeX, -- that is built on top to Subst; ToTeX overrides some of the methods -- in Subst a tricky way - using the function addoverrides, that is -- defined in another file. Each ToTeX object is the core of a -- "totexer"; each totexer is a way to convert ASTs to tex code. -- Totexers are defined at the end of this file. -- -- Introduction -- ============ -- The class Dang in Show2 has two ways of expanding substrings in -- <D>ouble <ang>le brackets: in -- -- Dang.replace "a<<2+3>>b<<:return 4+5>>" -- -- it treats the "2+3" as an "expression" and the "return 4+5" as -- "statements". For the details, see: -- -- (find-angg "LUA/Show2.lua") -- (find-angg "LUA/Show2.lua" "Dang-tests") -- -- The class Subst extends this idea with other kinds of -- substitutions. In -- -- Subst.replace "_<1>_<2+3>_<:return 4+5>_<aa>_" -- -- the "1" in <1> is expanded with expn, -- the "2+3" in <2+3> is expanded with expexpr, -- the ":return 2+3" in <:return 2+3> is expanded with expeval, and -- the "aa" in <aa> is expanded with expfield. -- -- In the class Subst all these methods are defined in a way that is -- suited for debugging; in the class ToTeX they are replaced by methods -- that are more complex - some are even recursive - and that are -- suited for generating tex code. -- -- Supersedes: -- (find-angg "LUA/Subst1.lua") -- Used by: -- (find-angg "LUA/ELpeg1.lua" "AST") -- -- (defun tt () (interactive) (find-angg "LUA/ToTeX1.lua")) -- (defun s1 () (interactive) (find-angg "LUA/Subst1.lua")) -- «.Subst» (to "Subst") -- «.Subst-tests» (to "Subst-tests") -- «.ToTeX» (to "ToTeX") -- «.ToTeX-tests» (to "ToTeX-tests") -- «.totexer» (to "totexer") -- «.totexer-tests» (to "totexer-tests") require "ELpeg1" -- (find-angg "LUA/ELpeg1.lua") require "Show2" -- (find-angg "LUA/Show2.lua") require "addoverrides1" -- (find-angg "LUA/addoverrides1.lua") L = Code.L -- (find-angg "LUA/Code.lua" "Code") -- ____ _ _ -- / ___| _ _| |__ ___| |_ -- \___ \| | | | '_ \/ __| __| -- ___) | |_| | |_) \__ \ |_ -- |____/ \__,_|_.__/|___/\__| -- -- (find-angg "LUA/lua50init.lua" "pformat" "myntos =") -- «Subst» (to ".Subst") Subst = Class { type = "Subst", replace = function (str,verbose) return Subst{}:replace(str, verbose) end, __tostring = function (su) return su:tostring() end, __index = { tostring = function (tt) return "(Dummy tostring)" end, -- nil_tos = function (su) return "(nil)" end, number_tos = function (su, n) return myntos(n) end, table_tos = function (su, tbl) return mytostring(tbl) end, tostring1 = function (su, o) if type(o) == "string" then return o end if type(o) == "nil" then return su:nil_tos() end if type(o) == "number" then return su:number_tos(o) end if type(o) == "table" then return su:table_tos(o) end return tostring(o) end, -- fields = {aa="AAA", bb="BBB"}, hasfield = function (su, s) return su.fields[s] end, expfield = function (su, s) return su.fields[s] end, expn = function (su, n) return format("(expn %d)", n) end, expexpr = function (su, code) return format("(expexpr %s)", code) end, expeval = function (su, code) return format("(expeval %s)", code) end, -- classify = function (su, s) if s:match("^[0-9]+$") then return "expn", s+0 end if s:match("^:") then return "expeval", s:sub(2) end if su:hasfield(s) then return "expfield", s end return "expexpr", s end, replace = function (su, str, verbose) local f = function (b) local s = b:sub(2,-2) local method,arg = su:classify(s) local out = su:tostring1(su[method](su,arg)) if verbose then PP(s, method, arg, out) end return out end return (str:gsub("%b<>", f)) end, }, } -- «Subst-tests» (to ".Subst-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "ToTeX1.lua" = Subst.replace("_<2+3>_<:return 4+5>_<aa>_") = Subst.replace("_<2+3>_<:return 4+5>_<aa>_", "verbose") s = Subst {} = s = s:tostring1("a") = s:tostring1(nil) = s:tostring1(true) = s:tostring1(1.23456) = s:tostring1({20,30}) --]] -- _____ _____ __ __ -- |_ _|_|_ _|__\ \/ / -- | |/ _ \| |/ _ \\ / -- | | (_) | | __// \ -- |_|\___/|_|\___/_/\_\ -- -- TODO: explain how I used expexpr and expeval to implement expn -- -- «ToTeX» (to ".ToTeX") ToTeX = Class { type = "ToTeX", from = function (tbl) return addoverrides(Subst(shallowcopy(tbl)), ToTeX.__index) end, __index = { witho = function (tt,o) tt=shallowcopy(tt); tt.o=o; return tt end, tostring = function (tt) return tt:tostring1(tt.o) end, expexpr = function (tt,code) return L("tt,o => "..code)(tt, tt.o) end, expeval = function (tt,code) L("tt,o => "..code)(tt, tt.o) end, -- -- Overrides for table_tos tag = function (tt) return tt.o[0] end, fmt = function (tt) return tt.fmts[tt:tag()] end, table_tos = function (tt) if not tt:tag() then return "[No tag]" end if not tt:fmt() then return "[No fmt: "..tt:tag().."]" end return tt:replace(tt:fmt()) end, -- -- Overrides for expn getn0 = function (tt, n) return tt.o[n] end, getn = function (tt, n) return tt:witho(tt.o[n]) end, expn = function (tt, n) return tostring(tt:getn(n)) end, -- show00 = function (tt,...) return tostring(a):show00(...) end, show0 = function (tt,...) return tostring(a):show0 (...) end, show = function (tt,...) return tostring(a):show (...) end, }, } -- «ToTeX-tests» (to ".ToTeX-tests") --[==[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "ToTeX1.lua" fmts["+"] = "<1> + <2>" fmts["*"] = "<1> \\cdot <2>" fmts["L"] = "\\leaf " tt0 = ToTeX.from {fmts=fmts} o3 = mkast("*", "a", 2.3456) o5 = mkast("+", mkast("*", "a", 2.3456), 99) tt3 = tt0:witho(o3) tt5 = tt0:witho(o5) = tt3 = tt5 = tt3:fmt() = tt3:getn(1) = tt3:getn(2) = tt3:getn(2).o = tt3:replace("_<2+3>_") = tt3:replace("_<2>_") -- err = tt3:replace("_<tt.o[1]>_") = tt3:replace("_<tt.o[2]>_") = tt3:replace("_<tt:getn(1)>_") = tt3:replace("_<tostring(tt:getn(1))>_") = tt3:replace("_<tostring(tt:getn(2))>_") = tt3:replace("_<tt:getn(2)>_") = tt3:replace("_<tt:getn(2)>_") = tt3:replace("_<tostring(tt)>_") = tt3:replace("_<tostring(tt:getn(1))>_") = tt3:replace("_<tostring(tt:getn(2))>_") = tt3:replace("_<rawtostring(tt)>_") = tt3:replace("_<:2+3>_") = tt3:replace("_<:2+3+>_") -- err = tt3:replace("_<:print(2+3)>_") gm = function (o) return getmetatable(o) end gmi = function (o) return getmetatable(o).__index end PPV(tt3) PPV(gm(tt3)) PPV(gmi(tt3)) = type(PrintFunction.tostring(print)) = print setmetatable(print, PrintFunction.fmetatable()) -- broken setmetatable({}, PrintFunction.fmetatable()) -- broken = tt3.expeval = prf(tt3.expeval) -- broken = tt3:expeval("print 'hello'") tt3:expeval("print(tt,o)") tt3:expeval("print(tt)") = tt3 = prf(gmi(tt3).__tostring) = prf(gm (tt3).__tostring) = prf( tt3 . tostring) = PPV(gmi(tt3)) = PPV(gmi(tt3)) PPV(gm(tt3)) = tt0:replace("foo", "verbose") = tt0:replace("foo <1>", "verbose") = tt0:witho(2) = tt0:witho(o3) = tt0:witho(o3):getn0(1) = tt0:witho(o3):getn (1) = tt0:witho(o3):getn0(2) = tt0:witho(o3):getn(2) = tt0:witho(2.3456) = tt0:witho({[0]="L"}) tt1 = tt0:witho(o3) = tt1 = tt1:getn0(1) = tt1:getn0(2) = tt1:getn(2) = tt1:expn(1) = tt1:expn(2) = tt0:witho(o3) tt1 = tt0:witho(o5) = tt1 = tt1:tostring() = tt1:replace "foo" = tt1:tostring() = tt1.o = tt1.fmts = tt1:tag() = tt1:fmt() keyss = function (T) local ks = sorted(keys(T), rawtostring_comp) return mapconcat(mytostring, ks, " ") end = keyss {20, 30, a=40} funs = VTable {} funs["sin"] = VTable {} = totex (o) = totex0 (o) = totex00(o) = totex00(o).o = totex00(o):tag() = totex00(o):fmt() = totex00(o):getn(1) = totex00(o):getn(1).o = totex00(o):getn(2) = totex00(o):getn(2).o = totex00(o):getn(2):fmt() = totex00(o):getn(2):getn(2) = totex00(o):getn(2):getn(2).o = totex00() = totex00():gsub("a<2+3>b") --]==] -- _ _ -- | |_ ___ | |_ _____ _____ _ __ -- | __/ _ \| __/ _ \ \/ / _ \ '__| -- | || (_) | || __/> < __/ | -- \__\___/ \__\___/_/\_\___|_| -- -- «totexer» (to ".totexer") -- A "totexer" is a function that converts ASTs to LaTeX code. The -- "default totexer" consists of five global variables below. -- TODO: write examples showing how to build several different totexers -- and how to make them all available in parallel. -- fmts = VTable {} funs = VTable {} totex00 = ToTeX.from {fmts=fmts, funs=funs} totex0 = function (o) return totex00:witho(o) end totex = function (o) return totex0(o):tostring() end -- Add to: (find-angg "LUA/ELpeg1.lua" "AST") -- Based on: (find-angg "LUA/Pict3.lua" "Points2-methods") -- (find-angg "LUA/Show2.lua" "StringShow") table.addentries(AST.__index, { show00 = function (a,...) return totex(a):show00(...) end, show0 = function (a,...) return totex(a):show0 (...) end, show = function (a,...) return totex(a):show (...) end, }) -- «totexer-tests» (to ".totexer-tests") --[[ * (show2-use "/tmp/") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "ToTeX1.lua" fmts["+"] = "<1> + <2>" fmts["*"] = "<1> \\cdot <2>" o5 = mkast("+", "a", mkast("*", 2.3456, 3.4567)) = otype(totex0(o5)) = otype(totex (o5)) = totex0(o5) = totex0(o5).o = totex (o5) = o5:show00 {em=1} = o5:show0 {em=1} = o5:show {em=1} * (etv) --]] -- -- (defun s1 () (interactive) (find-angg "LUA/Subst1.lua")) -- (defun s2 () (interactive) (find-angg "LUA/Subst2.lua")) -- Local Variables: -- coding: utf-8-unix -- End: