1
0
mirror of https://github.com/g012/l65.git synced 2024-11-16 10:09:13 +00:00
l65/macro/TokenList.lua

202 lines
4.6 KiB
Lua
Raw Normal View History

---------------
-- A TokenList class for generating token lists.
--
-- There are also useful `get_` methods for extracting values from
-- the first token.
--
-- @module macro.TokenList
local TokenList = {}
local M = TokenList
TokenList.__index = TokenList
local append = table.insert
function TokenList.new (tl)
return setmetatable(tl or {},TokenList)
end
local TokenListList = {}
function TokenList.new_list (ltl)
return setmetatable(ltl or {},TokenListList)
end
TokenListList.__index = function(self,key)
local m = TokenList[key]
return function(self,...)
local res = {}
for i = 1,#self do res[i] = m(self[i],...) end
return TokenList.new_list(res)
end
end
-- token-getting helpers
local function extract (tl)
local tk = tl[1]
if tk[1] == 'space' then
tk = tl[2]
end
return tk
end
--- get an identifier from front of a token list.
-- @return identifier name
function TokenList.get_iden (tl)
local tk = extract(tl)
M.assert(tk[1]=='iden','expecting identifier')
return tk[2]
end
--- get an number from front of a token list.
-- @return number
function TokenList.get_number(tl)
local tk = extract(tl)
M.assert(tk[1]=='number','expecting number')
return tonumber(tk[2])
end
--- get a string from front of a token list.
-- @return string value (without quotes)
function TokenList.get_string(tl)
local tk = extract(tl)
M.assert(tk[1]=='string')
return tk[2]:sub(2,-2) -- watch out! what about long string literals??
end
--- takes a token list and strips spaces and comments.
-- @return new tokenlist
function TokenList.strip_spaces (tl)
local out = TokenList.new()
for _,t in ipairs(tl) do
if t[1] ~= 'comment' and t[1] ~= 'space' then
append(out,t)
end
end
return out
end
--- pick the n-th token from this tokenlist.
-- Note that it returns the value and type, not the type and value.
-- @param n (1 to #self)
-- @return token value
-- @return token type
function TokenList.pick (tl,n)
local t = tl[n]
return t[2],t[1]
end
-- token-putting helpers
local comma,space = {',',','},{'space',' '}
--- append an identifier.
-- @param name the identifier
-- @param no_space true if you don't want a space after the iden
-- @return self
function TokenList.iden(res,name,no_space)
append(res,{'iden',name})
if not no_space then
append(res,space)
end
return res
end
TokenList.name = TokenList.iden -- backwards compatibility!
--- append a string.
-- @param s the string
-- @return self
function TokenList.string(res,s)
append(res,{'string','"'..s..'"'})
return res
end
--- append a number.
-- @param val the number
-- @return self
function TokenList.number(res,val)
append(res,{'number',val})
return res
end
--- put out a list of identifiers, separated by commas.
-- @param res output token list
-- @param names a list of identifiers
-- @return self
function TokenList.idens(res,names)
for i = 1,#names do
res:iden(names[i],true)
if i ~= #names then append(res,comma) end
end
return res
end
TokenList.names = TokenList.idens -- backwards compatibility!
--- put out a token list.
-- @param res output token list
-- @param tl a token list
-- @return self
function TokenList.tokens(res,tl)
for j = 1,#tl do
append(res,tl[j])
end
return res
end
--- put out a list of token lists, separated by commas.
-- @param res output token list
-- @param ltl a list of token lists
-- @return self
function TokenList.list(res,ltl)
for i = 1,#ltl do
res:tokens(ltl[i])
if i ~= #ltl then append(res,comma) end
end
return res
end
--- put out a space token.
-- @param res output token list
-- @param space a string containing only whitespace (default ' ')
-- @return self
function TokenList.space(res,space)
append(res,{'space',space or ' '})
return res
end
--- put out a keyword token.
-- @param res output token list
-- @param keyw a Lua keyword
-- @param no_space true if you don't want a space after the iden
-- @return self
function TokenList.keyword(res,keyw,no_space)
append(res,{'keyword',keyw})
if not no_space then
append(res,space)
end
return res
end
--- convert this tokenlist into a string.
function TokenList.__tostring(tl)
local res = {}
for j = 1,#tl do
append(res,tl[j][2])
end
return table.concat(res)
end
--- put out a operator token. This is the overloaded call operator
-- for token lists.
-- @param res output token list
-- @param keyw an operator string
function TokenList.__call(res,t,v)
append(res,{t,v or t})
return res
end
return TokenList