Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This is the `blogme2-middle.lua' file of blogme2. -- It contains the "middle layer" of the kernel of blogme2 - the -- functions for parsing arguments, the main functions for defining -- blogme words, and a handful of words. -- 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") ----------[[ argument-parsing functions ]]---------- --;; --;; vparse: parse and return val --;; pparse: parse a string and print the result (for debugging) --;; vparse = function (tag) if parse(tag or "rest:string") then return val end end pparse = function (str, tag) subj, pos = str, 0; print(vparse(tag)) end -- dbg --;; --;; typical argument-parsing functions --;; vword = function () return vparse("bigword:eval") end vrest = function () parse("%s*"); return vparse("rest:string") end vrest_a = function () return vparse("rest:list") end -- "array" vrest_q = function () parse("%s*"); return substring(pos, e) end -- "quoted" vargs1_ = function () return vrest() end vargs2_ = function () return vword(), vrest() end vargs3_ = function () return vword(), vword(), vrest() end vargs4_ = function () return vword(), vword(), vword(), vrest() end vargs1 = function () return vrest() or "" end vargs2 = function () return vword(), vrest() or "" end vargs3 = function () return vword(), vword(), vrest() or "" end vargs4 = function () return vword(), vword(), vword(), vrest() or "" end vargs1_a = function () return vrest_a() end vargs2_a = function () return vword(), vrest_a() end vargs3_a = function () return vword(), vword(), vrest_a() end vargs4_a = function () return vword(), vword(), vword(), vrest_a() end vargs1_q = function () return vrest_q() end vargs2_q = function () return vword(), vrest_q() end vargs3_q = function () return vword(), vword(), vrest_q() end vargs4_q = function () return vword(), vword(), vword(), vrest_q() end nop = function () end _AA = { ["1"] =vargs1, ["2"] =vargs2, ["3"] =vargs3, ["4"] =vargs4, ["1L"]=vargs1_a, ["2L"]=vargs2_a, ["3L"]=vargs3_a, ["4L"]=vargs4_a, ["1Q"]=vargs1_q, ["2Q"]=vargs2_q, ["3Q"]=vargs3_q, ["4Q"]=vargs4_q } ----------[[ def - a simple high-level tool for defining heads ]]---------- --;; --;; eval, expr, slambda, lambda, undollar --;; eval = function (body) return assert(loadstring(body))() end expr = function (body) return assert(loadstring("return "..body))() end slambda = function (arglist, body) -- here body is made of statements return assert(loadstring( "return function ("..arglist..")\n"..body.."\nend"))() end lambda = function (arglist, body) -- here body is an expression return assert(loadstring( "return function ("..arglist..")\nreturn "..body.."\nend"))() end undollar = function (str) str = string.gsub(str, "%$([a-z]+)", "\"..%1..\"") str = string.gsub(str, "%$(%b())", "\"..%1..\"") str = string.gsub(str, "%$(%b[])", function (s) return "]]..("..strsub(s, 2, -2)..")..[[" end) return str end --;; --;; def itself. Note that def is to be invoked from Lua code. --;; Example: def [[ BF 1 str "<strong>$str</strong>" ]] --;; runs as: _G["BF"] = function (str) return "<strong>"..str.."</strong>" end --;; _A["BF"] = _AA["1"] or _G["1"] --;; -- (find-luafile "src/lib/lstrlib.c" "case 's' : res = isspace(c)") -- (find-node "(libc)Classification of Characters" "int isspace") def = function (str) local _, __, name, aspec, arglist, body = string.find (str, "^%s*(%S+)%s+(%S+)%s+(%S+)%s(.*)") _G[name] = lambda(arglist, undollar(body)) _A[name] = _AA[aspec] or _G[aspec] or error("Bad argument-parsing specificier: "..name.." "..aspec) end ----------[[ DEF - for defining blogme words in blogme ]]---------- --;; $, list, WITH and withvars. --;; Blogme's "WITH" is similar to Elisp's "let". --;; We use dynamic scoping because it is trivial to implement. --;; See: (info "(elisp)Variable Scoping") --;; Example of use: --;; [WITH [list a valueofa b valueofb] --;; a is [$ a], b is [$ b]; --;; [WITH [list a othervalueofa b othervalueofb] --;; inside the sub-"WITH": a is [$ a], b is [$ b];] --;; outside again, a is [$ a], b is [$ b]. --;; ] --;; The above gets expanded to this (modulo whitespace): --;; a is valueofa, b is valueofb; --;; inside the sub-"WITH": a is othervalueofa, b is othervalueofb; --;; outside again, a is valueofa, b is valueofb. --;; _V = {} def [[ $ 1 varname _V[varname] or "" ]] def [[ list 1L arr arr ]] def [[ WITH nop noargs withvars(vword(), vrest) or "" ]] withvars = function (plist, code) local _Vbackups = {} for i=1,getn(plist),2 do local varname, value = plist[i], plist[i+1] tinsert(_Vbackups, {varname, _V[varname]}) _V[varname] = value end local result = code() for i=getn(_Vbackups),1,-1 do local varname, value = _Vbackups[i][1], _Vbackups[i][2] _V[varname] = value end return result end --;; --;; withsubj, withvars_expand, zip: auxiliary functions used by DEF --;; withsubj = function (newsubj, code) local oldsubj, oldpos = subj, pos subj, pos = newsubj, 0 local result = code() subj, pos = oldsubj, oldpos return result end withvars_expand = function (plist, text) return withvars(plist, function () return withsubj(text, vparse) end) end zip = function (arr1, arr2) local arr12 = {} for i=1,getn(arr1) do tinsert(arr12, arr1[i]) tinsert(arr12, arr2[i]) end return arr12 end --;; --;; DEF itself. --;; --;; Here's a simple example. This: --;; [DEF HREF 2 url,text <a href="[$ url]">[$ str]</a>] --;; runs like this: --;; HREF = function (url, text) --;; return withvars_expand({"url", url, "text", text}, --;; "<a href=\"[$ url]\">[$ str]</a>") --;; end --;; _A["HREF"] = vargs2 --;; Note that the `[DEF ...]' construct is used inside blogme code, --;; while the `def [[...]]' construct is a Lua command. --;; Let's dissect how the the definition of "DEF", below, works. --;; First we transform the above into: --;; local wordname = "HREF" --;; local argparser = vargs2 --;; local argnamelist = {"url", "text"} --;; local text = "<a href=\"[$ url]\">[$ str]</a>" --;; _G[wordname] = function (...) --;; return withvars_expand(zip(argnamelist, arg), text) --;; end --;; _A[wordname] = argparser --;; And now it's easy to write the word DEF: --;; DEF = function (wordname, argparser_spec, argnames, text) local argparser = _AA[argparser_spec] or _G[argparser_spec] local argnamelist = split(argnames, "([^,]+)") _G[wordname] = function (...) return withvars_expand(zip(argnamelist, arg), text) end _A[wordname] = argparser return "" end _A["DEF"] = vargs4_q --------------------------------------------------------- -- (find-blogmefile "blogme.lua" "_G[\"lua:\"]")