summaryrefslogtreecommitdiff
path: root/script/parser/guide.lua
diff options
context:
space:
mode:
Diffstat (limited to 'script/parser/guide.lua')
-rw-r--r--script/parser/guide.lua155
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 = {