Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Создал NEO
- --http://computercraft.ru/user/13-neo/
- lexer = {}
- lexer.tokens = nil
- lexer.sep_chars = nil
- lexer.spec_chars = nil
- function checkArgs(n, ...)
- args = {...}
- if #args % 2 ~= 0 or #args/2 ~= n then return false end
- for i = 1, n, 2 do
- if type(args[i]) ~= args[i + 1] then
- error("argument "..i..": "..args[i].." is type "..type(args[i]))
- return false
- end
- end
- return true
- end
- function cutString(chars, start, tend)
- if checkArgs(3, chars, "table", start, "number", tend, "number") and start < tend and tend <= #chars then
- local len = #chars
- local out = ""
- for i = start, tend do
- out = out..chars[i]
- end
- return out
- end
- return nil
- end
- function isString(char)
- if #char > 1 then error("1 arg is not char") end
- res = string.match(char, "%a")
- if res ~= nil then return true end
- return false
- end
- function isNumber(char)
- if #char > 1 then error("1 arg is not char") end
- n = tonumber(char)
- if n ~= nil then
- return true
- end
- return false
- end
- function isChar(char)
- if checkArgs(1, char, "string") and #char == 1 then
- return true
- end
- return false
- end
- function getString(chars, pointer)
- if checkArgs(2, chars, "table", pointer, "number") then
- if #chars < pointer then error("pointer > chars") end
- local len = #chars
- local out = ""
- for i = pointer, len do
- if not lexer:isSepareChar(chars[i]) and not lexer:isSpecChar(chars, i) then
- out = out..chars[i]
- else
- return out, i-1
- end
- end
- return out, len
- end
- end
- function getNumber(chars, pointer)
- if checkArgs(2, chars, "table", pointer, "number") then
- local len = #chars
- local out = ""
- for i = pointer, len do
- n = string.match(chars[i], "%d")
- if n ~= nil then
- out = out..n
- else
- return tonumber(out), i-1
- end
- end
- return tonumber(out), len
- end
- end
- function lexer:setTokens(toks)
- if checkArgs(1, toks, "table") then
- self.tokens = toks
- end
- end
- function lexer:setSepareChars(sep_chars)
- if checkArgs(1, sep_chars, "table") then
- self.sep_chars = sep_chars
- end
- end
- function lexer:setSpecChars(spec_chars)
- if checkArgs(1, spec_chars, "table") then
- self.spec_chars = spec_chars
- end
- end
- function lexer:lex(str)
- self:isInit()
- --str = string.gsub(str, "%s+", " ")
- local str_len = #str
- local chars = self:cut(str, str_len)
- local p = 1
- local tokens = {}
- while p <= str_len do
- t, pp = self:getToken(chars, p)
- if t ~= nil then
- p = pp
- table.insert(tokens, t)
- end
- p = p + 1
- end
- return tokens
- end
- function lexer:isInit()
- if self.tokens == nil then error("tokens list is nil, setTokens.") end
- if self.sep_chars == nil then error("separe chars is nil, setSepareChars.") end
- if self.spec_chars == nil then error("spec chars is nil, setSpecChars.") end
- end
- function lexer:isSepareChar(char)
- self:isInit()
- if char == nil then return true end
- if #char > 1 then error("1 arg is not char.") end
- local sep_chars = self.sep_chars
- local len = #sep_chars
- for i = 1, len do
- if sep_chars[i] == char then
- return true
- end
- end
- return false
- end
- function lexer:isSpecChar(chars, pointer)
- self:isInit()
- if checkArgs(2, chars, "table", pointer, "number") then
- local len = #chars
- local spec_chars = self.spec_chars
- local len2 = #spec_chars
- local ret = false
- for i = 1, len2 do
- if chars[pointer] == spec_chars[i] then
- ret = true
- break
- end
- end
- if ret --[[and isSepareChar(chars[pointer+1]) or isNumber(chars[pointer+1]) or isString(chars[pointer+1])]] then
- return true
- else
- return false
- end
- end
- end
- function lexer:getToken(chars, pointer)
- self:isInit()
- if self:isSepareChar(chars[pointer]) then return nil, pointer end
- if chars[pointer] == "'" or chars[pointer] == '"' then
- local out = ""
- local len = #chars
- while pointer <= len do
- pointer = pointer + 1
- if chars[pointer] == "'" or chars[pointer] == '"' then
- local tmp = {}
- tmp.token = out
- tmp.type = "string"
- return tmp, pointer
- else
- out = out..chars[pointer]
- end
- end
- end
- if self:isSpecChar(chars, pointer) then
- tmp = {}
- tmp.token = chars[pointer]
- tmp.type = "spec_char"
- return tmp, pointer+#tmp.token-1
- end
- if self:isSepareChar(chars[pointer - 1]) or self:isSpecChar(chars, pointer-1) then
- local ret = false
- local tokens = self.tokens
- local len = #tokens
- local tmp = {}
- for i = 1, len do
- local len2 = #tokens[i]
- local pat = cutString(chars, pointer, pointer+len2-1)
- if pat ~= nil and self:isSepareChar(chars[pointer+len2]) then
- if tokens[i] == pat then
- ret = true
- tmp.token = pat
- tmp.type = "token"
- break
- end
- elseif pat ~= nil and self:isSpecChar(chars, pointer+len2) then
- if tokens[i] == pat then
- ret = true
- tmp.token = pat
- tmp.type = "token"
- break
- end
- end
- end
- if ret then
- return tmp, pointer+#tmp.token-1
- else
- if isString(chars[pointer]) then
- str, ppp = getString(chars, pointer)
- tmp.token = str
- tmp.type = "variable"
- return tmp, ppp
- elseif isNumber(chars[pointer]) then
- num, ppp = getNumber(chars, pointer)
- tmp.token = num
- tmp.type = "number"
- return tmp, ppp
- end
- end
- end
- return nil, pointer
- end
- function lexer:cut(str, len)
- if len <= 0 then error("string len <= 0") end
- local out = {}
- for i = 1, len do
- table.insert(out, string.sub(str, i, i))
- end
- return out
- end
- return lexer
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement