User:Anaminus/class tree

From Legacy Roblox Wiki
Jump to navigationJump to search

Trees

Parser

  • Save as "ParseTree.lua"
  • require "ParseTree"</syntaxhighlight>

Does not handle errors or bad syntax

local COMMENT		= "'"
local BEGIN_CLASS	= "["
local END_CLASS		= "]"
local BEGIN_IN		= "("
local END_IN		= ")"
local BEGIN_OUT		= "{"
local END_OUT		= "}"
local METHOD		= "$"
local PROPERTY		= "#"
local EVENT		= "@"
local CALLBACK		= "&"
local YIELD		= "^"
local ENUM		= "?"
local PRELIMINARY	= "!"
local DEPRECATED	= "~"
local PROTECTED		= "*"
local LOCKED		= "%%"
local BLOCK		= ";"

local CLASS_PREFIX	= ENUM..PRELIMINARY..DEPRECATED
local CLASS_POSTFIX	= END_CLASS..BLOCK
local CLASS_ENCLOSE	= BEGIN_CLASS..END_CLASS
local MEMBER_STATUS	= PRELIMINARY..DEPRECATED
local MEMBER_PREFIX	= PRELIMINARY..DEPRECATED..PROTECTED..LOCKED
local IN_ENCLOSE	= BEGIN_IN..END_IN
local OUT_ENCLOSE	= BEGIN_OUT..END_OUT
local BEGIN_PREFIX	= BEGIN_IN..BEGIN_OUT

local function GetMemberSet(name,status)
	local set = {
		preliminary	= not not status:match(PRELIMINARY);
		deprecated	= not not status:match(DEPRECATED);
		protected	= not not status:match(PROTECTED);
		locked		= not not status:match(LOCKED);
		name		= name;
	}
	return set
end

local function GetArgs(str)
	local set = {}
	if str then
		str = str:sub(2,-2)
		for a in str:gmatch("[^,]+") do
			local default = a:match("=%s*(.-)$")
			local type = default and a:match("^%s*(.-)%s*=") or a:match("^%s*(.+)%s*$")
			table.insert(set,{type=type,default=default})
		end
	end
	return set
end

local function GetBrac(str)
	return str and str:sub(2,-2) or "void"
end

local function GetParams(str)
	local set = {}
	if str then
		str = str:sub(2,-2)
		for a in str:gmatch("[^,]+") do
			local type = a:match("^%s*(.+)%s*$")
			table.insert(set,type)
		end
	end
	return set
end

local function p(class,tree)
	local status,name = class:match("%"..BEGIN_CLASS.."%s*(["..CLASS_PREFIX.."]*)(.-)%s*[%"..CLASS_POSTFIX.."]")
	class = class:gsub("^%"..BEGIN_CLASS..".-[%"..CLASS_POSTFIX.."]","")	-- purge opening
	class = class:gsub(";%"..END_CLASS.."$","")		-- purge closing
	class = class:gsub("%b"..CLASS_ENCLOSE,"")		-- purge derived types
	local out = {
		methods			= {};
		properties		= {};
		events			= {};
		callbacks		= {};
--		yields			= {};
		subclasses		= {};
	}
	if status:match("?") then	-- enum
		out.type = "enum"
		out.items = {};
	else						-- object
		out.type = "object"
	end
	for block in class:gmatch("[^"..BLOCK.."]+") do
		local status,type,member = block:match("(["..MEMBER_PREFIX.."]*)(%W+)(.*)")
		if type == METHOD then
			local arguments = member:match("%b"..IN_ENCLOSE)
			local returns = member:match("%b"..OUT_ENCLOSE)
			local name = (arguments or returns) and member:match("^(.-)%s-["..BEGIN_PREFIX.."]") or member:match("(.-)%s*$")
			local set = GetMemberSet(name,status)
			set.arguments = GetArgs(arguments)
			set.returns = GetBrac(returns)
			table.insert(out.methods,set)
		elseif type == PROPERTY then
			local type = member:match("%b"..OUT_ENCLOSE)
			local name = type and member:match("^(.-)%s-"..BEGIN_OUT) or member:match("(.-)%s*$")
			local set = GetMemberSet(name,status)
			set.type = GetBrac(type)
			table.insert(out.properties,set)
		elseif type == EVENT then
			local parameters = member:match("%b"..IN_ENCLOSE)
			local name = parameters and member:match("^(.-)%s-%"..BEGIN_IN) or member:match("(.-)%s*$")
			local set = GetMemberSet(name,status)
			set.parameters = GetParams(parameters)
			table.insert(out.events,set)
		elseif type == CALLBACK then
			local parameters = member:match("%b"..IN_ENCLOSE)
			local returns = member:match("%b"..OUT_ENCLOSE)
			local name = (parameters or returns) and member:match("^(.-)%s-["..BEGIN_PREFIX.."]") or member:match("(.-)%s*$")
			local set = GetMemberSet(name,status)
			set.parameters = GetParams(parameters)
			set.returns = GetBrac(returns)
			table.insert(out.callbacks,set)
		elseif type == YIELD then
			-- I don't know what these are
		elseif type == ENUM then
			local num,name = member:match("(%d+)%s+(.*)")
			out.items[tonumber(num) or num] = name
		end
	end
	out.preliminary		= status:match(PRELIMINARY) and true or false
	out.deprecated		= status:match(DEPRECATED) and true or false
	out.name			= name
	table.insert(tree,out)
	return out
end

local function r(str,tree)
	local _,n = 0,0
	while true do
		local class = str:match("%b"..CLASS_ENCLOSE,n+1)
		_,n = str:find("%b"..CLASS_ENCLOSE,n+1)
		if class then
			local child = p(class,tree)
			if child then
				r(class:sub(2,-1),child.subclasses)
			end
		else
			break
		end
	end
	return tree
end

local function raw(str)
	local out = ""
	for block in str:gmatch("[^\r\n"..BLOCK.."]+") do	-- separate by line or block
		block = block:gsub(COMMENT..".-$","")		-- purge comments
		block = block:gsub("\t","")			-- purge tabs
		if #block > 0 then out = out .. block .. BLOCK end
	end
	return out
end

function _G.ParseTree(file_name)
	local f=io.open(file_name,"r")
	local source=f:read("*a")
	f:close()
	f = nil
	return r(raw(source),{})
end

Constructor

  • Save as "ConstructTree.lua"
  • require "ConstructTree"</syntaxhighlight>

Does not handle errors or bad syntax

local COMMENT		= "'"
local BEGIN_CLASS	= "["
local END_CLASS		= "]"
local BEGIN_IN		= "("
local END_IN		= ")"
local BEGIN_OUT		= "{"
local END_OUT		= "}"
local METHOD		= "$"
local PROPERTY		= "#"
local EVENT		= "@"
local CALLBACK		= "&"
local YIELD		= "^"
local ENUM		= "?"
local PRELIMINARY	= "!"
local DEPRECATED	= "~"
local PROTECTED		= "*"
local LOCKED		= "%"
local BLOCK		= ";"

function count(t)
	local c = 0
	for _ in pairs(t) do
		c = c + 1
	end
	return c
end

function contents(c)
	local n = 
		count(c.methods)
		+ count(c.properties)
		+ count(c.callbacks)
		+ count(c.events)
		+ count(c.subclasses)
		+ (c.type == "enum" and count(c.items) or 0)
	return n > 0
end

local tab = 0
function r(class)
	local out = ""
	out = out .. string.rep("\t",tab) .. BEGIN_CLASS .. " "
	out = out .. (class.preliminary and PRELIMINARY or "")
	out = out .. (class.deprecated and DEPRECATED or "")
	out = out .. (class.type == "enum" and ENUM or "") .. class.name
	if contents(class) then
		out = out .. "\n"
		tab = tab + 1
		if class.type == "enum" then
			local ordered = {}
			for n in pairs(class.items) do
				table.insert(ordered,n)
			end
			table.sort(ordered)
			for _,n in pairs(ordered) do
				out = out .. string.rep("\t",tab) .. ENUM..n.." "..class.items[n] .. "\n"
			end
		end
		for n,method in pairs(class.methods) do
			out = out .. string.rep("\t",tab)
			out = out .. (method.preliminary and PRELIMINARY or "")
			out = out .. (method.deprecated and DEPRECATED or "")
			if method.protected then
				out = out .. PROTECTED
			elseif method.locked then
				out = out .. LOCKED
			end
			out = out .. METHOD .. method.name
			if #method.arguments > 0 then
				local args = " " .. BEGIN_IN
				for i,arg in pairs(method.arguments) do
					args = args .. arg.type .. (arg.default and (" = " .. arg.default) or "") .. ", "
				end
				args = args:sub(1,-3) .. END_IN
				out = out .. args
			end
			if method.returns ~= "void" then
				out = out .. " " .. BEGIN_OUT .. method.returns .. END_OUT
			end
			out = out .. "\n"
		end
		for n,property in pairs(class.properties) do
			out = out .. string.rep("\t",tab)
			out = out .. (property.preliminary and PRELIMINARY or "")
			out = out .. (property.deprecated and DEPRECATED or "")
			if property.protected then
				out = out .. PROTECTED
			elseif property.locked then
				out = out .. LOCKED
			end
			out = out .. PROPERTY .. property.name
			if property.type ~= "void" then
				out = out .. " " .. BEGIN_OUT .. property.type .. END_OUT
			end
			out = out .. "\n"
		end
		for n,callback in pairs(class.callbacks) do
			out = out .. string.rep("\t",tab)
			out = out .. (callback.preliminary and PRELIMINARY or "")
			out = out .. (callback.deprecated and DEPRECATED or "")
			if callback.protected then
				out = out .. PROTECTED
			elseif callback.locked then
				out = out .. LOCKED
			end
			out = out .. CALLBACK .. callback.name
			if #callback.parameters > 0 then
				local params = " " .. BEGIN_IN
				for i,type in pairs(callback.parameters) do
					params = params .. type .. ", "
				end
				params = params:sub(1,-3) .. END_IN
				out = out .. params
			end
			if callback.returns ~= "void" then
				out = out .. " " .. BEGIN_OUT .. callback.returns .. END_OUT
			end
			out = out .. "\n"
		end
		for n,event in pairs(class.events) do
			out = out .. string.rep("\t",tab)
			out = out .. (event.preliminary and PRELIMINARY or "")
			out = out .. (event.deprecated and DEPRECATED or "")
			if event.protected then
				out = out .. PROTECTED
			elseif event.locked then
				out = out .. LOCKED
			end
			out = out .. EVENT .. event.name
			if #event.parameters > 0 then
				local params = " " .. BEGIN_IN
				for i,type in pairs(event.parameters) do
					params = params .. type .. ", "
				end
				params = params:sub(1,-3) .. END_IN
				out = out .. params
			end
			out = out .. "\n"
		end
		for n,sub in pairs(class.subclasses) do
			out = out .. r(sub)
		end
		tab = tab - 1
		out = out .. string.rep("\t",tab)
	else
		out = out .. " "
	end
	out = out .. "]\n"
	return out
end

function _G.ConstructTree(db)
	local out = ""
	for _,class in pairs(db) do
		out = out .. r(class)
	end
	return out
end

Conversion

Tree

[ class
	$method (argument_type, default_type = value) {return_type}
	!$preliminary_method (arg_1, arg_2 = "two", arg_3)
	~$deprecated_method {boolean}
	*$protected_method
	!*$preliminary_protected_method
	~*$deprecated_protected_method
	%$locked_method
	!%$preliminary_locked_method
	~%$deprecated_locked_method
	#property {type}
	!#preliminary_property
	~#deprecated_property
	*#protected_property
	!*#preliminary_protected_property
	~*#deprecated_protected_property
	%#locked_property
	!%#preliminary_locked_property
	~%#deprecated_locked_property
	<callback (parameters) {return_type}
	!<preliminary_callback (param_1, param_2)
	~<deprecated_callback {bool}
	@event (parameters)
	!@preliminary_event
	~@deprecated_event
	*@protected_event
	!*@preliminary_protected_event
	~*@deprecated_protected_event
	%@locked_event
	!%@preliminary_locked_event
	~%@deprecated_locked_event
	[ subclass ]
]
[ !preliminary_class ]
[ ~deprecated_class ]
[ ?enum_1
	?0 enum_item1
	?1 enum_item2
	?2 enum_item3
	$GetEnumItems {table}
]

Table

root = {
    [1] = {
        ["type"]                    = "object";
        ["callbacks"] = {
            [1] = {
                ["protected"]       = false;
                ["name"]            = "callback";
                ["locked"]          = false;
                ["deprecated"]      = false;
                ["returns"]         = "return_type";
                ["preliminary"]     = false;
                ["parameters"] = {
                    [1]             = "parameters";
                };
            };
            [2] = {
                ["protected"]       = false;
                ["name"]            = "preliminary_callback";
                ["locked"]          = false;
                ["deprecated"]      = false;
                ["returns"]         = "void";
                ["preliminary"]     = true;
                ["parameters"] = {
                    [1]             = "param_1";
                    [2]             = "param_2";
                };
            };
            [3] = {
                ["protected"]       = false;
                ["name"]            = "deprecated_callback";
                ["locked"]          = false;
                ["deprecated"]      = true;
                ["returns"]         = "bool";
                ["preliminary"]     = false;
                ["parameters"]      = {};
            };
        };
        ["properties"] = {
            [1] = {
                ["protected"]       = false;
                ["name"]            = "property";
                ["deprecated"]      = false;
                ["type"]            = "type";
                ["preliminary"]     = false;
                ["locked"]          = false;
            };
            [2] = {
                ["protected"]       = false;
                ["name"]            = "preliminary_property";
                ["deprecated"]      = false;
                ["type"]            = "void";
                ["preliminary"]     = true;
                ["locked"]          = false;
            };
            [3] = {
                ["protected"]       = false;
                ["name"]            = "deprecated_property";
                ["deprecated"]      = true;
                ["type"]            = "void";
                ["preliminary"]     = false;
                ["locked"]          = false;
            };
            [4] = {
                ["protected"]       = true;
                ["name"]            = "protected_property";
                ["deprecated"]      = false;
                ["type"]            = "void";
                ["preliminary"]     = false;
                ["locked"]          = false;
            };
            [5] = {
                ["protected"]       = true;
                ["name"]            = "preliminary_protected_property";
                ["deprecated"]      = false;
                ["type"]            = "void";
                ["preliminary"]     = true;
                ["locked"]          = false;
            };
            [6] = {
                ["protected"]       = true;
                ["name"]            = "deprecated_protected_property";
                ["deprecated"]      = true;
                ["type"]            = "void";
                ["preliminary"]     = false;
                ["locked"]          = false;
            };
            [7] = {
                ["protected"]       = false;
                ["name"]            = "locked_property";
                ["deprecated"]      = false;
                ["type"]            = "void";
                ["preliminary"]     = false;
                ["locked"]          = true;
            };
            [8] = {
                ["protected"]       = false;
                ["name"]            = "preliminary_locked_property";
                ["deprecated"]      = false;
                ["type"]            = "void";
                ["preliminary"]     = true;
                ["locked"]          = true;
            };
            [9] = {
                ["protected"]       = false;
                ["name"]            = "deprecated_locked_property";
                ["deprecated"]      = true;
                ["type"]            = "void";
                ["preliminary"]     = false;
                ["locked"]          = true;
            };
        };
        ["preliminary"]             = false;
        ["events"] = {
            [1] = {
                ["protected"]       = false;
                ["name"]            = "event";
                ["deprecated"]      = false;
                ["locked"]          = false;
                ["preliminary"]     = false;
                ["parameters"] = {
                    [1]             = "parameters";
                };
            };
            [2] = {
                ["protected"]       = false;
                ["name"]            = "preliminary_event";
                ["deprecated"]      = false;
                ["locked"]          = false;
                ["preliminary"]     = true;
                ["parameters"]      = {};
            };
            [3] = {
                ["protected"]       = false;
                ["name"]            = "deprecated_event";
                ["deprecated"]      = true;
                ["locked"]          = false;
                ["preliminary"]     = false;
                ["parameters"]      = {};
            };
            [4] = {
                ["protected"]       = true;
                ["name"]            = "protected_event";
                ["deprecated"]      = false;
                ["locked"]          = false;
                ["preliminary"]     = false;
                ["parameters"]      = {};
            };
            [5] = {
                ["protected"]       = true;
                ["name"]            = "preliminary_protected_event";
                ["deprecated"]      = false;
                ["locked"]          = false;
                ["preliminary"]     = true;
                ["parameters"]      = {};
            };
            [6] = {
                ["protected"]       = true;
                ["name"]            = "deprecated_protected_event";
                ["deprecated"]      = true;
                ["locked"]          = false;
                ["preliminary"]     = false;
                ["parameters"]      = {};
            };
            [7] = {
                ["protected"]       = false;
                ["name"]            = "locked_event";
                ["deprecated"]      = false;
                ["locked"]          = true;
                ["preliminary"]     = false;
                ["parameters"]      = {};
            };
            [8] = {
                ["protected"]       = false;
                ["name"]            = "preliminary_locked_event";
                ["deprecated"]      = false;
                ["locked"]          = true;
                ["preliminary"]     = true;
                ["parameters"]      = {};
            };
            [9] = {
                ["protected"]       = false;
                ["name"]            = "deprecated_locked_event";
                ["deprecated"]      = true;
                ["locked"]          = true;
                ["preliminary"]     = false;
                ["parameters"]      = {};
            };
        };
        ["name"]                    = "class";
        ["deprecated"]              = false;
        ["subclasses"] = {
            [1] = {
                ["type"]            = "object";
                ["callbacks"]       = {};
                ["properties"]      = {};
                ["preliminary"]     = false;
                ["events"]          = {};
                ["name"]            = "subclass";
                ["deprecated"]      = false;
                ["subclasses"]      = {};
                ["methods"]         = {};
            };
        };
        ["methods"] = {
            [1] = {
                ["protected"]       = false;
                ["name"]            = "method";
                ["arguments"] = {
                    [1] = {
                        ["type"]    = "argument_type";
                    };
                    [2] = {
                        ["default"] = "value";
                        ["type"]    = "default_type";
                    };
                };
                ["deprecated"]      = false;
                ["returns"]         = "return_type";
                ["preliminary"]     = false;
                ["locked"]          = false;
            };
            [2] = {
                ["protected"]       = false;
                ["name"]            = "preliminary_method";
                ["arguments"] = {
                    [1] = {
                        ["type"]    = "arg_1";
                    };
                    [2] = {
                        ["default"] = "\"two\"";
                        ["type"]    = "arg_2";
                    };
                    [3] = {
                        ["type"]    = "arg_3";
                    };
                };
                ["deprecated"]      = false;
                ["returns"]         = "void";
                ["preliminary"]     = true;
                ["locked"]          = false;
            };
            [3] = {
                ["protected"]       = false;
                ["name"]            = "deprecated_method";
                ["arguments"]       = {};
                ["deprecated"]      = true;
                ["returns"]         = "boolean";
                ["preliminary"]     = false;
                ["locked"]          = false;
            };
            [4] = {
                ["protected"]       = true;
                ["name"]            = "protected_method";
                ["arguments"]       = {};
                ["deprecated"]      = false;
                ["returns"]         = "void";
                ["preliminary"]     = false;
                ["locked"]          = false;
            };
            [5] = {
                ["protected"]       = true;
                ["name"]            = "preliminary_protected_method";
                ["arguments"]       = {};
                ["deprecated"]      = false;
                ["returns"]         = "void";
                ["preliminary"]     = true;
                ["locked"]          = false;
            };
            [6] = {
                ["protected"]       = true;
                ["name"]            = "deprecated_protected_method";
                ["arguments"]       = {};
                ["deprecated"]      = true;
                ["returns"]         = "void";
                ["preliminary"]     = false;
                ["locked"]          = false;
            };
            [7] = {
                ["protected"]       = false;
                ["name"]            = "locked_method";
                ["arguments"]       = {};
                ["deprecated"]      = false;
                ["returns"]         = "void";
                ["preliminary"]     = false;
                ["locked"]          = true;
            };
            [8] = {
                ["protected"]       = false;
                ["name"]            = "preliminary_locked_method";
                ["arguments"]       = {};
                ["deprecated"]      = false;
                ["returns"]         = "void";
                ["preliminary"]     = true;
                ["locked"]          = true;
            };
            [9] = {
                ["protected"]       = false;
                ["name"]            = "deprecated_locked_method";
                ["arguments"]       = {};
                ["deprecated"]      = true;
                ["returns"]         = "void";
                ["preliminary"]     = false;
                ["locked"]          = true;
            };
        };
    };
    [2] = {
        ["type"]                    = "object";
        ["callbacks"]               = {};
        ["properties"]              = {};
        ["preliminary"]             = true;
        ["events"]                  = {};
        ["name"]                    = "preliminary_class";
        ["deprecated"]              = false;
        ["subclasses"]              = {};
        ["methods"]                 = {};
    };
    [3] = {
        ["type"]                    = "object";
        ["callbacks"]               = {};
        ["properties"]              = {};
        ["preliminary"]             = false;
        ["events"]                  = {};
        ["name"]                    = "deprecated_class";
        ["deprecated"]              = true;
        ["subclasses"]              = {};
        ["methods"]                 = {};
    };
    [4] = {
        ["type"]                    = "enum";
        ["callbacks"]               = {};
        ["properties"]              = {};
        ["preliminary"]             = false;
        ["items"] = {
            [1]                     = "enum_item2";
            [2]                     = "enum_item3";
            [0]                     = "enum_item1";
        };
        ["events"]                  = {};
        ["name"]                    = "enum_1";
        ["deprecated"]              = false;
        ["subclasses"]              = {};
        ["methods"] = {
            [1] = {
                ["protected"]       = false;
                ["name"]            = "GetEnumItems";
                ["arguments"]       = {};
                ["deprecated"]      = false;
                ["returns"]         = "table";
                ["preliminary"]     = false;
                ["locked"]          = false;
            };
        };
    };
};