--[[ Licensed according to the included 'LICENSE' document Author: Thomas Harning Jr ]] local lpeg = require("lpeg") local select = select local pairs, ipairs = pairs, ipairs local tonumber = tonumber local string_char = require("string").char local rawset = rawset local error = error local setmetatable = setmetatable module("json.decode.util") -- 09, 0A, 0B, 0C, 0D, 20 ascii_space = lpeg.S("\t\n\v\f\r ") do local chr = string_char local u_space = ascii_space -- \u0085 \u00A0 u_space = u_space + lpeg.P(chr(0xC2)) * lpeg.S(chr(0x85) .. chr(0xA0)) -- \u1680 \u180E u_space = u_space + lpeg.P(chr(0xE1)) * (lpeg.P(chr(0x9A, 0x80)) + chr(0xA0, 0x8E)) -- \u2000 - \u200A, also 200B local spacing_end = "" for i = 0x80,0x8b do spacing_end = spacing_end .. chr(i) end -- \u2028 \u2029 \u202F spacing_end = spacing_end .. chr(0xA8) .. chr(0xA9) .. chr(0xAF) u_space = u_space + lpeg.P(chr(0xE2, 0x80)) * lpeg.S(spacing_end) -- \u205F u_space = u_space + lpeg.P(chr(0xE2, 0x81, 0x9F)) -- \u3000 u_space = u_space + lpeg.P(chr(0xE3, 0x80, 0x80)) -- BOM \uFEFF u_space = u_space + lpeg.P(chr(0xEF, 0xBB, 0xBF)) _M.unicode_space = u_space end identifier = lpeg.R("AZ","az","__") * lpeg.R("AZ","az", "__", "09") ^0 hex = lpeg.R("09","AF","af") hexpair = hex * hex comments = { cpp = lpeg.P("//") * (1 - lpeg.P("\n"))^0 * lpeg.P("\n"), c = lpeg.P("/*") * (1 - lpeg.P("*/"))^0 * lpeg.P("*/") } comment = comments.cpp + comments.c ascii_ignored = (ascii_space + comment)^0 unicode_ignored = (unicode_space + comment)^0 local types = setmetatable({false}, { __index = function(self, k) error("Unknown type: " .. k) end }) function register_type(name) types[#types + 1] = name types[name] = #types return #types end _M.types = types function append_grammar_item(grammar, name, capture) local id = types[name] local original = grammar[id] if original then grammar[id] = original + capture else grammar[id] = capture end end -- Parse the lpeg version skipping patch-values -- LPEG <= 0.7 have no version value... so 0.7 is value DecimalLpegVersion = lpeg.version and tonumber(lpeg.version():match("^(%d+%.%d+)")) or 0.7 function get_invalid_character_info(input, index) local parsed = input:sub(1, index) local bad_character = input:sub(index, index) local _, line_number = parsed:gsub('\n',{}) local last_line = parsed:match("\n([^\n]+.)$") or parsed return line_number, #last_line, bad_character, last_line end function setObjectKeyForceNumber(t, key, value) key = tonumber(key) or key return rawset(t, key, value) end