It looks like you're new here. If you want to get involved, click one of these buttons!
function stringToTable(s) local t, side, key, negate, addDecimals = {} local nilFalse = true local count = 1 local inQuotes local function changeInQuotes(quoteType) if not inQuotes then inQuotes = quoteType return true elseif inQuotes == quoteType then inQuotes = nil return true end end local function emit() local val if nilFalse then val = side else val = nilFalse end if key then t[key] = val else t[count] = val count = count + 1 end side = nil nilFalse = true key = nil end local function isChar(c) return c:byte(1) >= 65 and c:byte(1) <= 90 or c:byte(1) >= 97 and c:byte(1) <= 122 or c == '_' end local function isDigit(c) return c:byte(1) >= 48 and c:byte(1) <= 57 end local i = 2 while i <= #s do local c = s:sub(i,i) if c ~= "'" or not changeInQuotes(1) then if c ~= '"' or not changeInQuotes(2) then if s:sub(i,i+2) == 'nil' then side = true nilFalse = nil i=i+2 elseif s:sub(i,i+3) == 'true' then side = true i=i+3 elseif s:sub(i,i+4) == 'false' then side = true nilFalse = false i=i+4 elseif inQuotes or isChar(c) then side = (side or '') .. c elseif isDigit(c) then local digit = c:byte(1) - 48 side = side or 0 if addDecimals then side = side + digit * math.pow(10, -addDecimals) addDecimals = addDecimals + 1 else side = side * 10 + digit end local c2 = s:sub(i+1,i+1) if negate and not isDigit(c2) and c2 ~= '.' then side = -side negate = nil end if not isDigit(c2) then addDecimals = nil end elseif c == '-' then negate = true elseif c == '.' then addDecimals = 1 elseif c == '{' then side, j = stringToTable(s:sub(i)) i=i+j - 1 elseif c == '}' then if side then emit() end return t, i elseif c == '=' then key = side side = nil elseif c == ',' then emit() elseif c == '[' then elseif c == ']' then elseif c == ' ' or c == '\r' or c == '\n' or c == '\t' then else return end end end i=i+1 end end function dumptable(t) local function maybeQuote(s) local quote = "" if type(s) == 'string' then return "'" .. tostring(s) .. "'" else return tostring(s) end end local result = '#==' .. #t .. ' {' for k,v in pairs(t) do local vv if type(v) == 'table' then vv = dumptable(v) else vv = maybeQuote(v) end result = result .. maybeQuote(k) .. '=' .. vv .. ', ' end return result .. '}' end function test(s) print('load: ' .. dumptable(load("return " .. s)())) print('stot: ' .. dumptable(stringToTable(s))) print() end test"{nil}" test"{true}" test"{false}" test"{[1]=1,[2]=2,[3]=3}" test"{[1]='a',[2]='b',[3]='c'}" test"{[1]='a',[3]='b',[5]='c'}" test"{['1']='a',['3']='b',['5']='c'}" test"{'abc','def'}" test"{'abc','def',}" test"{{'abc',123}}" test"{{'abc',123.789, 456}}" test"{{'abc',-123.789}}" test"{{'abc',.789}}" test"{{'abc',-.789}}" test"{['abc']=true,['def']=true}" test"{\r\n\t['abc']\r\n\t=\r\n\ttrue,\r\n\t[\r\n\t'def'\r\n\t]\r\n\t=\r\n\ttrue\r\n\t}" test"{abckey='abcval',defkey='defval',nested={'nestedabc','nesteddef',123,nil,true,false}}" test'{abckey="abcval",defkey="defval",nested={"nestedabc","nesteddef",123,nil,true,false}}' |
Likes: ar2rsawseen, pie
Comments
-uk
Markus