diff options
-rw-r--r-- | test/catch.lua | 108 | ||||
-rw-r--r-- | test/references/init.lua | 2 |
2 files changed, 57 insertions, 53 deletions
diff --git a/test/catch.lua b/test/catch.lua index 09b55929..849be09d 100644 --- a/test/catch.lua +++ b/test/catch.lua @@ -1,3 +1,5 @@ +local m = require 'lpeglabel' + local mt = {} local function catchedTable() @@ -18,63 +20,65 @@ function mt.__add(a, b) return t end -local function getLine(offset, lns) - for i = 0, #lns do - if offset >= lns[i] - and offset < lns[i+1] then - return i - end - end -end - -local function getPosition(offset, lns) - for i = 0, #lns do - if offset >= lns[i] - and offset < lns[i+1] then - return 10000 * i + offset - lns[i] - end - end +local function parseTokens(script, seps) + local parser = m.P { + m.Ct(m.V 'Token'^0), + Token = m.Cp() * (m.V 'Mark' + m.V 'Nl' + m.V 'Text'), + Mark = m.Cc 'ML' * m.P '<' * m.C(m.S(seps)) + + m.Cc 'MR' * m.C(m.S(seps)) * m.P '>', + Nl = m.Cc 'NL' * m.C(m.P '\r\n' + m.S '\r\n'), + Text = m.Cc 'TX' * m.C((1 - m.V 'Nl' - m.V 'Mark')^1), + } + local results = parser:match(script) + return results end ---@param script string ----@param sep string -return function (script, sep) - local pattern = ('()<(%s).-%s>()'):format(sep, sep) - local lns = {} - lns[0] = 0 - for pos in script:gmatch '()\n' do - lns[#lns+1] = pos - end - lns[#lns+1] = math.maxinteger - local codes = {} - local pos = 1 - ---@type integer[] - local list = {} - local cuted = 0 - local lastLine = 0 - for a, char, b in script:gmatch(pattern) do - codes[#codes+1] = script:sub(pos, a - 1) - codes[#codes+1] = script:sub(a + 2, b - 3) - pos = b - local line1 = getLine(a + 1, lns) - if line1 ~= lastLine then - cuted = 0 - lastLine = line1 +---@param seps string +return function (script, seps) + local tokens = parseTokens(script, seps) + local newBuf = {} + local result = {} + local marks = {} + + local lineOffset = 1 + local line = 0 + local skipOffset = 0 + for i = 1, #tokens, 3 do + local offset = tokens[i + 0] + local mode = tokens[i + 1] + local text = tokens[i + 2] + if mode == 'TX' then + newBuf[#newBuf+1] = text end - cuted = cuted + 2 - local left = getPosition(a + 1, lns) - cuted - local line2 = getLine(b - 3, lns) - if line2 ~= lastLine then - cuted = 0 - lastLine = line2 + if mode == 'NL' then + newBuf[#newBuf+1] = text + line = line + 1 + lineOffset = offset + #text - skipOffset end - local right = getPosition(b - 3, lns) - cuted - cuted = cuted + 2 - if not list[char] then - list[char] = catchedTable() + if mode == 'ML' then + marks[#marks+1] = { + char = text, + position = line * 10000 + offset - skipOffset - lineOffset, + } + skipOffset = skipOffset + 1 + #text + end + if mode == 'MR' then + for j = #marks, 1, -1 do + local mark = marks[j] + if mark.char == text then + local position = line * 10000 + offset - skipOffset - lineOffset + if not result[text] then + result[text] = catchedTable() + end + result[text][#result[text]+1] = { mark.position, position } + table.remove(marks, j) + break + end + end + skipOffset = skipOffset + 1 + #text end - list[char][#list[char]+1] = { left, right } end - codes[#codes+1] = script:sub(pos) - return table.concat(codes), list + + return table.concat(newBuf), result end diff --git a/test/references/init.lua b/test/references/init.lua index a14f0a02..78e9aabf 100644 --- a/test/references/init.lua +++ b/test/references/init.lua @@ -20,7 +20,7 @@ end function TEST(script) files.removeAll() - local newScript, catched = catch(script, '[!?~]') + local newScript, catched = catch(script, '!?~') files.setText('', newScript) local input = catched['?'] + catched['~'] |