From 9b440f279e05131db5d2bba15efcd6fcf930e5ed Mon Sep 17 00:00:00 2001 From: tour Date: Sat, 14 Sep 2024 20:42:42 +0200 Subject: [PATCH] fix edge case when lua keywords are used as keys --- alg1.lua | 27 ++++++++++++++++++++++++++- alg2.lua | 34 ++++++++++++++++++++++++++++++---- algtour.lua | 27 ++++++++++++++++++++++++++- init.lua | 3 ++- 4 files changed, 84 insertions(+), 7 deletions(-) diff --git a/alg1.lua b/alg1.lua index dfe50bc..e67b6ef 100644 --- a/alg1.lua +++ b/alg1.lua @@ -44,11 +44,36 @@ local function stringToTable(str) end end + local lua_keywords = { + ["and"] = true, + ["break"] = true, + ["do"] = true, + ["else"] = true, + ["elseif"] = true, + ["end"] = true, + ["false"] = true, + ["for"] = true, + ["function"] = true, + ["goto"] = true, + ["if"] = true, + ["in"] = true, + ["local"] = true, + ["nil"] = true, + ["not"] = true, + ["or"] = true, + ["repeat"] = true, + ["return"] = true, + ["then"] = true, + ["true"] = true, + ["until"] = true, + ["while"] = true, + } + local function parseKey(s, i) s = s:match("^%s*(.-)%s*$", i) -- Trim leading/trailing spaces if s:find("^[%a_]") then local key = s:match("^[%a%d_]*") - if key ~= "true" and key ~= "false" and key ~= "nil" then + if not lua_keywords[key] then return key, #key end end diff --git a/alg2.lua b/alg2.lua index 2b358ab..ccbcfae 100644 --- a/alg2.lua +++ b/alg2.lua @@ -41,15 +41,41 @@ local function codedStringToTable(str) end end + local lua_keywords = { + ["and"] = true, + ["break"] = true, + ["do"] = true, + ["else"] = true, + ["elseif"] = true, + ["end"] = true, + ["false"] = true, + ["for"] = true, + ["function"] = true, + ["goto"] = true, + ["if"] = true, + ["in"] = true, + ["local"] = true, + ["nil"] = true, + ["not"] = true, + ["or"] = true, + ["repeat"] = true, + ["return"] = true, + ["then"] = true, + ["true"] = true, + ["until"] = true, + ["while"] = true, + } + local function parseKey(s) s = s:match("^%s*(.-)%s*$") -- trim whitespace if s:match("^%[(.*)%]$") then return parseValue(s:match("^%[(.*)%]$")) - elseif s:find("^[%a_][%a%d_]*$") then -- make sure the string is a valid lua identifier - return s - else - error("Unrecognized key: " .. s) end + s = s:match("^[%a_][%a%d_]*$") -- make sure the string is a valid lua identifier + if s and not lua_keywords[s] then + return s + end + error("Unrecognized key: " .. s) end local tbl = {} diff --git a/algtour.lua b/algtour.lua index 1091300..2c8e4ee 100644 --- a/algtour.lua +++ b/algtour.lua @@ -38,6 +38,31 @@ local function parse_value(str) return false, string.format("unable to parse '%s'", str) end +local lua_keywords = { + ["and"] = true, + ["break"] = true, + ["do"] = true, + ["else"] = true, + ["elseif"] = true, + ["end"] = true, + ["false"] = true, + ["for"] = true, + ["function"] = true, + ["goto"] = true, + ["if"] = true, + ["in"] = true, + ["local"] = true, + ["nil"] = true, + ["not"] = true, + ["or"] = true, + ["repeat"] = true, + ["return"] = true, + ["then"] = true, + ["true"] = true, + ["until"] = true, + ["while"] = true, +} + local function parse_key(str) if str:find("^%[.*%]$") then -- if in brackets, we can threat it like a value @@ -51,7 +76,7 @@ local function parse_key(str) return true, key end -- make sure the key is a valid identifier - if str:find("^[%a_][%a%d_]*$") then + if str:find("^[%a_][%a%d_]*$") and not lua_keywords[str] then return true, str end return false, string.format("'%s' is not a valid key", str) diff --git a/init.lua b/init.lua index aeb69b4..7f5e51f 100644 --- a/init.lua +++ b/init.lua @@ -26,6 +26,7 @@ local tests = { "{a = 1", "{'unclosed string\\'}", "{invalid key = 3}", + "{false = 2}", -- invalid key "{1 = 2}", -- invalid key "{,}", "{[nil] = 1}" @@ -44,7 +45,7 @@ local function test(alg) end local t2 = minetest.get_us_time() minetest.log("action",alg .. " = " .. (t2-t1)) - print(dump(outcome)) + -- print(dump(outcome)) end test("s2t1")