summaryrefslogtreecommitdiff
path: root/server-beta/src/parser
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2019-09-21 21:34:22 +0800
committer最萌小汐 <sumneko@hotmail.com>2019-09-21 21:34:22 +0800
commitfb655ed5de736db10f63192a9efe70c2cddf3e21 (patch)
treeb406bdaee79ad2c00a05708a01aa4156fe085525 /server-beta/src/parser
parent4215b35c77d879bddd1d19a71a2196e66fd439d8 (diff)
downloadlua-language-server-fb655ed5de736db10f63192a9efe70c2cddf3e21.zip
更新parser
Diffstat (limited to 'server-beta/src/parser')
-rw-r--r--server-beta/src/parser/guide.lua60
-rw-r--r--server-beta/src/parser/lines.lua156
2 files changed, 66 insertions, 150 deletions
diff --git a/server-beta/src/parser/guide.lua b/server-beta/src/parser/guide.lua
index d7f39652..061efaec 100644
--- a/server-beta/src/parser/guide.lua
+++ b/server-beta/src/parser/guide.lua
@@ -1,4 +1,6 @@
-local error = error
+local error = error
+local utf8Len = utf8.len
+local utf8Offset = utf8.offset
_ENV = nil
@@ -172,4 +174,60 @@ function m.getLabel(root, block, name)
error('guide.getLocal overstack')
end
+--- 获取偏移对应的坐标(row从0开始,col为光标位置)
+---@param lines table
+---@return integer {name = 'row'}
+---@return integer {name = 'col'}
+function m.positionOf(lines, offset)
+ if offset < 1 then
+ return 0, 0
+ end
+ local lastLine = lines[#lines]
+ if offset > lastLine.finish then
+ return #lines - 1, lastLine.finish - lastLine.start
+ end
+ local min = 1
+ local max = #lines
+ for _ = 1, 100 do
+ if max <= min then
+ local line = lines[min]
+ return min - 1, offset - line.start
+ end
+ local row = (max - min) // 2 + min
+ local line = lines[row]
+ if offset < line.start then
+ max = row - 1
+ elseif offset >= line.finish then
+ min = row + 1
+ else
+ return row - 1, offset - line.start
+ end
+ end
+ error('Stack overflow!')
+end
+
+--- 获取坐标对应的偏移(row从0开始,col为光标位置)
+---@param lines table
+---@param row integer
+---@param col integer
+---@return integer {name = 'offset'}
+function m.offsetOf(lines, row, col)
+ if row < 0 then
+ return 0
+ end
+ if row > #lines - 1 then
+ local lastLine = lines[#lines]
+ return lastLine.finish
+ end
+ local line = lines[row + 1]
+ local len = line.finish - line.start
+ if col < 0 then
+ return line.start
+ elseif col > len then
+ return line.finish
+ else
+ return line.start + col
+ end
+end
+
return m
diff --git a/server-beta/src/parser/lines.lua b/server-beta/src/parser/lines.lua
index f2f076e1..b36829de 100644
--- a/server-beta/src/parser/lines.lua
+++ b/server-beta/src/parser/lines.lua
@@ -1,15 +1,10 @@
local m = require 'lpeglabel'
+local utf8Len = utf8.len
-local function utf8_len(buf, start, finish)
- local len, pos = utf8.len(buf, start, finish)
- if len then
- return len
- end
- return 1 + utf8_len(buf, start, pos-1) + utf8_len(buf, pos+1, finish)
-end
+_ENV = nil
local function Line(start, line, finish)
- line.start = start
+ line.start = start - 1
line.finish = finish - 1
return line
end
@@ -34,154 +29,17 @@ end
local parser = m.P{
'Lines',
Lines = m.Ct(m.V'Line'^0 * m.V'LastLine'),
-Line = m.Cp() * m.V'Indent' * (1 - m.V'Nl')^0 * m.Cp() * m.V'Nl' / Line,
+Line = m.Cp() * m.V'Indent' * (1 - m.V'Nl')^0 * m.V'Nl' * m.Cp() / Line,
LastLine= m.Cp() * m.V'Indent' * (1 - m.V'Nl')^0 * m.Cp() / Line,
Nl = m.P'\r\n' + m.S'\r\n',
Indent = m.C(m.S' \t')^0 / Space,
}
-local mt = {}
-mt.__index = mt
-
-function mt:position(row, col, code)
- if row < 1 then
- return 1
- end
- code = code or self.code
- if row > #self then
- if code == 'utf8' then
- return utf8_len(self.buf) + 1
- else
- return #self.buf + 1
- end
- end
- local line = self[row]
- local next_line = self[row+1]
- local start = line.start
- local finish
- if next_line then
- finish = next_line.start - 1
- else
- finish = #self.buf + 1
- end
- local pos
- if code == 'utf8' then
- pos = utf8.offset(self.buf, col, start) or finish
- else
- pos = start + col - 1
- end
- if pos < start then
- pos = start
- elseif pos > finish then
- pos = finish
- end
- return pos
-end
-
-local function isCharByte(byte)
- if not byte then
- return false
- end
- -- [0-9]
- if byte >= 48 and byte <= 57 then
- return true
- end
- -- [A-Z]
- if byte >= 65 and byte <= 90 then
- return true
- end
- -- [a-z]
- if byte >= 97 and byte <= 122 then
- return true
- end
- -- <utf8>
- if byte >= 128 then
- return true
- end
- return false
-end
-
-function mt:positionAsChar(row, col, code)
- local pos = self:position(row, col, code)
- if isCharByte(self.buf:byte(pos, pos)) then
- return pos
- elseif isCharByte(self.buf:byte(pos+1, pos+1)) then
- return pos + 1
- end
- return pos
-end
-
-function mt:rowcol(pos, code)
- if pos < 1 then
- return 1, 1
- end
- code = code or self.code
- if pos >= #self.buf + 1 then
- local start = self[#self].start
- if code == 'utf8' then
- return #self, utf8_len(self.buf, start) + 1
- else
- return #self, #self.buf - start + 2
- end
- end
- local min = 1
- local max = #self
- for _ = 1, 100 do
- if max == min then
- local start = self[min].start
- if code == 'utf8' then
- return min, utf8_len(self.buf, start, pos)
- else
- return min, pos - start + 1
- end
- end
- local row = (max - min) // 2 + min
- local start = self[row].start
- if pos < start then
- max = row
- elseif pos > start then
- local next_start = self[row + 1].start
- if pos < next_start then
- if code == 'utf8' then
- return row, utf8_len(self.buf, start, pos)
- else
- return row, pos - start + 1
- end
- elseif pos > next_start then
- min = row + 1
- else
- return row + 1, 1
- end
- else
- return row, 1
- end
- end
- error('rowcol failed!')
-end
-
-function mt:line(i)
- local start, finish = self:range(i)
- return self.buf:sub(start, finish)
-end
-
-function mt:range(i)
- if i < 1 or i > #self then
- return 0, 0
- end
- return self[i].start, self[i].finish
-end
-
-function mt:set_code(code)
- self.code = code
-end
-
-return function (self, buf, code)
- local lines, err = parser:match(buf)
+return function (self, text)
+ local lines, err = parser:match(text)
if not lines then
return nil, err
end
- lines.buf = buf
- lines.code = code
- return setmetatable(lines, mt)
+ return lines
end