Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- brackets.lua -- version: 2004dec28 -- conventions: -- %b[] - balanced [] block -- %w - word constituent (everything but blanks chars and [ and ]) -- %s - space -- %c - non-[] chars _ = {} FAIL = {"FAIL"} FAILS = function (f) _ = pack(f()); return _[1] == FAIL end SUCCEEDS = function (f) _ = pack(f()); return _[1] ~= FAIL end pat0 = function (patstr) local _, __, e = string.find(subj, patstr, pos) if _ then pos = e else return FAIL end end wplus = function () return pat0("^[^ \t\n%[%]]+()") end splus = function () return pat0("^[ \t\n]+()") end cplus = function () return pat0("^[^%[%]]+()") end block = function () return pat0("^%b[]()") end subjsubstr = function (b, e) return string.sub(subj, b, e-1) end blockorwplus = function () -- %b[]|%w+ if SUCCEDS(block) then return end if SUCCEDS(wplus) then return end return FAIL end blockorwplus_plus = function () -- (%b[]|%w+)+ if FAILS(blockorwplus) then return FAIL end while SUCCEDS(blockorwplus) do end return pos end blockorwplus_eval = function () -- (%b[]|%w+)+ local b = pos if SUCCEEDS(block) then return evalblock(b, pos) end if SUCCEEDS(wplus) then return subjsubstr(b, pos) end return FAIL end blockorwplus_eval_plus = function () -- (%b[]|%w+)+ ??? if FAILS(blockorwplus_eval) then return FAIL end local result = _[1] while SUCCEEDS(blockorwplus_eval) do result = result .. _[1] end return result end argument = function () splus(); return blockorwplus_eval_plus() end arguments = function () local arr = {} while SUCCEEDS(argument) do table.insert(arr, _[1]) end return arr end evalblock = function (s, e) local oldpos = pos pos = s + 1 if FAILS(argument) then error("Empty block") end local head, args = _[1], arguments() pos = oldpos local f = functions[head] return f(unpack(args)) end functions = {} functions["<>"] = function (str) local s = "<"..str..">"; print(s); return s end functions["PP"] = function (...) PP(unpack(arg)); return "_" end subj = "foo bar[PP weep [<> blink]][<> aloo] b" print(subj) pos = 1 PP(22, argument()) PP(33, argument()) -- Notes: -- if an evalblock returns FAIL then things will get VERY messy -- gather_results = function () local a = {} store = function (x) tinsert(a, x) end result = function () return a end return store, result end stuff = function (gatheter, parsefunction) store, result = gatherer() while SUCCEEDS(parsefunction()) do store(_[1]) end return result() end pat0 = function (patstr) local _, __, e = string.find(subj, patstr, pos) if _ then pos = e else return FAIL end end subjsubstr = function (b, e) return string.sub(subj, b, e-1) end wplus = function () return pat0("^[^ \t\n%[%]]+()") end splus = function () return pat0("^[ \t\n]+()") end cplus = function () return pat0("^[^%[%]]+()") end block = function () return pat0("^%b[]()") end --%%%%% --% --% versao nova --% --%%%%% -- "r_" = "returning" -- "ir pack = function (...) return arg end id = function (...) return unpack(arg) end nop = function () end looking_at = function (pat) return function () local _, __, e = strfind(subj, pat, pos) if _ then pos = e; return true end end end blanks = looking_at("^[ \t\n]+()") wordchars = looking_at("^[^ \t\n%[%]]+()") bracket = looking_at("^%b[]()") OR = function (f1, f2) return function () return f1() or f2() end end PROG2 = function (f1, f2) return function () f1() return f2() end end r_string = function (f) return function () local b = pos if f() then r = string.sub(subj, b, pos-1); return true end end end --%%%%% --% --% gatherers for plus and star --% --%%%%% gplus_concat = function () local s return (function () s = r end), (function () s = s .. r end), (function () return s end) end gplus_list = function () local a return (function () a = {r} end), (function () table.insert(a, r) end), (function () return a end) end gstar_concat = function () local s return (function () if s then s = s .. r else s = r end), (function () return s end) end gstar_list = function () local a = {} return (function () table.insert(a, r) end), (function () return a end) end gplus_nil = function () return nop, nop, nop end gstar_nil = function () return nop, nop end --%%%%% --% --% PLUS and STAR using the gatherer functions --% --%%%%% r_gather_PLUS = function (gatherer, f) return function () local addfirst, addmore, result = gatherer() if not f() then return false end addfirst() while f() do addmore() end r = result() return true end end r_gather_STAR = function (gatherer, f) return function () local add, result = gatherer() while f() do add() end r = result() return true end end -- normalchars (nao vou usar por enquanto) -- (find-fline "~/elisp/lua-mode.el") r_concat_PLUS = function (f) return function () if not f() then return false end local newr = r while f() do newr = newr .. r end r = newr return true end end r_list_STAR = function (f) return function () local newr = {} while f() do table.insert(newr, r) end r = newr return true end end r_string_bigword = r_concat_PLUS(OR(r_string(wordchars), r_string(bracket)) r_string(wordchars) PROG2(blanks, argument bigword = r_concat_PLUS(OR(r_string(wordchars), r_eval_bracket) r_list_STAR = PROG2(blanks, starfs_concat = function () local s = "" STAR = function (f) return function () while f() end return true end end PLUS = function (f1, f2) f2 = f2 or f1 return function () if not f1() then return false end while f2() do end return true end end init, add, ret