summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2018-10-12 15:54:00 +0800
committer最萌小汐 <sumneko@hotmail.com>2018-10-12 15:54:00 +0800
commit015392d5769c1694bde7f75cd2f541e6a18dab3c (patch)
tree0b438334f371c5af6cacc417220f84f719b757c8 /src
parent3b8a6b8bcc14ea279a4e6c005e740777b01ab623 (diff)
downloadlua-language-server-015392d5769c1694bde7f75cd2f541e6a18dab3c.zip
main
Diffstat (limited to 'src')
-rw-r--r--src/json/decode.lua115
-rw-r--r--src/json/encode.lua128
-rw-r--r--src/json/init.lua6
-rw-r--r--src/parser/grammar.lua4
-rw-r--r--src/service/definition.lua0
-rw-r--r--src/service/init.lua5
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