Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This is the `blogme2-inner.lua' file of blogme2. -- It contains the "inner layer" of the kernel of blogme2 - just the parsers. -- Author and version: Eduardo Ochs <[email protected]>, 2005aug24 -- License: GPL. -- (find-fline "INTERNALS") -- (find-fline "blogme2-inner.lua") -- (find-fline "blogme2-middle.lua") -- (find-fline "blogme2-outer.lua") -- The lowest-level low-level parsers -- Remember (see the file INTERNALS): -- BP Long name/meaning Corresponding Lua pattern -- +------+----------------------+------------------------------------------+ -- | "%s" | space char | "[ \t\n]" | -- | "%w" | word char | "[^%[%]]" | -- | "%c" | normal char | "[^ \t\n%[%]]" | -- | "%B" | bracketed expression | "%b[]" | -- | "%W" | bigword | "(%w*%b[]*)*" (but not the empty string) | -- +------+----------------------+------------------------------------------+ -- subj = "" -- what we are parsing ("" is a dummy value, of course) pos = 0 -- current position; positions are 0-based val = nil -- the semantic value of parsing something b,e = 0, 0 -- beginning and end of the text inside []s _P = {} -- table of low-level parsers substring = function (b, e) return strsub(subj, b+1, e) end parse = function (blogmepat) return _P[blogmepat]() end parsepat = function (patstr) local _, __, newpos_ = string.find(subj, patstr, pos+1) if _ then pos = newpos_-1; return true end end _P["%s*"] = function () return parsepat("^[ \t\n]*()") end _P["%w+"] = function () return parsepat("^[^ \t\n%[%]]+()") end _P["%c+"] = function () return parsepat("^[^%[%]]+()") end _P["%B"] = function () return parsepat("^%b[]()") end _P["%w+:string"] = function () local origpos = pos if parse("%w+") then val = substring(origpos, pos); return true end end _P["%c+:string"] = function () local origpos = pos if parse("%c+") then val = substring(origpos, pos); return true end end -- Blogme parsers that invoke "%B:eval": -- Name Input Semantic value -- +----------------------+------------------+--------------+ -- | "%W:eval" | "a[lexp 22]bar" | "a22bar" | -- | "%s*;%W:eval" | " a[lexp 22]bar" | "a22bar" | -- | "(%s*;%W)*:evallist" | " a [lexp 22] " | {"a", 22} | -- | "(%c+|%B)*:eval" | " a [lexp 22] " | " a 22 " | -- +----------------------+------------------+--------------+ -- _P["%W:eval"] = function () local result = {} while parse("%w+:string") or parse("%B:eval") do tinsert(result, val) end if getn(result) == 1 then val = result[1]; return true end if getn(result) > 1 then val = concat(result); return true end end _P["%s*;%W:eval"] = function () parse("%s*") return parse("%W:eval") end _P["(%s*;%W)*:evallist"] = function () local result = {} while parse("%s*;%W:eval") do tinsert(result, val) end val = result return true end _P["(%c+|%B)*:eval"] = function () -- implicit concat local result = {} while parse("%c+:string") or parse("%B:eval") do tinsert(result, val or "") end val = concat(result) return true end -- Parsers with human-readable names _P["bigword:eval"] = _P["%s*;%W:eval"] -- almost always a string (!) _P["rest:string"] = _P["(%c+|%B)*:eval"] -- implicit eval _P["rest:list"] = _P["(%s*;%W)*:evallist"] -- implicit eval _P["rest:quote"] = function () val = substring(pos, e); return true end -- "%B:eval" itself. Parsing it can be so confusing... -- [ head arg1 arg2 ] -- /\pos instant 0 -- /\b /\pos instant 1 -- /\pos /\e instant 2 -- /\pos instant 3 -- _P["%B:eval"] = function () local oldb, olde = b, e -- instant 0 (pos = before the "[") b = pos+1 -- b = after the "[" if parse("%B") then -- instant 1 (pos = after the "]") pos, e = b, pos-1 -- instant 2 (b=pos= after "[", e = before "]") parse("%s*;%W:eval") -- instant 3 (pos = after the head) val = run_head(val) b, e, pos = oldb, olde, e+1 return true end b, e = oldb, olde end -- run_head: parse the args and run head(arg1, arg2, ...) _W = {} -- blogme words _A = {} -- argument-parsing functions for blogme words functionp = function (obj) return type(obj) == "function" end run_head = function (head) local headfun = _W[head] or _G[head] local argsfun = _A[head] if functionp(headfun) and functionp(argsfun) then return headfun(argsfun()) else print("Bad head:", head) printpos("pos:", pos) -- printpos is defined below printpos("b:", b) printpos("e:", e) error() end end -- printpos (I need to rewrite this) blogme_input_fname = "?" printpos = function (str, pos) printf("%s (progn (find-fline \"%s\") (goto-char %d))\n", str, blogme_input_fname, pos+1) end -- (find-fline "blogme2-inner.lua") -- (find-fline "blogme2-middle.lua") -- (find-fline "blogme2-outer.lua")