diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-09-21 21:34:22 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-09-21 21:34:22 +0800 |
commit | fb655ed5de736db10f63192a9efe70c2cddf3e21 (patch) | |
tree | b406bdaee79ad2c00a05708a01aa4156fe085525 /server-beta/src/parser | |
parent | 4215b35c77d879bddd1d19a71a2196e66fd439d8 (diff) | |
download | lua-language-server-fb655ed5de736db10f63192a9efe70c2cddf3e21.zip |
更新parser
Diffstat (limited to 'server-beta/src/parser')
-rw-r--r-- | server-beta/src/parser/guide.lua | 60 | ||||
-rw-r--r-- | server-beta/src/parser/lines.lua | 156 |
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 |