scansion/parser.lua

Tue, 27 Oct 2015 23:08:48 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Tue, 27 Oct 2015 23:08:48 +0000
changeset 44
0dab1dc183c1
parent 43
b37504fa3031
child 47
1cbc0d9d132d
permissions
-rw-r--r--

parser, objects.client: Experimental support for more liberal object names

local function parse(data)
	local parsed = {
		objects = {};
		actions = {};
	};
	
	local line_number = 0;
	local last_object;
	local annotation;
	
	for line in data:gmatch("([^\r\n]*)\r?\n") do
		line_number = line_number + 1;
		if line:sub(1,1) == "[" then
			local obj_type, name, extra = line:match("^%[(%a+)%] (.+)$");
			
			if parsed.objects[name] then
				return nil, "Duplicate definition of "..name.." on line "..line_number;
			end
			parsed.objects[name] = {
				type = obj_type:lower();
				name = name;
				defined_line = line_number;
			};
			last_object = parsed.objects[name];
		elseif line:match("^%s+%a+:.+$") then
			if not last_object then
				return nil, "Line "..line_number.. "unexpected outside of an object definition";
			end
			local k, v = line:match("^%s+(%a+):%s*(.+)$")
			last_object[k] = v;
		elseif #parsed.actions > 0 and line:sub(1,1) == "\t" then
			table.insert(parsed.actions[#parsed.actions].extra, line:sub(2));
		elseif line:match("^%s*$") or line:match("^#") or line:match("^([/-])%1") then
			-- Blank line or comment, save as annotation
			if #line == 0 then
				if annotation then
					annotation.closed = true;
				end
			else
				if (not annotation) or annotation.closed then
					annotation = { line };
				else
					table.insert(annotation, line);
				end
			end
		else
			last_object = nil;
			local name, action, extra = line:match("^([^:]+) (%a+):?%s?(.*)$");
			if not name then
				return nil, "Unable to parse action on line "..line_number;
			end
			if not parsed.objects[name] then
				return nil, "The object '"..name.."' used on line "..line_number.." was not declared";
			end
			table.insert(parsed.actions, {
				object_name = name;
				action = action:lower();
				extra = {#extra>0 and extra or nil};
				annotation = annotation and table.concat(annotation, "\n") or nil;
			});
			annotation = nil;
		end
	end
	return parsed;
end

return {
	parse = parse;
};

mercurial