This commit is contained in:
tour 2024-09-13 18:14:02 +02:00
parent e9d96b20d9
commit 2a90c58c50
2 changed files with 81 additions and 26 deletions

101
alg1.lua
View File

@ -1,4 +1,6 @@
local function stringToTable(str)
local parseTable -- defined later, but we need it in parseValue
local function parseValue(s, i)
s = s:match("^%s*(.-)%s*$", i) -- Trim leading/trailing spaces
i = 1
@ -6,57 +8,110 @@ local function stringToTable(str)
if s:sub(1, 1) == "{" then
return parseTable(s)
elseif s:sub(1, 4) == "true" then
return true, 5
return true, 4
elseif s:sub(1, 5) == "false" then
return false, 6
return false, 5
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
return nil, 3
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
if s:sub(i, i) == quote then
local j = i - 1
local escaped = false
while (s:sub(j,j)) == "\\" do
escaped = not escaped
j = j - 1
end
if not escaped then
value = value:gsub("\\(.)", "%1")
return value, i
end
end
value = value .. s:sub(i, i)
end
error("Unclosed string")
end
local _, next_i = s:find("^[+-]?%d+%.?%d*[eE][+-]?%d+%s*")
if not next_i then
_, next_i = s:find("^[+-]?%d+%.?%d*%s*")
end
if next_i then
return tonumber(s:match("^[+-]?%d+%.?%d*[eE][+-]?%d+") or s:match("^([+-]?%d+%.?%d*)")), next_i
else
print(s)
error("Invalid value")
end
end
local function parseTable(s)
local function parseKey(s, i)
s = s:match("^%s*(.-)%s*$", i) -- Trim leading/trailing spaces
i = 1
if s:find("^[%a_]") then
local key = s:match("^[%a%d_]*")
if key ~= "true" and key ~= "false" and key ~= "nil" then
return key, #key
end
end
end
function parseTable(s)
local tbl = {}
local i = 2 -- Start after the opening '{'
local key = nil
local key, value
local value_found -- we cannot check for value, bc {nil} is valid
local next_key = 1
local next_i
local function getNextKey()
while tbl[next_key] ~= nil do
next_key = next_key + 1
end
key = next_key
next_key = next_key + 1
return key
end
while i <= #s do
if s:sub(i, i) == "}" then
return tbl, i + 1
elseif s:sub(i, i) == "," then
local char = s:sub(i, i)
if char == "}" then
return tbl, i
elseif char == " " then
i = i + 1
elseif s:sub(i, i) == "[" then
local value, next_i = parseValue(s:sub(i + 1))
i = i + next_i
elseif char == "," or char == ";" then
if key ~= nil or (not value_found) then
error("value expected")
end
value_found = false
i = i + 1
elseif char == "[" then
if key ~= nil then
error("Expected value, not a key")
end
key, next_i = parseValue(s:sub(i + 1))
i = i + next_i + 1
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
key, next_i = parseKey(s:sub(i))
if not key then -- not a valid key
value, next_i = parseValue(s:sub(i))
key = getNextKey()
tbl[key] = value
value_found = true
key = nil
end
i = i + next_i
elseif char == "=" then
i = i + 1
local value, next_i = parseValue(s:sub(i))
value, next_i = parseValue(s:sub(i))
tbl[key] = value
value_found = true
key = nil
i = i + next_i - 1
i = i + next_i + 1
else
error("Unexpected character: " .. s:sub(i, i))
end

View File

@ -13,7 +13,7 @@ local tests = {
'{a = {b = {c = 3}}}',
'{1, "hello", true, false, nil, 3.14}',
'{[1] = "one", [2] = "two", ["three"] = 3}',
'{"quoted string", \'single quoted\'}',
'{"quoted string with an escaped quote \\"", \'single quoted\'}',
'{nested = {tables = {are = {supported = true}}}}',
"{key1 = 123, key2 = true, key3 = {nestedKey1 = 'value1', nestedKey2 = false}}",
"{}", "{ }",
@ -41,13 +41,13 @@ 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))
print(dump(outcome))
end
-- test("s2t1")
test("s2t1")
test("s2t2")
-- test("s2t3")
test("s2ttour")