From 23f01fe6daf1a6fd37ada66ed85fb916ed11b36a Mon Sep 17 00:00:00 2001 From: tour Date: Fri, 13 Sep 2024 15:05:53 +0200 Subject: [PATCH] add another algo --- algtour.lua | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++ init.lua | 5 ++- 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 algtour.lua diff --git a/algtour.lua b/algtour.lua new file mode 100644 index 0000000..281ef27 --- /dev/null +++ b/algtour.lua @@ -0,0 +1,113 @@ +local nested_tables = {} + +-- strings might contain characters that are part of the table syntax. +-- We need to mask them, otherwise they might break our parser +-- based on https://www.lua.org/pil/20.4.html +local function code(s) + -- mask all escaped characters + return s:gsub("\\(.)", function (c) + return string.format("\\%03d", string.byte(c)) + end):gsub("([\"'])(.-)%1", function (_, match) -- detect all strings + return "'" .. match:gsub("([,;{}%[%]=])", function (c) + return string.format("\\%03d", string.byte(c)) + end) .. "'" + end) +end + +local function decode(s) + return s:gsub("\\(%d%d%d)", function (d) + return string.char(d) + end) +end + + +local function parse_value(str) + if str == "nil" then + return true, nil + elseif str == "true" then + return true, true + elseif str == "false" then + return true, false + elseif str:find("^([\"']).-%1$") then + return true, decode(str:sub(2, -2)) + elseif tonumber(str) then + return true, tonumber(str) + elseif nested_tables[str] then + return true, nested_tables[str] + end + return false, string.format("unable to parse '%s'", str) +end + +local function parse_key(str) + if str:find("^%[.*%]$") then + -- if in brackets, we can threat it like a value + local success, key = parse_value(str:sub(2, -2)) + if not success then + return false, key + end + if key == nil then + return false, "nil cannot be a key" + end + return true, key + end + -- make sure the key is a valid identifier + if str:find("^[%a_][%a%d_]*$") then + return true, str + end + return false, string.format("'%s' is not a valid key", str) +end + +local function parse_flat_table(str) + if str:find("{%s*}") then return true, {} end + str = str:gsub("^{(.-)[,;]?%s*}$", "%1,") + local next_index = 1 + + local res = {} + for pair in str:gmatch("(.-)[,;]") do + local key, value, success + if pair:find("=") then + key, value = pair:match("^(.-)=(.*)$") + key = key:gsub("^%s*(.-)%s*$", "%1") + success, key = parse_key(key) + if not success then return false, key end + else + while res[next_index] ~= nil do + next_index = next_index + 1 + end + key = next_index + next_index = next_index + 1 + value = pair + end + value = value:gsub("^%s*(.-)%s*$", "%1") + success, value = parse_value(value) + if not success then return false, value end + + res[key] = value + end + + return true, res +end + +local function stringToTable(str) + str = code(str) + + nested_tables = {} + local success = true + local tbl + + local replacements = 0 + local table_count = 0 + repeat + str, replacements = str:gsub("({[^{}]*})", function (match) + table_count = table_count + 1 + success, tbl = parse_flat_table(match) + nested_tables["\\t" .. tostring(table_count)] = tbl + return "\\t" .. tostring(table_count) + end) + until replacements == 0 or success == false + return success and (nested_tables[str] or "not a table") or tbl +end + +function test_string_to_table.s2ttour(str) + return stringToTable(str) +end \ No newline at end of file diff --git a/init.lua b/init.lua index f08e14c..0274358 100644 --- a/init.lua +++ b/init.lua @@ -5,6 +5,7 @@ test_string_to_table.modpath = minetest.get_modpath("test_string_to_table") .. D dofile(test_string_to_table.modpath .. "alg1.lua") dofile(test_string_to_table.modpath .. "alg2.lua") dofile(test_string_to_table.modpath .. "alg3.lua") +dofile(test_string_to_table.modpath .. "algtour.lua") local tests = { '{1, 2, 3}', @@ -26,6 +27,7 @@ local function test(alg) for _, case in ipairs(tests) do local ret = {case, test_string_to_table[alg](case)} table.insert(outcome, ret) + minetest.log(dump(ret)) end local t2 = minetest.get_us_time() minetest.log("action",alg .. " = " .. (t2-t1)) @@ -33,4 +35,5 @@ end -- test("s2t1") -- test("s2t2") -test("s2t3") \ No newline at end of file +-- test("s2t3") +test("s2ttour") \ No newline at end of file