summaryrefslogtreecommitdiff
path: root/test/catch.lua
diff options
context:
space:
mode:
Diffstat (limited to 'test/catch.lua')
-rw-r--r--test/catch.lua84
1 files changed, 84 insertions, 0 deletions
diff --git a/test/catch.lua b/test/catch.lua
new file mode 100644
index 00000000..849be09d
--- /dev/null
+++ b/test/catch.lua
@@ -0,0 +1,84 @@
+local m = require 'lpeglabel'
+
+local mt = {}
+
+local function catchedTable()
+ return setmetatable({}, mt)
+end
+
+function mt.__add(a, b)
+ if not a or not b then
+ return a or b
+ end
+ local t = catchedTable()
+ for _, v in ipairs(a) do
+ t[#t+1] = v
+ end
+ for _, v in ipairs(b) do
+ t[#t+1] = v
+ end
+ return t
+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 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
+ if mode == 'NL' then
+ newBuf[#newBuf+1] = text
+ line = line + 1
+ lineOffset = offset + #text - skipOffset
+ end
+ 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
+ end
+
+ return table.concat(newBuf), result
+end