test_string_to_table/alg3.lua
AliasAlreadyTaken 09e8eec932 Mehgit add *
2024-09-09 02:17:15 +02:00

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