Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
--   http://angg.twu.net/LUA/Parenthesize2.lua.html
--   http://angg.twu.net/LUA/Parenthesize2.lua
--           (find-angg "LUA/Parenthesize2.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- (defun p  () (interactive) (find-angg "LUA/PrecParser1.lua"))
-- (defun o  () (interactive) (find-angg "LUA/Parenthesize2.lua"))
-- (defun oo () (interactive) (find-angg "LUA/Parenthesize1.lua"))

require "Show1"         -- (find-angg "LUA/Show1.lua" "string.show")
require "Tree1"         -- (find-angg "LUA/Tree1.lua")
require "GetInfo2"      -- (find-angg "LUA/GetInfo2.lua")

OpInfo = Class {
  type = "OpInfo",
  new  = function () return OpInfo {ops={}} end,
  __tostring = function (opi) return mytostringv(opi.ops) end,
  __index = {
    addinfix = function (opi, lbp, rbp, names)
        for _,name in ipairs(split(names)) do
          opi.ops[name] = HTable {fixity="infix", name=name, lbp=lbp, rbp=rbp}
        end
        return opi
      end,
    addprefix = function (opi, rbp, names)
        for _,name in ipairs(split(names)) do
          opi.ops[name] = HTable {fixity="prefix", name=name, rbp=rbp}
        end
        return opi
      end,
    addpostfix = function (opi, lbp, names)
        for _,name in ipairs(split(names)) do
          opi.ops[name] = HTable {fixity="postfix", name=name, lbp=lbp}
        end
        return opi
      end,
    norm = function (opi, x) return x or HTable {} end,
    opinfo = function (opi, op) return opi:norm(op and opi.ops[op]) end,
    oinfo  = function (opi, o) return opi:norm(type(o) == "table" and opi:opinfo(o[0])) end,
    --
    opbin     = function (opi, op) return opi:opinfo(op).fixity == "infix" end,
    opinfix   = function (opi, op) return opi:opinfo(op).fixity == "infix" end,
    opprefix  = function (opi, op) return opi:opinfo(op).fixity == "prefix" end,
    oppostfix = function (opi, op) return opi:opinfo(op).fixity == "postfix" end,
    oplbp     = function (opi, op) return opi:opinfo(op).lbp end,
    oprbp     = function (opi, op) return opi:opinfo(op).rbp end,
    --
    obin     = function (opi, o) return opi:oinfo(o).fixity == "infix" end,
    oinfix   = function (opi, o) return opi:oinfo(o).fixity == "infix" end,
    oprefix  = function (opi, o) return opi:oinfo(o).fixity == "prefix" end,
    opostfix = function (opi, o) return opi:oinfo(o).fixity == "postfix" end,
    olbp     = function (opi, o) return opi:oinfo(o).lbp end,
    orbp     = function (opi, o) return opi:oinfo(o).rbp end,
    parenp   = function (opi, o, i)
        if i==1 then
          if     opi:obin(o)     then return (opi:orbp(o[1]) or 999) < opi:olbp(o)
          elseif opi:opostfix(o) then return (opi:orbp(o[1]) or 999) < opi:olbp(o)
          elseif opi:oprefix(o)  then return (opi:olbp(o[1]) or 999) < opi:orbp(o)
          else error("Bad paren1")
          end
        elseif i==2 then
          if opi:obin(o) then return (opi:olbp(o[2]) or 999) < opi:orbp(o)
          else error("Bad paren2")
          end
        else error("Bad i for parenp")
        end
      end,
    text = function (opi, o)
        if type(o) ~= "table" then return mytostring(o) end
        local ptext = function (i)  
            local fmt = opi:parenp(o, i) and "(%s)" or "%s"
            return format(fmt, opi:text(o[i]))
          end
        if     opi:obin(o)
        then   return format("%s %s %s", ptext(1), o[0], ptext(2))
        elseif opi:opostfix(o)
        then   return format("%s %s", ptext(1), o[0])
        elseif opi:oprefix(o)
        then   return format("%s %s", o[0], ptext(1))
        end
        return "Bad opi:text"
      end,
  },
}

opi = OpInfo.new()
opi:addinfix(10, 11, "+ -")
opi:addinfix(30, 31, "* /")
opi:addinfix(41, 40, "^")
opi:addpostfix(50, "!")
opi:addprefix (20, "u-")

bin    = function (a, op, b) return Tree {[0]=op, a, b} end
pre    = function (op, a) return Tree {[0]=op, a} end
post   = function (a, op) return Tree {[0]=op, a} end
add    = function (a, b) return bin(a, "+", b) end
minus  = function (a, b) return bin(a, "-", b) end
mul    = 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
fact   = function (a) return Tree {[0]="!", a} end
uminus = function (a) return Tree {[0]="u-", a} end

--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Parenthesize2.lua"
= opi
= add(2, 3)
foo = add(2, 3)
= opi:opinfo(foo)
= opi:opinfo("+")
= opi:oinfo("+")
= opi:oinfo(foo)

* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Parenthesize2.lua"

test = function (o) print(trees(o, opi:text(o))) end
test(mul(1, add(2, 3)), "1 * (2 + 3)")
test(mul(add(1, 2), 3), "(1 + 2) * 3")
test(mul(add(1, 2), add(3, 4)), "ok")
test(add(mul(1, 2), mul(3, 4)), "ok")
test(add(2, 3))
test(add(1, mul(2, 3)))
test(add(mul(1, 2), 3))
test(minus(minus(1, 2), minus(3, 4)))
test(pow(pow(1, 2), pow(3, 4)))
test(mul(uminus(1), fact(2)))
test(uminus(fact(42)))
test(fact(uminus(42)))

--]]










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