Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
--   http://angg.twu.net/LUA/Arith3.lua.html
--   http://angg.twu.net/LUA/Arith3.lua
--           (find-angg "LUA/Arith3.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- (defun a () (interactive) (find-angg "LUA/Arith3.lua"))
--
-- «.Ok»			(to "Ok")
-- «.Ok-tests»			(to "Ok-tests")
-- «.top-down-parser»		(to "top-down-parser")
-- «.top-down-parser-tests»	(to "top-down-parser-tests")


--[[
* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
rm -v    ~/LUA/lua50init.lua
mkdir -p ~/LUA/
cd       ~/LUA/
wget http://angg.twu.net/LUA/lua50init.lua
# (setenv "LUA_INIT" (concat "@" (ee-expand "~/LUA/lua50init.lua")))

rm -Rv /tmp/parser/
mkdir  /tmp/parser/
cd     /tmp/parser/
wget http://angg.twu.net/LUA/Arith3.lua
# (find-anchor  "/tmp/parser/Arith3.lua" "top-down-parser-tests")

--]]


Tokens = Class {
  fromcs = function (str) return Tokens(split(str, "(.)")) end,
  fromws = function (str) return Tokens(split(str)) end,
  type    = "Tokens",
  __tostring = function (tks) return tks:tostring() end,
  __index = {
    torect1 = function (tks, i)
        return Rect.from(tks[i].."\n"..i)
      end,
    torect = function (tks, i, j)
        i, j = i or 1, j or #tks
        local out = tks:torect1(i)
        for k=i+1,j do out = out.." "..tks:torect1(k) end
        return out
      end,
    torectp = function (tks) return tks:torect() .. "  pos=" .. tks.pos end,
    tostring1 = function (tks, i, j, sep)
        return table.concat(tks, sep or tks.sep or "", i or 1, j or #tks)
      end,
    tostring = function (tks, i, j)
        return tks:torect(i or 1, j or #tks):tostring()
      end,
    tostringp = function (tks) return tks:torectp():tostring() end,
    sub = function (tks, i, j) return TokenSeq.from(tks, i, j) end,
  },
}

TokenSeq = Class {
  type = "TokenSeq",
  from = function (tks, i, j) return TokenSeq {tks=tks, i=i, j=j} end,
  __tostring = function (ts) return ts:tostring1() end,
  __concat   = function (tsl, tsr) return tsl:glue(tsr) end,
  __index = {
    tostring1 = function (ts) return ts.tks:tostring1(ts.i, ts.j) end,
    tostring  = function (ts) return ts.tks:tostring (ts.i, ts.j) end,
    glue = function (tsl, tsr) return TokenSeq.from(tsl.tks, tsl.i, tsr.j) end,
  },
}

-- (find-dn6 "stacks.lua" "Stack")
--
Stack = Class {
  type    = "Stack",
  new     = function () return Stack {} end,
  --
  __tostring = function (s) return mapconcat(tostring, s, " ") end,
  __index = {
    push  = function (s, o) table.insert(s, o); return s end,
    pushs = function (s, ...) for _,o in ipairs({...}) do s:push(o) end; return s end,
    --
    check     = function (s) assert(#s>0, s.msg or "Empty stack"); return s end,
    drop      = function (s) s:check(); s[#s]=nil; return s end,
    dropn     = function (s, n) for i=1,n  do s:drop() end; return s end,
    dropuntil = function (s, n) while #s>n do s:drop() end; return s end,
    clear     = function (s)    return s:dropn(#s) end,
    --
    pop  = function (s) return                            s[#s], s:dropn(1) end,
    pop2 = function (s) return                   s[#s-1], s[#s], s:dropn(2) end,
    pop3 = function (s) return          s[#s-2], s[#s-1], s[#s], s:dropn(3) end,
    pop4 = function (s) return s[#s-3], s[#s-2], s[#s-1], s[#s], s:dropn(4) end,
    --
    pick = function (s, offset) return s[#s-offset] end,
    pock = function (s, offset, o)     s[#s-offset] = o; return s end,
  },
}

--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Arith2.lua"
tks = Tokens.fromcs "(1+2)*3^(4+5)"
tks.pos = 1
= tks
= tks:sub(3,5)
= tks:sub(3,5):tostring1()
= tks:sub(3,5):tostring()
s = Stack.new()
s:pushs(22, 44)
= s
s = Stack.new()
s:pushs(tks:sub(3,6), tks:sub(7,9))
= s

--]]



--   ___  _    
--  / _ \| | __
-- | | | | |/ /
-- | |_| |   < 
--  \___/|_|\_\
--             
-- «Ok»  (to ".Ok")
-- In the top-down parser below every parsing that succeed returns an
-- object of the class "Ok". The naming of the fields in the class Ok
-- is very bad (at the moment), but let me try to explain what they
-- mean anyway. If a parsing function return this,
--
--   Ok = {i=42, j=99, k=100, o="FOO BAR"}
--
-- this means that that parsing function parsed the tokens 42 to 99
-- (inclusive) of the global variable tks, and it returned "FOO BAR"
-- as the "output" of the parsing. The field "k" means that the next
-- parsing function should start at the token 100.

Ok = Class {
  type = "Ok",
  __tostring = function (ok)
      return format("i=%s j=%s k=%s o='%s'", ok.i, ok.j, ok.k, tostring(ok.o))
    end,
  __index = {
  },
}
sub = function (i, j)    return tks:sub(i, j) end
ok  = function (i, j, o)
    j = j or i
    o = o or sub(i, j)
    return Ok {i=i, j=j, k=j+1, o=o}
  end

-- «Ok-tests»  (to ".Ok-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Arith3.lua"
tks = Tokens.fromcs "(1+2+3)+4+(5+6)"
= tks
= sub(3,8)
= sub(3,8):tostring()
= ok(3,8)
= ok(3)
= ok(3, nil, "FOO BAR")

--]]




-- «top-down-parser»  (to ".top-down-parser")
-- Grammar (in the syntax or re.lua):
--   n         <- [0-9]
--   plus      <- "+"
--   openp     <- "("
--   closep    <- ")"
--   plusnorp  <- plus norp
--   plusnorps <- plusnorp*
--   norps     <- norp plusnorps
--   norp      <- n | p
--   p         <- openp norps closep

parse_n = function (i)
    if tks[i]:match("[0-9]") then return ok(i) end
  end
parse_plus = function (i)
    if tks[i] == "+" then return ok(i) end
  end
parse_openp = function (i)
    if tks[i] == "(" then return ok(i) end
  end
parse_closep = function (i)
    if tks[i] == ")" then return ok(i) end
  end

parse_plusnorp = function (i)
    local ok1 =         parse_plus(i)
    local ok2 = ok1 and parse_norp(ok1.k)
    return      ok2 and ok(i, ok2.j)
  end
parse_plusnorps = function (i)
    local k = i
    while true do
      local okn = parse_plusnorp(k)
      if not okn then return ok(i,k-1) end
      k = okn.k
    end
  end
parse_norps = function (i)
    local ok1 =         parse_norp(i)
    local ok2 = ok1 and parse_plusnorps(ok1.k)
    return      ok2 and ok(i, ok2.j)
  end
parse_norp = function (i)
    return parse_n(i) or parse_p(i)
  end
parse_p = function (i)
    local ok1 =         parse_openp(i)
    local ok2 = ok1 and parse_norps(ok1.k)
    local ok3 = ok2 and parse_closep(ok2.k)
    return      ok3 and ok(i, ok3.j)
  end



-- «top-down-parser-tests»  (to ".top-down-parser-tests")

--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Arith3.lua"
tks = Tokens.fromcs "(1+2+3)+4+(5+6)"
tks.pos = 1
= tks
= parse_openp(1)
= parse_n(2)
= parse_plus(3)
= parse_n(4)
= parse_closep(7)
= parse_p(1)
= parse_plusnorp(3)
= parse_plusnorps(3)
= parse_norp(2)
= parse_norp(4)
= parse_norps(2)
= parse_norp(1)
= parse_norps(1)

--]]





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