diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2018-10-12 15:54:00 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2018-10-12 15:54:00 +0800 |
commit | 015392d5769c1694bde7f75cd2f541e6a18dab3c (patch) | |
tree | 0b438334f371c5af6cacc417220f84f719b757c8 /src | |
parent | 3b8a6b8bcc14ea279a4e6c005e740777b01ab623 (diff) | |
download | lua-language-server-015392d5769c1694bde7f75cd2f541e6a18dab3c.zip |
main
Diffstat (limited to 'src')
-rw-r--r-- | src/json/decode.lua | 115 | ||||
-rw-r--r-- | src/json/encode.lua | 128 | ||||
-rw-r--r-- | src/json/init.lua | 6 | ||||
-rw-r--r-- | src/parser/grammar.lua | 4 | ||||
-rw-r--r-- | src/service/definition.lua | 0 | ||||
-rw-r--r-- | src/service/init.lua | 5 |
6 files changed, 256 insertions, 2 deletions
diff --git a/src/json/decode.lua b/src/json/decode.lua new file mode 100644 index 00000000..c220622d --- /dev/null +++ b/src/json/decode.lua @@ -0,0 +1,115 @@ +local lpeg = require 'lpeglabel' +local save_sort + +local P = lpeg.P +local S = lpeg.S +local R = lpeg.R +local V = lpeg.V +local C = lpeg.C +local Ct = lpeg.Ct +local Cg = lpeg.Cg +local Cc = lpeg.Cc +local Cp = lpeg.Cp +local Cs = lpeg.Cs + +local EscMap = { + ['t'] = '\t', + ['r'] = '\r', + ['n'] = '\n', + ['"'] = '"', + ['\\'] = '\\', +} +local BoolMap = { + ['true'] = true, + ['false'] = false, +} + +local hashmt = { + __pairs = function (self) + local i = 1 + local function next() + i = i + 1 + local k = self[i] + if k == nil then + return + end + local v = self[k] + if v == nil then + return next() + end + return k, v + end + return next + end, + __newindex = function (self, k, v) + local i = 2 + while self[i] do + i = i + 1 + end + rawset(self, i, k) + rawset(self, k, v) + end, +} + +local tointeger = math.tointeger +local tonumber = tonumber +local setmetatable = setmetatable +local rawset = rawset +local function HashTable(patt) + return Ct(patt) / function (hash) + if save_sort then + local max = #hash // 2 + for i = 1, max do + local key, value = hash[2*i-1], hash[2*i] + hash[key] = value + hash[i+1] = key + end + hash[1] = nil + for i = max+2, max*2 do + hash[i] = nil + end + return setmetatable(hash, hashmt) + else + local max = #hash // 2 + for i = 1, max do + local a = 2*i-1 + local b = 2*i + local key, value = hash[a], hash[b] + hash[key] = value + hash[a] =nil + hash[b] = nil + end + return hash + end + end +end + +local Token = P +{ + V'Value' * Cp(), + Nl = P'\r\n' + S'\r\n', + Sp = S' \t', + Spnl = (V'Sp' + V'Nl')^0, + Bool = C(P'true' + P'false') / BoolMap, + Int = C('0' + (P'-'^-1 * R'19' * R'09'^0)) / tointeger, + Float = C(P'-'^-1 * ('0' + R'19' * R'09'^0) * '.' * R'09'^0) / tonumber, + Null = P'null' * Cc(nil), + String = '"' * Cs(V'Char'^0) * '"', + Char = V'Esc' + (1 - P'"' - P'\t' - V'Nl'), + Esc = P'\\' * C(S'tnr"\\') / EscMap, + Hash = V'Spnl' * '{' * V'Spnl' * HashTable(V'Object'^-1 * (P',' * V'Object')^0) * V'Spnl' * P'}'^-1 * V'Spnl', + Array = V'Spnl' * '[' * V'Spnl' * Ct(V'Value'^-1 * (P',' * V'Spnl' * V'Value')^0) * V'Spnl' * P']'^-1 * V'Spnl', + Object = V'Spnl' * V'Key' * V'Spnl' * V'Value' * V'Spnl', + Key = V'String' * V'Spnl' * ':', + Value = V'Hash' + V'Array' + V'Bool' + V'Null' + V'String' + V'Float' + V'Int', +} + +return function (str, save_sort_) + save_sort = save_sort_ + local table, pos = Token:match(str) + if not pos or pos <= #str then + pos = pos or 1 + error(('没匹配完[%s]\n%s'):format(pos, str:sub(pos, pos+100))) + end + return table +end diff --git a/src/json/encode.lua b/src/json/encode.lua new file mode 100644 index 00000000..135a51a1 --- /dev/null +++ b/src/json/encode.lua @@ -0,0 +1,128 @@ +local rep = string.rep +local format = string.format +local gsub = string.gsub +local sub = string.sub +local sort = table.sort +local tostring = tostring +local getmetatable = debug.getmetatable +local type = type +local next = next +local ipairs = ipairs + +local index +local lines +local n = -1 +local tabs = {} + +local esc_map = { + ['\\'] = '\\\\', + ['\r'] = '\\r', + ['\n'] = '\\n', + ['\t'] = '\\t', + ['"'] = '\\"', +} + +local function encode(data, key) + n = n + 1 + if not tabs[n] then + tabs[n] = rep('\t', n) + end + local tp = type(data) + if tp == 'table' then + if not data[1] and next(data) then + -- 认为这个是哈希表 + if key then + index=index+1;lines[index] = tabs[n] .. '"' .. gsub(key, '[\\\r\n\t"]', esc_map) .. '" : {\n' + else + index=index+1;lines[index] = tabs[n] .. '{\n' + end + local meta = getmetatable(data) + local sep + if meta and meta.__pairs then + for k, v in meta.__pairs(data), data do + if encode(v, k) then + index=index+1;lines[index] = ',\n' + sep = true + end + end + else + local list = {} + local i = 0 + for k in next, data do + i=i+1;list[i] = k + end + sort(list) + for j = 1, i do + local k = list[j] + if encode(data[k], k) then + index=index+1;lines[index] = ',\n' + sep = true + end + end + end + if sep then + lines[index] = '\n' + end + index=index+1;lines[index] = tabs[n] .. '}' + else + -- 认为这个是数组 + if key then + index=index+1;lines[index] = tabs[n] .. '"' .. gsub(key, '[\\\r\n\t"]', esc_map) .. '" : [\n' + else + index=index+1;lines[index] = tabs[n] .. '[\n' + end + local sep + for k, v in pairs(data) do + if encode(v) then + index=index+1;lines[index] = ',\n' + sep = true + end + end + if sep then + lines[index] = '\n' + end + index=index+1;lines[index] = tabs[n] .. ']' + end + elseif tp == 'number' then + if key then + index=index+1;lines[index] = tabs[n] .. '"' .. gsub(key, '[\\\r\n\t"]', esc_map) .. '" : ' .. data + else + index=index+1;lines[index] = tabs[n] .. data + end + elseif tp == 'boolean' then + if key then + index=index+1;lines[index] = tabs[n] .. '"' .. gsub(key, '[\\\r\n\t"]', esc_map) .. '" : ' .. tostring(data) + else + index=index+1;lines[index] = tabs[n] .. tostring(data) + end + elseif tp == 'nil' then + if key then + index=index+1;lines[index] = tabs[n] .. '"' .. gsub(key, '[\\\r\n\t"]', esc_map) .. '" : null' + else + index=index+1;lines[index] = tabs[n] .. 'null' + end + elseif tp == 'string' then + local str = gsub(data, '[\\\r\n\t"]', esc_map) + if key then + index=index+1;lines[index] = tabs[n] .. '"' .. gsub(key, '[\\\r\n\t"]', esc_map) .. '" : "' .. str .. '"' + else + index=index+1;lines[index] = tabs[n] .. '"' .. str .. '"' + end + else + n = n - 1 + return false + end + n = n - 1 + return true +end + +local function json(t) + lines = {} + index = 0 + + encode(t) + + return table.concat(lines) +end + +return json diff --git a/src/json/init.lua b/src/json/init.lua new file mode 100644 index 00000000..c28e7aed --- /dev/null +++ b/src/json/init.lua @@ -0,0 +1,6 @@ +local api = { + decode = require 'json.decode', + encode = require 'json.encode', +} + +return api diff --git a/src/parser/grammar.lua b/src/parser/grammar.lua index cb2d2e6f..3bf40939 100644 --- a/src/parser/grammar.lua +++ b/src/parser/grammar.lua @@ -233,8 +233,8 @@ TableField <- NewIndex / NewField / Exp NewIndex <- BL Exp BR ASSIGN Exp NewField <- Name ASSIGN Exp -Function <- (FUNCTION {| FuncName? |} PL ArgList? PR) -> FunctionDef - (!END Action)* -> Function +Function <- (FUNCTION {| FuncName? |} PL ArgList? PR) -> FunctionDef + (!END Action)* -> Function END FuncName <- Name (FuncSuffix)* FuncSuffix <- DOT Name diff --git a/src/service/definition.lua b/src/service/definition.lua new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/service/definition.lua diff --git a/src/service/init.lua b/src/service/init.lua new file mode 100644 index 00000000..91e0a4d4 --- /dev/null +++ b/src/service/init.lua @@ -0,0 +1,5 @@ +local api = { + definition = require 'service.definition' +} + +return api |