Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: -- http://anggtwu.net/LUA/Subst1.lua.html -- http://anggtwu.net/LUA/Subst1.lua -- (find-angg "LUA/Subst1.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- -- (defun s1 () (interactive) (find-angg "LUA/Subst1.lua")) -- (defun e1 () (interactive) (find-angg "LUA/ELpeg1.lua")) -- (defun i1 () (interactive) (find-angg "LUA/Indent1.lua")) -- «.Subst» (to "Subst") -- «.Subst-tests» (to "Subst-tests") -- «.totex» (to "totex") -- «.ToTeX-fakeclass» (to "ToTeX-fakeclass") -- «.totex-tests» (to "totex-tests") -- Superseded by: -- (find-angg "LUA/ToTeX1.lua") -- (find-angg "LUA/Indent1.lua" "string.indent") indent = indent or function (s) return s end string.indent = string.indent or function (s) return s end -- ____ _ _ -- / ___| _ _| |__ ___| |_ -- \___ \| | | | '_ \/ __| __| -- ___) | |_| | |_) \__ \ |_ -- |____/ \__,_|_.__/|___/\__| -- -- This is like the Dang class of tikz1.lua, -- (find-angg "LUA/tikz1.lua" "Dang") -- but with lots of configurable options. -- Subst has four kinds of expansions: in -- Subst({}):gsub "_<1>_<2+3>_<:return 4+5>_<aa>_<+6><-7><!>_" -- 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. -- The substrings "<+6>", "<-7>", "<!>" at the end above all fall in -- the "do not expand" category; they are left unchanged. This is for: -- (find-angg "LUA/Indent1.lua") -- Note that the original Dang class only supports exprs and evals. -- Also, the "tostring" method below has several configurable subcases. -- Usually when we define objects of the class Subst we override at least -- table_tos and expn. The overrides are done with addoverrides. -- See: (find-angg "LUA/lua50init.lua" "addoverrides") -- (to "totex") -- -- «Subst» (to ".Subst") Subst = Class { type = "Subst", __tostring = function (su) return su:tostring() end, __index = { -- 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, -- 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, tostring = function (su) return su:tostring1(su.o) 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, -- donotexpand = function (su, s) return s:match("^[-+!][0-9]*$") end, -- pat = "<(.-)>", -- gsub1 = function (su, s) if su:donotexpand(s) then return nil end if s:match("^[0-9]+$") then return su:expn(s+0) end if su:hasfield(s) then return su:expfield(s) end if s:match("^:") then return su:expeval(s:sub(2)) end if true then return su:expexpr(s) end end, gsub = function (su, fmt) local f = function (s) return su:tostring1(su:gsub1(s)) end return (fmt:gsub(su.pat, f)) end, -- with = function (su, o) su.o = o; return su end, addoverrides = function (su, O) return addoverrides(su, O) end, }, } -- «Subst-tests» (to ".Subst-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Subst1.lua" su = Subst {o={20,30}} = su su = Subst {} fmt = "field: <aa>\n" .. "expr: <2+3>\n" .. "eval: <:return 4+5>\n" .. "n: <1>" = su:gsub(fmt) = expr "2+3" = eval "return 2+3" su.expexpr = function (su, code) return expr(code) end su.expeval = function (su, code) return eval(code) end = su:expexpr "2+3" = su:expeval "return 2+3" = su:gsub(fmt) su = Subst {o={20,30}} = su:gsub(fmt) O = { expn = function (su, n) return "["..su.o[n].."]" end, } su:addoverrides(O) = su:gsub(fmt) --]] -- _ _ -- | |_ ___ | |_ _____ __ -- | __/ _ \| __/ _ \ \/ / -- | || (_) | || __/> < -- \__\___/ \__\___/_/\_\ -- -- Based on: (find-angg "LUA/ELpeg1.lua" "ToTeX") -- This is the basic way to convert ASTs to TeX code. -- Every time that totex00 is run it creates a new Subst object with: -- 1. overrides for three methods: table_tos, expn, expexpr -- 2. a few other methods: tag, fmt, getn, -- 3. a copy of the argument o. -- This new Subst object is recursive. In a case like this, -- o = mkast("*", 2, 3) -- fmts["*"] = "<1> \\cdot <2>" -- something like this will happen: -- totex(o) -- --> totex0(o) -- --> totex00(o):tostring() -- --> totex00(o):tostring1(o) -- --> totex00(o):table_tos(o) -- --> totex00(o):gsub("<1> \\cdot <2>") -- --> totex00(o):expn(1) -- --> totex00(o):getn(1) -- --> totex00(o[1]) -- -- Note that this recursion scheme uses several globals: totex, -- totex0, totex00, fmts, and sometimes funs. I've tried to write -- alternatives to this with no globals, but in all cases their code -- ended up very intrincate... in this version with globals at least -- the code is quite simple. -- -- To use indent, override the definition of totex below with: -- totex = function (o) return totex0 (o):indent() end -- See: (find-angg "LUA/Indent1.lua" "Indent") -- -- «totex» (to ".totex") --totex = function (o) return totex0(o) end totex = function (o) return tostring(totex0(o)):indent() end totex0 = function (o) return totex00(o) end totex00 = function (o) return ToTeX.fromo(o) end -- «ToTeX-fakeclass» (to ".ToTeX-fakeclass") -- This is a fake class in the sense that its creators, -- ToTeX.from(A) and ToTeX.fromo(o), return objects of the class -- Subst, but with some methods overridden. Also, ToTeX.__index -- is not a list of methods but a list of overrides. ToTeX = Class { type = "ToTeX", from = function (A) return Subst(copy(A)):addoverrides(ToTeX.__index) end, fromo = function (o) return ToTeX.from({o=o}) end, __index = { -- -- Override table_tos tag = function (su) return su.o[0] end, fmt = function (su) return fmts[su:tag()] end, table_tos = function (su) if not su:tag() then return "[No tag]" end if not su:fmt() then return "[No fmt: "..su:tag().."]" end return su:gsub(su:fmt()) end, -- -- Override expn getn = function (su, n) return totex00(su.o[n]) end, expn = function (su, n) return su:getn(n):tostring() end, -- -- For debugging: expexpr = function (su, code) return L("su,o => "..code)(su, su.o) end, }, } -- «totex-tests» (to ".totex-tests") --[==[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Subst1.lua" dofile "ELpeg1.lua" -- for mkast s = Subst {o={20,30}} = s t = ToTeX.fromo({20,30}) = t = otype(s) --> Subst = otype(t) --> Subst = s = t fmts = VTable {} fmts["+"] = "<1> + <2>" fmts["*"] = "<1> \\cdot <2>" funs = VTable {} funs["sin"] = VTable {} o = mkast("+", "a", mkast("*", 2, 3.4567)) = o = 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") --]==] -- Local Variables: -- coding: utf-8-unix -- End: