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: