|
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 <edrx@mat.puc-rio.br>, 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")