Wrote a parser for a subset of canonical sexps
This commit is contained in:
parent
a6654f9c43
commit
1f7d215fdc
66
assets/.lua/csexp.lua
Normal file
66
assets/.lua/csexp.lua
Normal file
@ -0,0 +1,66 @@
|
||||
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, "^[1-9]%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}
|
Loading…
Reference in New Issue
Block a user