commit 09e8eec9320cf097e3480143a69d2f5e5bdd9144 Author: AliasAlreadyTaken Date: Mon Sep 9 02:17:15 2024 +0200 Mehgit add * diff --git a/alg1.lua b/alg1.lua new file mode 100644 index 0000000..c549244 --- /dev/null +++ b/alg1.lua @@ -0,0 +1,73 @@ +local function stringToTable(str) + local function parseValue(s, i) + s = s:match("^%s*(.-)%s*$", i) -- Trim leading/trailing spaces + i = 1 + + if s:sub(1, 1) == "{" then + return parseTable(s) + elseif s:sub(1, 4) == "true" then + return true, 5 + elseif s:sub(1, 5) == "false" then + return false, 6 + elseif s:sub(1, 3) == "nil" then + return nil, 4 + elseif s:match("^%d+%.?%d*") then + local num = tonumber(s:match("^%d+%.?%d*")) + return num, #tostring(num) + 1 + elseif s:sub(1, 1) == '"' or s:sub(1, 1) == "'" then + local quote = s:sub(1, 1) + local value = "" + for i = 2, #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) + end + error("Unclosed string") + else + error("Invalid value") + end + end + + local function parseTable(s) + local tbl = {} + local i = 2 -- Start after the opening '{' + local key = nil + + while i <= #s do + 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 + local value, next_i = parseValue(s:sub(i + 1)) + i = i + next_i + if s:sub(i, i) ~= "]" then + error("Expected closing bracket") + end + key = value + i = i + 1 + elseif key == nil then + local value, next_i = parseValue(s:sub(i)) + key = value + i = i + next_i - 1 + elseif s:sub(i, i) == "=" then + i = i + 1 + local value, next_i = parseValue(s:sub(i)) + tbl[key] = value + key = nil + i = i + next_i - 1 + else + error("Unexpected character: " .. s:sub(i, i)) + end + end + error("Unclosed table") + end + + local result, _ = parseValue(str) + return result +end + +function test_string_to_table.s2t1(str) + return stringToTable(str) +end \ No newline at end of file diff --git a/alg2.lua b/alg2.lua new file mode 100644 index 0000000..b9eaf05 --- /dev/null +++ b/alg2.lua @@ -0,0 +1,76 @@ +local function stringToTable(str) + local function parseValue(s) + s = s:match("^%s*(.-)%s*$") -- trim whitespace + + if s == "nil" then + return nil + elseif s == "true" then + return true + elseif s == "false" then + return false + elseif tonumber(s) then + return tonumber(s) + elseif s:match("^\".*\"$") or s:match("^'.*'$") then + return s:sub(2, -2):gsub("\\(.)", "%1") -- handle escape sequences + elseif s:match("^%b{}$") then + return stringToTable(s) + else + error("Unrecognized value: " .. s) + end + end + + local tbl = {} + local key, value + local inKey = true + local depth = 0 + local buffer = "" + + for i = 1, #str do + local char = str:sub(i, i) + + if char == '{' then + if depth > 0 then + buffer = buffer .. char + end + depth = depth + 1 + + elseif char == '}' then + depth = depth - 1 + if depth > 0 then + buffer = buffer .. char + elseif depth == 0 and buffer ~= "" then + value = buffer + buffer = "" + end + + elseif char == ',' and depth == 1 then + if inKey then + key = parseValue(buffer) + else + value = parseValue(buffer) + tbl[key] = value + end + buffer = "" + inKey = not inKey + + elseif char == '=' and depth == 1 then + key = parseValue(buffer) + buffer = "" + inKey = false + + else + buffer = buffer .. char + end + + if depth == 1 and i == #str and buffer ~= "" then + value = parseValue(buffer) + tbl[key] = value + end + end + + return tbl +end + +function test_string_to_table.s2t2(str) + return stringToTable(str) +end \ No newline at end of file diff --git a/alg3.lua b/alg3.lua new file mode 100644 index 0000000..8e3803e --- /dev/null +++ b/alg3.lua @@ -0,0 +1,83 @@ +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 \ No newline at end of file diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..f08e14c --- /dev/null +++ b/init.lua @@ -0,0 +1,36 @@ +test_string_to_table ={} + +test_string_to_table.modpath = minetest.get_modpath("test_string_to_table") .. DIR_DELIM + +dofile(test_string_to_table.modpath .. "alg1.lua") +dofile(test_string_to_table.modpath .. "alg2.lua") +dofile(test_string_to_table.modpath .. "alg3.lua") + +local tests = { + '{1, 2, 3}', + '{a = 1, b = 2, c = 3}', + '{a = {b = {c = 3}}}', + '{1, "hello", true, false, nil, 3.14}', + '{[1] = "one", [2] = "two", ["three"] = 3}', + '{"quoted string", \'single quoted\'}', + '{nested = {tables = {are = {supported = true}}}}', + "{key1 = 123, key2 = true, key3 = {nestedKey1 = 'value1', nestedKey2 = false}}" +} + + + +local function test(alg) + -- alg1 + local outcome = {} + local t1 = minetest.get_us_time() + for _, case in ipairs(tests) do + local ret = {case, test_string_to_table[alg](case)} + table.insert(outcome, ret) + end + local t2 = minetest.get_us_time() + minetest.log("action",alg .. " = " .. (t2-t1)) +end + +-- test("s2t1") +-- test("s2t2") +test("s2t3") \ No newline at end of file diff --git a/mod.conf b/mod.conf new file mode 100644 index 0000000..f464fee --- /dev/null +++ b/mod.conf @@ -0,0 +1 @@ +name = test_string_to_table \ No newline at end of file