initial release
This commit is contained in:
116
cosmic rage/lua/json/decode/calls.lua
Normal file
116
cosmic rage/lua/json/decode/calls.lua
Normal file
@@ -0,0 +1,116 @@
|
||||
--[[
|
||||
Licensed according to the included 'LICENSE' document
|
||||
Author: Thomas Harning Jr <harningt@gmail.com>
|
||||
--]]
|
||||
local lpeg = require("lpeg")
|
||||
local tostring = tostring
|
||||
local pairs, ipairs = pairs, ipairs
|
||||
local next, type = next, type
|
||||
local error = error
|
||||
|
||||
local util = require("json.decode.util")
|
||||
|
||||
local buildCall = require("json.util").buildCall
|
||||
|
||||
local getmetatable = getmetatable
|
||||
|
||||
module("json.decode.calls")
|
||||
|
||||
local defaultOptions = {
|
||||
defs = nil,
|
||||
-- By default, do not allow undefined calls to be de-serialized as call objects
|
||||
allowUndefined = false
|
||||
}
|
||||
|
||||
-- No real default-option handling needed...
|
||||
default = nil
|
||||
strict = nil
|
||||
|
||||
local isPattern
|
||||
if lpeg.type then
|
||||
function isPattern(value)
|
||||
return lpeg.type(value) == 'pattern'
|
||||
end
|
||||
else
|
||||
local metaAdd = getmetatable(lpeg.P("")).__add
|
||||
function isPattern(value)
|
||||
return getmetatable(value).__add == metaAdd
|
||||
end
|
||||
end
|
||||
|
||||
local function buildDefinedCaptures(argumentCapture, defs)
|
||||
local callCapture
|
||||
if not defs then return end
|
||||
for name, func in pairs(defs) do
|
||||
if type(name) ~= 'string' and not isPattern(name) then
|
||||
error("Invalid functionCalls name: " .. tostring(name) .. " not a string or LPEG pattern")
|
||||
end
|
||||
-- Allow boolean or function to match up w/ encoding permissions
|
||||
if type(func) ~= 'boolean' and type(func) ~= 'function' then
|
||||
error("Invalid functionCalls item: " .. name .. " not a function")
|
||||
end
|
||||
local nameCallCapture
|
||||
if type(name) == 'string' then
|
||||
nameCallCapture = lpeg.P(name .. "(") * lpeg.Cc(name)
|
||||
else
|
||||
-- Name matcher expected to produce a capture
|
||||
nameCallCapture = name * "("
|
||||
end
|
||||
-- Call func over nameCallCapture and value to permit function receiving name
|
||||
|
||||
-- Process 'func' if it is not a function
|
||||
if type(func) == 'boolean' then
|
||||
local allowed = func
|
||||
func = function(name, ...)
|
||||
if not allowed then
|
||||
error("Function call on '" .. name .. "' not permitted")
|
||||
end
|
||||
return buildCall(name, ...)
|
||||
end
|
||||
else
|
||||
local inner_func = func
|
||||
func = function(...)
|
||||
return (inner_func(...))
|
||||
end
|
||||
end
|
||||
local newCapture = (nameCallCapture * argumentCapture) / func * ")"
|
||||
if not callCapture then
|
||||
callCapture = newCapture
|
||||
else
|
||||
callCapture = callCapture + newCapture
|
||||
end
|
||||
end
|
||||
return callCapture
|
||||
end
|
||||
|
||||
local function buildCapture(options)
|
||||
if not options -- No ops, don't bother to parse
|
||||
or not (options.defs and (nil ~= next(options.defs)) or options.allowUndefined) then
|
||||
return nil
|
||||
end
|
||||
-- Allow zero or more arguments separated by commas
|
||||
local value = lpeg.V(util.types.VALUE)
|
||||
local argumentCapture = (value * (lpeg.P(",") * value)^0) + 0
|
||||
local callCapture = buildDefinedCaptures(argumentCapture, options.defs)
|
||||
if options.allowUndefined then
|
||||
local function func(name, ...)
|
||||
return buildCall(name, ...)
|
||||
end
|
||||
-- Identifier-type-match
|
||||
local nameCallCapture = lpeg.C(util.identifier) * "("
|
||||
local newCapture = (nameCallCapture * argumentCapture) / func * ")"
|
||||
if not callCapture then
|
||||
callCapture = newCapture
|
||||
else
|
||||
callCapture = callCapture + newCapture
|
||||
end
|
||||
end
|
||||
return callCapture
|
||||
end
|
||||
|
||||
function load_types(options, global_options, grammar)
|
||||
local capture = buildCapture(options, global_options)
|
||||
if capture then
|
||||
util.append_grammar_item(grammar, "VALUE", capture)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user