diff options
Diffstat (limited to 'Tools/LuaMacro/macro/TokenList.lua')
-rw-r--r-- | Tools/LuaMacro/macro/TokenList.lua | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/Tools/LuaMacro/macro/TokenList.lua b/Tools/LuaMacro/macro/TokenList.lua new file mode 100644 index 0000000..a18ac67 --- /dev/null +++ b/Tools/LuaMacro/macro/TokenList.lua @@ -0,0 +1,201 @@ +--------------- +-- 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 |