diff options
Diffstat (limited to 'script/parser/guide.lua')
-rw-r--r-- | script/parser/guide.lua | 155 |
1 files changed, 64 insertions, 91 deletions
diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 6dcfbf95..b65d9680 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -54,6 +54,7 @@ local type = type ---@field ref parser.guide.object[] ---@field returnIndex integer ---@field docs parser.guide.object[] +---@field state table ---@field _root parser.guide.object ---@field _noders noders ---@field _mnode parser.guide.object @@ -85,13 +86,14 @@ local breakBlockTypes = { ['in'] = true, ['loop'] = true, ['repeat'] = true, + ['for'] = true, } local childMap = { ['main'] = {'#', 'docs'}, ['repeat'] = {'#', 'filter'}, ['while'] = {'filter', '#'}, - ['in'] = {'keys', '#'}, + ['in'] = {'keys', 'exps', '#'}, ['loop'] = {'loc', 'max', 'step', '#'}, ['if'] = {'#'}, ['ifblock'] = {'filter', '#'}, @@ -547,24 +549,24 @@ function m.getRange(source) return start, finish end ---- 判断source是否包含offset -function m.isContain(source, offset) +--- 判断source是否包含position +function m.isContain(source, position) local start, finish = m.getStartFinish(source) if not start then return false end - return start <= offset and finish >= offset + return start <= position and finish >= position end ---- 判断offset在source的影响范围内 +--- 判断position在source的影响范围内 --- --- 主要针对赋值等语句时,key包含value -function m.isInRange(source, offset) +function m.isInRange(source, position) local start, finish = m.getRange(source) if not start then return false end - return start <= offset and finish >= offset + return start <= position and finish >= position end function m.isBetween(source, tStart, tFinish) @@ -596,8 +598,8 @@ local function addChilds(list, obj) f(obj, list) end ---- 遍历所有包含offset的source -function m.eachSourceContain(ast, offset, callback) +--- 遍历所有包含position的source +function m.eachSourceContain(ast, position, callback) local list = { ast } local mark = {} while true do @@ -609,8 +611,8 @@ function m.eachSourceContain(ast, offset, callback) list[len] = nil if not mark[obj] then mark[obj] = true - if m.isInRange(obj, offset) then - if m.isContain(obj, offset) then + if m.isInRange(obj, position) then + if m.isContain(obj, position) then local res = callback(obj) if res ~= nil then return res @@ -722,15 +724,13 @@ function m.eachSource(ast, callback) end --- 获取指定的 special ----@param ast parser.guide.object ----@param name string ----@param callback fun(source: parser.guide.object) function m.eachSpecialOf(ast, name, callback) local root = m.getRoot(ast) - if not root.specials then + local state = root.state + if not state.specials then return end - local specials = root.specials[name] + local specials = state.specials[name] if not specials then return end @@ -739,92 +739,65 @@ function m.eachSpecialOf(ast, name, callback) end end ---- 获取光标偏移对应的坐标。 ---- 如果在换行符的右侧,则认为在新的一行。 ---- 第一行的行号是1不是0。 ----@param lines table ----@return integer {name = 'row'} ----@return integer {name = 'col'} -function m.positionOf(lines, offset) - if offset <= 0 then - return 1, 0 - end - local lastLine = lines[#lines] - if offset >= lastLine.finish then - return #lines, 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, 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, offset - line.start - end - end - error('Stack overflow!') +--- 将 position 拆分成行号与列号 +--- +--- 第一行是0 +---@param position integer +---@return integer row +---@return integer col +function m.rowColOf(position) + return position // 10000, position % 10000 end ---- 获取坐标对应的光标偏移。 ---- 一定会落在当前行的换行符左侧。 ---- 第一行的行号是1不是0。 ----@param lines table +--- 将行列合并为 position +--- +--- 第一行是0 ---@param row integer ---@param col integer ----@return integer {name = 'offset'} -function m.offsetOf(lines, row, col) - if row < 1 then - return 0 - end - if row > #lines then - local lastLine = lines[#lines] - return lastLine.finish - end - local line = lines[row] - local len = line.range - line.start - if col < 0 then - return line.start - elseif col > len then - return line.range - else - return line.start + col - end +---@return integer +function m.positionOf(row, col) + return row * 10000 + col end -function m.lineContent(lines, text, row, ignoreNL) - local line = lines[row] - if not line then - return '' - end - if ignoreNL then - return text:sub(line.start, line.range) - else - return text:sub(line.start, line.finish) - end +function m.positionToOffsetByLines(lines, position) + local row, col = m.rowColOf(position) + return lines[row] + col - 1 end -function m.lineRange(lines, row, ignoreNL) - local line = lines[row] - if not line then - return 0, 0 - end - if ignoreNL then - return line.start, line.range - else - return line.start, line.finish +--- 返回全文光标位置 +---@param state any +---@param position integer +function m.positionToOffset(state, position) + return m.positionToOffsetByLines(state.lines, position) +end + +function m.offsetToPositionByLines(lines, offset) + local left = 0 + local right = #lines + local row = 0 + while true do + row = (left + right) // 2 + if row == left then + if right ~= left then + if lines[right] <= offset then + row = right + end + end + break + end + local start = lines[row] - 1 + if start > offset then + right = row + else + left = row + end end + local col = offset - lines[row] + 1 + return m.positionOf(row, col) end -function m.lineData(lines, row) - return lines[row] +function m.offsetToPosition(state, offset) + return m.offsetToPositionByLines(state.lines, offset) end local isSetMap = { |