-- Hàm chuyển chuỗi thành table
function stringToTable(str)
-- Loại bỏ khoảng trắng thừa ở đầu và cuối
str = str:match("^%s*(.-)%s*$")
-- Kiểm tra nếu chuỗi rỗng hoặc không phải table
if str == "" or str:sub(1, 1) ~= "{" or str:sub(-1) ~= "}" then
return nil, "Invalid table string"
end
-- Hàm phụ để phân tích chuỗi thành table
local function parse(str, pos)
local t = {}
pos = pos or 1
local len = #str
while pos <= len do
-- Bỏ qua khoảng trắng
while pos <= len and str:sub(pos, pos):match("%s") do
pos = pos + 1
end
-- Kết thúc table
if pos > len then break end
if str:sub(pos, pos) == "}" then
return t, pos + 1
end
-- Phân tích key
local key
if str:sub(pos, pos) == "[" then
-- Key dạng [key]
pos = pos + 1
local start = pos
local bracket_count = 1
while pos <= len and bracket_count > 0 do
if str:sub(pos, pos) == "[" then
bracket_count = bracket_count + 1
elseif str:sub(pos, pos) == "]" then
bracket_count = bracket_count - 1
end
pos = pos + 1
end
if bracket_count ~= 0 then
return nil, "Invalid key syntax"
end
local key_str = str:sub(start, pos - 2)
key = load("return " .. key_str)()
if key == nil then
return nil, "Invalid key"
end
-- Bỏ qua dấu "="
while pos <= len and str:sub(pos, pos):match("%s") do
pos = pos + 1
end
if str:sub(pos, pos) ~= "=" then
return nil, "Expected '=' after key"
end
pos = pos + 1
else
-- Key dạng identifier hoặc số thứ tự
local start = pos
while pos <= len and str:sub(pos, pos):match("[%w_]") do
pos = pos + 1
end
key = str:sub(start, pos - 1)
if key == "" then
key = #t + 1
else
-- Bỏ qua dấu "="
while pos <= len and str:sub(pos, pos):match("%s") do
pos = pos + 1
end
if str:sub(pos, pos) ~= "=" then
pos = start
key = #t + 1
else
pos = pos + 1
end
end
end
-- Phân tích value
while pos <= len and str:sub(pos, pos):match("%s") do
pos = pos + 1
end
local value
local char = str:sub(pos, pos)
if char == "{" then
-- Table lồng nhau
value, pos = parse(str, pos + 1)
if value == nil then
return nil, pos
end
elseif char == "\"" or char == "'" then
-- Chuỗi
local quote = char
pos = pos + 1
local start = pos
while pos <= len and str:sub(pos, pos) ~= quote do
if str:sub(pos, pos) == "\\" then
pos = pos + 1
end
pos = pos + 1
end
if pos > len then
return nil, "Unterminated string"
end
value = str:sub(start, pos - 1)
pos = pos + 1
elseif char:match("%d") or char == "-" then
-- Số
local start = pos
while pos <= len and str:sub(pos, pos):match("[0-9%.eE%+%-]") do
pos = pos + 1
end
value = tonumber(str:sub(start, pos - 1))
if value == nil then
return nil, "Invalid number"
end
elseif str:sub(pos, pos + 3) == "true" then
value = true
pos = pos + 4
elseif str:sub(pos, pos + 4) == "false" then
value = false
pos = pos + 5
elseif str:sub(pos, pos + 2) == "nil" then
value = nil
pos = pos + 3
else
return nil, "Invalid value"
end
t[key] = value
-- Bỏ qua khoảng trắng trước dấu "," hoặc "}"
while pos <= len and str:sub(pos, pos):match("%s") do
pos = pos + 1
end
-- Kiểm tra dấu "," hoặc "}" (cho phép "}" ngay sau giá trị)
if pos <= len then
local next_char = str:sub(pos, pos)
if next_char == "," then
pos = pos + 1
elseif next_char ~= "}" then
return nil, "Expected ',' or '}'"
end
end
end
return t, pos
end
-- Gọi hàm phân tích và trả về kết quả
local result, err = parse(str)
if result == nil then
return nil, err
end
-- Kiểm tra nếu table có đúng một phần tử là table, trả về phần tử đó
local count = 0
local inner_table
for _, v in pairs(result) do
count = count + 1
if type(v) == "table" then
inner_table = v
else
inner_table = nil
break
end
end
if count == 1 and inner_table then
return inner_table
end
return result
end