Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
--   http://anggtwu.net/LUA/Ast2.lua.html
--   http://anggtwu.net/LUA/Ast2.lua
--          (find-angg "LUA/Ast2.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- (defun a  () (interactive) (find-angg "LUA/Ast1.lua"))
-- (defun a1 () (interactive) (find-angg "LUA/Ast1.lua"))
-- (defun a2 () (interactive) (find-angg "LUA/Ast2.lua"))
-- (defun a3 () (interactive) (find-angg "LUA/Ast3.lua"))
-- (defun a4 () (interactive) (find-angg "LUA/Ast4.lua"))
-- (defun c3 () (interactive) (find-angg "LUA/Caepro3.lua"))
-- (defun c4 () (interactive) (find-angg "LUA/Caepro4.lua"))
-- (defun g2 () (interactive) (find-angg "LUA/Gram2.lua"))
-- (defun g3 () (interactive) (find-angg "LUA/Gram3.lua"))

-- «.AST»		(to "AST")
-- «.AST-tests»		(to "AST-tests")
-- «.E»			(to "E")
-- «.E-tests»		(to "E-tests")
-- «.ToText»		(to "ToText")
-- «.ToText-tests»	(to "ToText-tests")


require "Gram2"   -- (find-angg "LUA/Gram2.lua")
lpeg.ptmatch = function (pat, str) PP(pat:Ct():match(str)) end
L = Code.L



--     _    ____ _____ 
--    / \  / ___|_   _|
--   / _ \ \___ \ | |  
--  / ___ \ ___) || |  
-- /_/   \_\____/ |_|  
--                     
-- «AST»  (to ".AST")
-- Based on: (find-angg "LUA/Gram2.lua" "AST")
--

AST = Class {
  type = "AST",
  alttags = {},			-- Override this!
  ify  = function (o)
      if type(o) == "table" and o[0] and AST.alttags[o[0]] then
        o[0] = AST.alttags[o[0]]
      end
      return AST(o)
    end,
  __tostring = function (o) return tostring(SynTree.from(o)) end,
  __index = {
  },
}

calceasy_alttags = function ()
    AST.alttags = {eq="=", plus="+", minus="-", Mul="*",
                   div="/", Div="//", pow="^",
                   paren="()", plic="'"}
  end

-- «AST-tests»  (to ".AST-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Ast2.lua"
= AST.ify {[0]="Mul", 2, 3}
calceasy_alttags()
= AST.ify {[0]="Mul", 2, 3}

--]]



--  _____ 
-- | ____|
-- |  _|  
-- | |___ 
-- |_____|
--        
-- «E»  (to ".E")

entries = {}
E = setmetatable({}, {
    __call     = function (_,name) return entries[name] end,
    __index    = function (_,name) return entries[name] end,
    __newindex = function (_,name,o) entries[name] = o end,
  })

calceasy_E = function ()
    fun   = function (name) return AST {[0]="fun", name} end
    var   = function (name) return AST {[0]="var", name} end
    num   = function (str)  return AST {[0]="num", str}  end
    bin   = function (a, op, b) return AST {[0]=op, a, b} end
    unary = function    (op, a) return AST {[0]=op, a}    end
    paren = function (a)    return unary("()", a) end
    plic  = function (a)    return unary("'", a) end
    ap    = function (a, b) return bin(a, "ap", b) end
    --
    eq    = function (a, b) return bin(a, "=", b) end
    plus  = function (a, b) return bin(a, "+", b) end
    minus = function (a, b) return bin(a, "-", b) end
    mul   = function (a, b) return bin(a, "mul", b) end
    Mul   = function (a, b) return bin(a, "*",   b) end
    div   = function (a, b) return bin(a, "/",   b) end
    Div   = function (a, b) return bin(a, "//",  b) end
    pow   = function (a, b) return bin(a, "^",   b) end
    --
    E[    "x"                ] = var"x"
    E[ "ln x"                ] = ap(fun"ln", E"x")
    E["(ln x)"               ] = paren(E"ln x")
    E[       "3"             ] = num("3")
    E["(ln x)^3"             ] = pow(E"(ln x)", E"3")
    E["(ln x)^3"             ] = pow(E"(ln x)", E"3")
    E[           "5"         ] = num("5")
    E[                "sin x"] = ap(fun"sin", E"x")
    E[            "5 + sin x"] = plus(E"5", E"sin x")
    E["(ln x)^3 // 5 + sin x"] = Div(E"(ln x)^3", E"5 + sin x")
    --
    E[ "f"                                 ] = fun"f"
    E[  "(x)"                              ] = paren(E"x")
    E[ "f(x)"                              ] = ap(E"f", E"(x)")
    E[     "g"                             ] = fun"g"
    E[     "g(x)"                          ] = ap(E"g", E"(x)")
    E[ "f(x)g(x)"                          ] = mul(E"f(x)", E"g(x)")
    E["(f(x)g(x))"                         ] = paren(E"f(x)g(x)")
    E["(f(x)g(x))'"                        ] = plic(E"(f(x)g(x))")
    E[              "f'"                   ] = fun"f'"
    E[              "f'(x)"                ] = ap(E"f'", E"(x)")
    E[              "f'(x)g(x)"            ] = mul(E"f'(x)", E"g(x)")
    E[                              "g'"   ] = fun"g'"
    E[                              "g'(x)"] = ap(E"g'", E"(x)")
    E[                          "f(x)g'(x)"] = mul(E"f(x)", E"g'(x)")
    E[              "f'(x)g(x) + f(x)g'(x)"] = plus(E"f'(x)g(x)", E"f(x)g'(x)")
    E["(f(x)g(x))' = f'(x)g(x) + f(x)g'(x)"] = eq(E"(f(x)g(x))'", E"f'(x)g(x) + f(x)g'(x)")
  end

-- «E-tests»  (to ".E-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Ast2.lua"
calceasy_alttags()   -- irrelevant here
calceasy_E()
= E["(f(x)g(x))' = f'(x)g(x) + f(x)g'(x)"]
= E["(ln x)^3 // 5 + sin x"]

--]]



-- (find-angg "LUA/Gram3.lua" "expr")

foldplic = function (A)
    local o = A[1]
    for i=2,#A do o = plic(o) end
    return o
  end

calceasy_grammar = function ()
    gr,V,VA,VE,PE = Gram.new()
    grcm = function (...) print(gr:cm(...)) end
    _ = S(" ")^0
    --
    VA.num   = Cs(R"09"^1)
    VA.var   = anyof "x"
    VA.fun   = anyof "f' f g' g ln sin"
    VA.ap    = V.fun *_* V.exprbasic
    --
    VA.paren = "("*_* V.expr *_*")"
    V.exprbasic = V.paren + V.ap + V.num + V.fun + V.var
    V.exprplic  = assocpost(V.exprbasic, Cs"'"     )
    V.exprpow   = assocr(V.exprplic,     Cs"^"     )
    V.exprmul   = assocl(V.exprpow,      Cc"mul"   )
    V.exprMul   = assocl(V.exprmul,      Cs"*"     )
    V.exprplus  = assocl(V.exprMul,      Cs"+"     )
    V.exprDiv   = assocl(V.exprplus,     Cs"//"    )
    V.expreq    = assocl(V.exprDiv,      Cs"="     )
    V.expr      = V.expreq
    --
    V.exprplic  = Ct(V.exprbasic * (_*Cs"'")^0) / foldplic
  end

--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Ast2.lua"
calceasy_grammar()
calceasy_alttags()   -- optional
calceasy_E()         -- needed for plic
-- alttags = {}
= grcm("num", "234")
= grcm("expr", "234")
= grcm("expr", "f'")
= grcm("expr", "f'(x)")
= grcm("expr", "f'(x)")
= grcm("expr", "f'(x) + 5")
= grcm("expr", "f'(x) + 5^6 // 20")
= grcm("expr", "(ln x)^3 // 5 + sin x")
= grcm("expr", "(f(x)g(x))' = f'(x)g(x) + f(x)g'(x)")

= E["(f(x)g(x))' = f'(x)g(x) + f(x)g'(x)"]
= E["(ln x)^3 // 5 + sin x"]

--]]



--  _____   _____         _   
-- |_   _|_|_   _|____  _| |_ 
--   | |/ _ \| |/ _ \ \/ / __|
--   | | (_) | |  __/>  <| |_ 
--   |_|\___/|_|\___/_/\_\\__|
--                            
-- «ToText»  (to ".ToText")

ToText0 = Class {
  type  = "ToText0",
  __index = {
    with = function (tt0,o) return ToText {tt0=tt0, o=o} end,
  },
}

ToText = Class {
  type = "ToText",
  __tostring = function (tt) return tostring(tt.o) end,
  __index = {
    from = function (tt, o) return ToText {tt0=tt.tt0, o=o} end,
    atn  = function (tt, n) return tt:from(tt.o[n+0]) end,
    tag  = function (tt) return tt.o[0] end,
    fmt  = function (tt) return tt.tt0.fmts[tt:tag()] end,
    --
    eval = function (tt,fmt,a,b,c)
        return L("tt,tt0,o,a,b,c => "..fmt)(tt, tt.tt0, tt.o, a, b, c)
      end,
    subst = function (tt, fmt)
        local f = function (s)
            if s:match"^[0-9]+$" then return tt:atn(s):totext() end
            return tt:eval(s)
          end
        return (fmt:gsub("<(.-)>", f))
      end,
    totext = function (tt)
        if type(tt.o) == "string" then return tt.o end
        if type(tt.o) == "number" then return tostring(tt.o) end
        if not tt:tag() then return "[No tag]" end
        if not tt:fmt() then return "[No fmt: "..tt:tag().."]" end
        return tt:asttotext(tt.o)
      end,
    asttotext = function (tt) return tt:subst(tt:fmt()) end,
  },
}

totex00 = ToText0 {fmts={}}    -- Override this!
totex0  = function (o) return totex00:with(o)          end
totex   = function (o) return totex00:with(o):totext() end
AST.__index.totex0 = function (o) return totex0(o) end
AST.__index.totex  = function (o) return totex (o) end

-- «ToText-tests»  (to ".ToText-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Ast2.lua"
calceasy_grammar()
calceasy_alttags()   -- optional
calceasy_E()         -- needed for plic
oo = E"f(x)"
= oo
= totex(oo)
= oo:totex()
= oo:atn(2):totex()

= calceasy0:with(o)
= calceasy0:with(nil)
PPPV(calceasy0:with(o))
PPPV(calceasy0:with(nil))
PPPV(calceasy0:with(42))
PPPV(calceasy0:with(oo))
ooo = calceasy0:with(oo)
= ooo
= ooo:totext()
  ooo:totext()

= E"f(x)":totex()

--]==]


calceasy_totex = function ()
    calceasy00 = ToText0 {
      fmts = {
        ["()"] = "(<1>)",
        ["//"] = "\\frac{<1>}{<2>}",
        ["^"]  = "{<1>}^{<2>}",
        ["+"]  = "<1> + <2>",
        ["="]  = "<1> = <2>",
        ap  = "<1> <2>",
        mul = "<1> <2>",
        Mul = "<1> \\cdot <2>",
        ["'"] = "<1>'",
        --
        num = "<1>",
        var = "<1>",
        fun = "<tt0.funs[o[1]] or o[1]>",
      },
      funs = {
        ln  = "\\ln ",
        sin = "\\sin ",
      },
    }
    totex00 = calceasy00
  end




--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Ast2.lua"
calceasy_grammar()
calceasy_alttags()   -- optional
calceasy_E()         -- needed for plic

totex = ToText0 {
  fmts = VTable {
    num = "<1>",
    var = "<1>",
    fun = "<tt.funs[o[1]] or o[1]>",
    fun = "<1>",
    ap = "<1> <2>",
    ["()"] = "(<1>)",
  },
  funs = {
  },
}
= totex:with(E"f(x)")
= totex:with(E"f(x)").o
= totex:with(E"f(x)").o.o
  totex:with(E"f(x)"):eval"print'hello'"
  totex:with(E"f(x)"):eval"print(o)"
= totex:with(E"f(x)"):eval"o"
= totex:with(E"f(x)"):eval"o[0]"
= totex:with(E"f(x)"):eval"tt0.fmts"
= totex:with(E"f(x)"):eval"tt:fmt()"
= totex:with(E"f(x)"):eval"tt.o"
= totex:with(E"f(x)"):eval"tt.o[0]"
= totex:with(E"f(x)"):eval"tt:fmt()"
= totex:with(E"f(x)"):eval"tt:atn(1)"
= totex:with(E"f(x)"):totext()


= totex:with(E"f(x)"):eval"tt0.fmts"

 = ToText {
    fmts = 
  }

= E"f(x)"
= E"f(x)"[1]

Slogans

        ["()"] = "(<1>)",
        ["//"] = "\\frac{<1>}{<2>}",
        ["^"]  = "{<1>}^{<2>}",
        ["+"]  = "<1> + <2>",
        ["="]  = "<1> = <2>",
        ap  = "<1> <2>",
        mul = "<1> <2>",
        Mul = "<1> \\cdot <2>",
        ["'"] = "<1>'",
        --
        num = "<1>",
        var = "<1>",
        fun = "<tt.funs[o[1]] or o[1]>",
      },
    --

--]==]




-- «Linearize-tests»  (to ".Linearize-tests")





-- Local Variables:
-- coding:  utf-8-unix
-- End: