Here's a JSON parser in LPeg, the excellent PEG parser from one of the Lua authors. The function "decode" returns the final, complete tree data structure.
local lpeg = require"lpeg"
local P, S, R, V = lpeg.P, lpeg.S, lpeg.R, lpeg.V
local C, Cc, Cf, Cg, Ct = lpeg.C, lpeg.Cc, lpeg.Cf, lpeg.Cg, lpeg.Ct
local function to8(n)
... -- Lua code to normalize UTF-16 to UTF-8
end
local unicode = P"u" * (R("09", "AF", "af")^4 / to8)
local named = C'"' + C"\\" + C"/" + (P"b" * Cc"\b") + (P"f" * Cc"\f") + (P"n" * Cc"\n") + (P"r" * Cc"\r") + (P"t" * Cc"\t")
local escaped = P"\\" * (named + unicode)
local unescaped = C((P(1) - S'\\"')^1)
local qstring = Ct(P'"' * (unescaped + escaped)^0 * P'"') / table.concat
local exp = S"Ee" * S"-+"^-1 * R"09"^1
local frac = P"." * R"09"^1
local number = (S"-+"^-1 * R"09"^1 * frac^-1 * exp^-1) / tonumber
local boolean = (P"true" * Cc(true)) + (P"false" * Cc(false))
local null = P"null" * Cc(nil)
local space = S" \t\r\n"^0
local JSON = { "Value",
Value = space * (V"Object" + V"Array" + V"Simple") * space,
Object = Cf(Ct"{" * space * Cg(qstring * space * P":" * V"Value" * P","^-1 * space)^0 * P"}", rawset),
Array = Ct(P"[" * space * (V"Value" * P","^-1 * space)^0 * P"]"),
Simple = number + boolean + null + qstring,
}
local function decode(txt)
return lpeg.match(JSON, txt)
end