FANDOM


<lua> expand = loadstring([[


-- Expand.lua


local strfind = string.find local strsub = string.sub local push = table.insert local pop = table.remove local concat = table.concat

local statements = {} for w in string.gfind('do if for while repeat', '%a+') do

 statements[w] = true

end

local function expand(str, ...)

 assert(type(str)=='string', 'expecting string')
 local searchlist = arg
 local estring,evar
 function estring(str)
   local b,e,i
   b,i = strfind(str, '%$.')
   if not b then return str end
   local R, pos = {}, 1
   repeat
     b,e = strfind(str, '^%b{}', i)
     if b then
       push(R, strsub(str, pos, b-2))
       push(R, evar(strsub(str, b+1, e-1)))
       i = e+1
       pos = i
     else
       b,e = strfind(str, '^%b()', i)
       if b then
         push(R, strsub(str, pos, b-2))
         push(R, evar(strsub(str, b+1, e-1)))
         i = e+1
         pos = i
       elseif strfind(str, '^%a', i) then
         push(R, strsub(str, pos, i-2))
         push(R, evar(strsub(str, i, i)))
         i = i+1
         pos = i
       elseif strfind(str, '^%$', i) then
         push(R, strsub(str, pos, i))
         i = i+1
         pos = i
       end
     end
     b,i = strfind(str, '%$.', i)
   until not b
   push(R, strsub(str, pos))
   return concat(R)
 end
 local function search(index)
   for _,symt in ipairs(searchlist) do
     local ts = type(symt)
     local value
     if     ts == 'function' then value = symt(index)
     elseif ts == 'table'
         or ts == 'userdata' then value = symt[index]
         if type(value)=='function' then value = value(symt) end
     else error'search item must be a function, table or userdata' end
     if value ~= nil then return value end
   end
   error('unknown variable: '.. index)
 end
 local function elist(var, v, str, sep)
   local tab = search(v)
   if tab then
     assert(type(tab)=='table', 'expecting table from: '.. var)
     local R = {}
     push(searchlist, 1, tab)
     push(searchlist, 1, false)
     for _,elem in ipairs(tab) do
       searchlist[1] = elem
       push(R, estring(str))
     end
     pop(searchlist, 1)
     pop(searchlist, 1)
     return concat(R, sep)
   else
     return 
   end
 end
 local function get(tab,index)
   for _,symt in ipairs(searchlist) do
     local ts = type(symt)
     local value
     if     ts == 'function' then value = symt(index)
     elseif ts == 'table'
         or ts == 'userdata' then value = symt[index]
     else error'search item must be a function, table or userdata' end
     if value ~= nil then
       tab[index] = value  -- caches value and prevents changing elements
       return value
     end
   end
 end
 function evar(var)
   if strfind(var, '^[_%a][_%w]*$') then -- ${vn}
     return estring(tostring(search(var)))
   end
   local b,e,cmd = strfind(var, '^(%a+)%s.')
   if cmd == 'foreach' then -- ${foreach vn xxx} or ${foreach vn/sep/xxx}
     local vn,s
     b,e,vn,s = strfind(var, '^([_%a][_%w]*)([%s%p]).', e)
     if vn then
       if strfind(s, '%s') then
         return elist(var, vn, strsub(var, e), )
       end
       b = strfind(var, s, e, true)
       if b then
         return elist(var, vn, strsub(var, b+1), strsub(var,e,b-1))
       end
     end
     error('syntax error in: '.. var, 2)
   elseif cmd == 'when' then -- $(when vn xxx)
     local vn
     b,e,vn = strfind(var, '^([_%a][_%w]*)%s.', e)
     if vn then
       local t = search(vn)
       if not t then
         return 
       end
       local s = strsub(var,e)
       if type(t)=='table' or type(t)=='userdata' then
         push(searchlist, 1, t)
         s = estring(s)
         pop(searchlist, 1)
         return s
       else
         return estring(s)
       end
     end
     error('syntax error in: '.. var, 2)
   else
     if statements[cmd] then -- do if for while repeat
       var = 'local OUT="" '.. var ..' return OUT'
     else  -- expression
       var = 'return '.. var
     end
     local f = assert(loadstring(var))
     local t = searchlist[1]
     assert(type(t)=='table' or type(t)=='userdata', 'expecting table')
     setfenv(f, setmetatable({}, {__index=get, __newindex=t}))
     return estring(tostring(f()))
   end
 end
 return estring(str)

end

return expand ]])()

template = [[ variables: $v environment: ${HOME} list: ${for i=1,list.n do

   OUT = table.concat{ OUT, ' list[', i, '] = ', list[i], '\n'}
 end}

]]

L = {'A', 'B', 'C', 'D', n=4} local x = {

 v = 'variable',
 list = L

}

io.write(expand(template, x, _G, os.getenv))

</lua>

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.