83 lines
2.6 KiB
Lua
83 lines
2.6 KiB
Lua
local function stringToTable(str)
|
|
local function errorAtPos(msg, pos)
|
|
error(msg .. " at position " .. pos)
|
|
end
|
|
|
|
local function parseValue(s, i)
|
|
s = s:match("^%s*(.-)%s*$", i) -- Trim leading/trailing spaces
|
|
i = 1
|
|
|
|
if s:sub(i, i) == "{" then
|
|
return parseTable(s, i)
|
|
elseif s:sub(i, i+3) == "true" then
|
|
return true, i + 4
|
|
elseif s:sub(i, i+4) == "false" then
|
|
return false, i + 5
|
|
elseif s:sub(i, i+2) == "nil" then
|
|
return nil, i + 3
|
|
elseif s:match("^%-?%d+%.?%d*[eE]%-?%d+") or s:match("^%-?%d+%.?%d*") then
|
|
local num = tonumber(s:match("^%-?%d+%.?%d*[eE]%-?%d*"))
|
|
return num, i + #tostring(num)
|
|
elseif s:sub(i, i) == '"' or s:sub(i, i) == "'" then
|
|
local quote = s:sub(i, i)
|
|
local value = ""
|
|
i = i + 1
|
|
while i <= #s do
|
|
if s:sub(i, i) == quote and s:sub(i-1, i-1) ~= "\\" then
|
|
return value, i + 1
|
|
end
|
|
value = value .. s:sub(i, i)
|
|
i = i + 1
|
|
end
|
|
errorAtPos("Unclosed string", i)
|
|
else
|
|
errorAtPos("Invalid value", i)
|
|
end
|
|
end
|
|
|
|
local function parseTable(s, i)
|
|
local tbl = {}
|
|
local key = nil
|
|
i = i + 1 -- Start after the opening '{'
|
|
|
|
while i <= #s do
|
|
i = i + (s:match("^%s*", i) or 0) -- Skip any whitespace
|
|
|
|
if s:sub(i, i) == "}" then
|
|
return tbl, i + 1
|
|
elseif s:sub(i, i) == "," then
|
|
i = i + 1
|
|
elseif s:sub(i, i) == "[" then
|
|
key, i = parseValue(s, i + 1)
|
|
i = i + (s:match("^%s*", i) or 0)
|
|
if s:sub(i, i) ~= "]" then
|
|
errorAtPos("Expected closing bracket", i)
|
|
end
|
|
i = i + 1
|
|
elseif key == nil then
|
|
key, i = parseValue(s, i)
|
|
elseif s:sub(i, i) == "=" then
|
|
i = i + 1
|
|
local value
|
|
value, i = parseValue(s, i)
|
|
tbl[key] = value
|
|
key = nil
|
|
else
|
|
errorAtPos("Unexpected character", i)
|
|
end
|
|
end
|
|
errorAtPos("Unclosed table", i)
|
|
end
|
|
|
|
local function preprocess(str)
|
|
return str:gsub("%s+", " ") -- Replace multiple spaces with a single space
|
|
end
|
|
|
|
str = preprocess(str)
|
|
local result, _ = parseValue(str, 1)
|
|
return result
|
|
end
|
|
|
|
function test_string_to_table.s2t3(str)
|
|
return stringToTable(str)
|
|
end |