summaryrefslogtreecommitdiff
path: root/Tools/LuaMacro/macro/TokenList.lua
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-11-17 23:03:07 +0800
committerchai <chaifix@163.com>2021-11-17 23:03:07 +0800
commit27d6efb5f5a076f825fe2da1875e0cabaf02b4e7 (patch)
tree44f301110bc2ea742908ed92a78eba0803cd3b60 /Tools/LuaMacro/macro/TokenList.lua
parentb34310c631989551054d456eb47aaab5ded266a4 (diff)
+ LuaMacro
Diffstat (limited to 'Tools/LuaMacro/macro/TokenList.lua')
-rw-r--r--Tools/LuaMacro/macro/TokenList.lua201
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