ZNZNCOOP

lexer

Feb 22nd, 2016
107
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --Создал NEO
  2. --http://computercraft.ru/user/13-neo/
  3.  
  4. lexer = {}
  5.  
  6. lexer.tokens = nil
  7. lexer.sep_chars = nil
  8. lexer.spec_chars = nil
  9.  
  10. function checkArgs(n, ...)
  11.     args = {...}
  12.     if #args % 2 ~= 0 or #args/2 ~= n then return false end
  13.     for i = 1, n, 2 do
  14.         if type(args[i]) ~= args[i + 1] then
  15.             error("argument "..i..": "..args[i].." is type "..type(args[i]))
  16.             return false
  17.         end
  18.     end
  19.     return true
  20. end
  21.  
  22. function cutString(chars, start, tend)
  23.    if checkArgs(3, chars, "table", start, "number", tend, "number") and start < tend and tend <= #chars then
  24.       local len = #chars
  25.       local out = ""
  26.       for i = start, tend do
  27.          out = out..chars[i]
  28.       end
  29.       return out
  30.    end
  31.    return nil
  32. end
  33.  
  34. function isString(char)
  35.     if #char > 1 then error("1 arg is not char") end
  36.     res = string.match(char, "%a")
  37.     if res ~= nil then return true end
  38.     return false
  39. end
  40.  
  41. function isNumber(char)
  42.     if #char > 1 then error("1 arg is not char") end
  43.     n = tonumber(char)
  44.     if n ~= nil then
  45.         return true
  46.     end
  47.     return false
  48. end
  49.  
  50. function isChar(char)
  51.     if checkArgs(1, char, "string") and #char == 1 then
  52.         return true
  53.     end
  54.     return false
  55. end
  56.  
  57. function getString(chars, pointer)
  58.     if checkArgs(2, chars, "table", pointer, "number") then
  59.         if #chars < pointer then error("pointer > chars") end
  60.         local len = #chars
  61.         local out = ""
  62.         for i = pointer, len do
  63.             if not lexer:isSepareChar(chars[i]) and not lexer:isSpecChar(chars, i) then
  64.                 out = out..chars[i]
  65.             else
  66.                 return out, i-1
  67.             end
  68.         end
  69.         return out, len
  70.     end
  71. end
  72.  
  73. function getNumber(chars, pointer)
  74.     if checkArgs(2, chars, "table", pointer, "number") then
  75.         local len = #chars
  76.         local out = ""
  77.         for i = pointer, len do
  78.             n = string.match(chars[i], "%d")
  79.             if n ~= nil then
  80.                 out = out..n
  81.             else
  82.                 return tonumber(out), i-1
  83.             end
  84.         end
  85.         return tonumber(out), len
  86.     end
  87. end
  88.  
  89. function lexer:setTokens(toks)
  90.     if checkArgs(1, toks, "table") then
  91.         self.tokens = toks
  92.     end
  93. end
  94.  
  95. function lexer:setSepareChars(sep_chars)
  96.     if checkArgs(1, sep_chars, "table") then
  97.         self.sep_chars = sep_chars
  98.     end
  99. end
  100.  
  101. function lexer:setSpecChars(spec_chars)
  102.     if checkArgs(1, spec_chars, "table") then
  103.         self.spec_chars = spec_chars
  104.     end
  105. end
  106.  
  107. function lexer:lex(str)
  108.     self:isInit()
  109.     --str = string.gsub(str, "%s+", " ")
  110.     local str_len = #str
  111.     local chars = self:cut(str, str_len)
  112.     local p = 1
  113.     local tokens = {}
  114.     while p <= str_len do
  115.         t, pp = self:getToken(chars, p)
  116.         if t ~= nil then
  117.             p = pp
  118.             table.insert(tokens, t)
  119.         end
  120.         p = p + 1
  121.     end
  122.     return tokens
  123. end
  124.  
  125. function lexer:isInit()
  126.     if self.tokens == nil then error("tokens list is nil, setTokens.") end
  127.     if self.sep_chars == nil then error("separe chars is nil, setSepareChars.") end
  128.     if self.spec_chars == nil then error("spec chars is nil, setSpecChars.") end
  129. end
  130.  
  131. function lexer:isSepareChar(char)
  132.     self:isInit()
  133.     if char == nil then return true end
  134.     if #char > 1 then error("1 arg is not char.") end
  135.     local sep_chars = self.sep_chars
  136.     local len = #sep_chars
  137.     for i = 1, len do
  138.         if sep_chars[i] == char then
  139.             return true
  140.         end
  141.     end
  142.     return false
  143. end
  144.  
  145. function lexer:isSpecChar(chars, pointer)
  146.     self:isInit()
  147.     if checkArgs(2, chars, "table", pointer, "number") then
  148.         local len = #chars
  149.         local spec_chars = self.spec_chars
  150.         local len2 = #spec_chars
  151.         local ret = false
  152.         for i = 1, len2 do
  153.             if chars[pointer] == spec_chars[i] then
  154.                 ret = true
  155.                 break
  156.             end
  157.         end
  158.         if ret --[[and isSepareChar(chars[pointer+1]) or isNumber(chars[pointer+1]) or isString(chars[pointer+1])]] then
  159.             return true
  160.         else
  161.             return false
  162.         end
  163.     end
  164. end
  165.  
  166. function lexer:getToken(chars, pointer)
  167.     self:isInit()
  168.     if self:isSepareChar(chars[pointer]) then return nil, pointer end
  169.     if chars[pointer] == "'" or chars[pointer] == '"' then
  170.         local out = ""
  171.         local len = #chars
  172.         while pointer <= len do
  173.             pointer = pointer + 1
  174.             if chars[pointer] == "'" or chars[pointer] == '"' then
  175.                 local tmp = {}
  176.                 tmp.token = out
  177.                 tmp.type = "string"
  178.                 return tmp, pointer
  179.             else
  180.                 out = out..chars[pointer]
  181.             end
  182.         end
  183.     end
  184.     if self:isSpecChar(chars, pointer) then
  185.         tmp = {}
  186.         tmp.token = chars[pointer]
  187.         tmp.type = "spec_char"
  188.         return tmp, pointer+#tmp.token-1
  189.     end
  190.     if self:isSepareChar(chars[pointer - 1]) or self:isSpecChar(chars, pointer-1) then
  191.         local ret = false
  192.         local tokens = self.tokens
  193.         local len = #tokens
  194.         local tmp = {}
  195.         for i = 1, len do
  196.             local len2 = #tokens[i]
  197.             local pat = cutString(chars, pointer, pointer+len2-1)
  198.             if pat ~= nil and self:isSepareChar(chars[pointer+len2]) then
  199.                 if tokens[i] == pat then
  200.                     ret = true
  201.                     tmp.token = pat
  202.                     tmp.type = "token"
  203.                     break
  204.                 end
  205.             elseif pat ~= nil and self:isSpecChar(chars, pointer+len2) then
  206.                 if tokens[i] == pat then
  207.                     ret = true
  208.                     tmp.token = pat
  209.                     tmp.type = "token"
  210.                     break
  211.                 end
  212.             end
  213.         end
  214.         if ret then
  215.             return tmp, pointer+#tmp.token-1
  216.         else
  217.             if isString(chars[pointer]) then
  218.                 str, ppp = getString(chars, pointer)
  219.                 tmp.token = str
  220.                 tmp.type = "variable"
  221.                 return tmp, ppp
  222.             elseif isNumber(chars[pointer]) then
  223.                 num, ppp = getNumber(chars, pointer)
  224.                 tmp.token = num
  225.                 tmp.type = "number"
  226.                 return tmp, ppp
  227.             end
  228.         end
  229.     end
  230.     return nil, pointer
  231. end
  232.  
  233. function lexer:cut(str, len)
  234.     if len <= 0 then error("string len <= 0") end
  235.     local out = {}
  236.     for i = 1, len do
  237.         table.insert(out, string.sub(str, i, i))
  238.     end
  239.     return out
  240. end
  241.  
  242. return lexer
RAW Paste Data