scansion/parser.lua

Tue, 27 Oct 2015 20:03:32 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Tue, 27 Oct 2015 20:03:32 +0000
changeset 42
67d50889b7fe
parent 19
af311b9827e2
child 43
b37504fa3031
permissions
-rw-r--r--

scansion.parser: Don't skip blank lines (otherwise line numbers get skewed)

local function parse(data)
	local parsed = {
		objects = {};
		actions = {};
	};
	
	local line_number = 0;
	local last_object;
	
	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
		else
			last_object = nil;
			local name, action, extra = line:match("^(%a+) (%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};
			});
		end
	end
	return parsed;
end

return {
	parse = parse;
};

mercurial