Skip to content

Instantly share code, notes, and snippets.

@magicoal-nerb
Last active May 25, 2025 05:39
Show Gist options
  • Save magicoal-nerb/b6c8421fd812a22cc6a60127c8c81da7 to your computer and use it in GitHub Desktop.
Save magicoal-nerb/b6c8421fd812a22cc6a60127c8c81da7 to your computer and use it in GitHub Desktop.
-- Average stack based JSON parser i guess
local LEX_CLASSIFIER = {
8, 8, 8, 8, 8, 8, 8, 8, 8, 40, 40, 40, 40, 40, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 160, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 66, 16, 16, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 65, 65, 65, 65, 65,
65, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 16, 16, 16, 16, 16, 16, 66, 66, 66, 66, 66, 66, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16,
8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1,
1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
};
return function(content)
local root = { id = 0 };
local node = root;
local queue = {};
local length = #content;
local read = 1;
local id = 0;
while(read <= length)do
local current = string.byte(content, read);
local last = queue[#queue];
local classifier = LEX_CLASSIFIER[current + 1];
if(bit.btest(classifier, 0x20))then
-- Whitespace
elseif(current == 123 or current == 91)then
-- Open paranthesees / square bracket
if(not last or last.id ~= id)then
table.insert(queue, {
index = #node+1;
id = id;
})
end
local newStack = {};
id = id + 1;
newStack.id = id;
newStack.parent = node;
node = newStack;
elseif(current == 125 or current == 93)then
-- Closing paranthesees
local parent = node.parent;
if(parent.id == 0)then
-- End of file
break;
end
-- Should have been from an assignment.
assert(last.id == parent.id, "How?");
table.remove(queue);
parent[last.index] = node;
id = parent.id;
-- Set parent
node.parent = nil;
node.id = nil;
node = parent;
elseif(current == 58)then
table.insert(queue, {
index = table.remove(node);
id = id;
});
elseif(current == 34)then
-- String
local start = read + 1;
read = start;
while(string.byte(content, read) ~= 34)do
read = read + 1;
end
local data = string.sub(content, start, read-1);
if(last and last.id == id)then
-- Check last index
table.remove(queue);
node[last.index] = data;
else
-- Probably a literal
table.insert(node, data);
end
elseif(bit.btest(classifier, 0x7))then
-- Usually for booleans and stuff.
local start = read;
read = start + 1;
while(bit.btest(LEX_CLASSIFIER[string.byte(content, read) + 1], 0x07))do
read = read + 1;
end
read = read - 1;
local substr = string.sub(content, start, read);
if(bit.btest(classifier, 0x4))then
-- We had a number here!
substr = tonumber(substr);
end
if(last and last.id == id)then
-- Check last index
table.remove(queue);
node[last.index] = substr;
else
-- Probably a literal
table.insert(node, substr);
end
elseif(current == 44)then
-- ¯\_(ツ)_/¯
else
error("invalid character: " .. current .. " ascii: " .. string.char(current));
end
read = read + 1;
end
-- Close
assert(node.parent.id == 0, "Not enough closing braces :/");
node.parent = nil;
node.id = nil;
return node;
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment