peachy/assets/.lua/csexp.lua

67 lines
1.6 KiB
Lua

local function _parse(str, init)
local pos = init
if string.find(str, "^%(", pos) then
pos = pos + 1
local list = {};
while true do
if string.find(str, "^%)", pos) then
pos = pos + 1
return list, pos
end
local child, new_pos = _parse(str, pos)
if not child then
error(string.format("expected ')', '(', or atom at index %d", pos))
end
table.insert(list, child)
pos = new_pos
end
else
local pos = init
local len_str = string.match(str, "^%d+", pos)
if not len_str then
error(string.format("expected '(' or atom at index %d", pos))
end
local len = tonumber(len_str)
pos = pos+#len_str
if not string.find(str, "^:", pos) then error(string.format("expected ':' at index %d", pos)) end
pos = pos + 1
local value = string.sub(str, pos, pos + len - 1)
if #value < len then error(string.format("unexpected end of string at index %d", pos)) end
pos = pos + len
return value, pos
end
end
local function parse(str)
local value, pos = _parse(str, 1)
if pos <= #str then
error(string.format("extra characters at index %d", pos))
end
return value
end
local function _serialize(tokens, obj)
if type(obj) == "table" then
table.insert(tokens, "(")
for _, item in ipairs(obj) do
_serialize(tokens, item)
end
table.insert(tokens, ")")
else
local s = tostring(obj)
table.insert(tokens, tostring(#s))
table.insert(tokens, ":")
table.insert(tokens, s)
end
end
local function serialize(obj)
local tokens = {}
_serialize(tokens, obj)
return table.concat(tokens)
end
return {parse = parse, serialize = serialize}