Tue, 11 Sep 2018 23:24:08 +0100
main: Don't let action timeout fire after a script already finished
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 = 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 local in_header = (next(parsed.objects) == nil) and (next(parsed.actions) == nil); if in_header and #line > 0 then if not parsed.title and not line:match("^#!") then parsed.title = line:gsub("^[#-]+%s*", ""); elseif line:match("^##") then if not parsed.tags then parsed.tags = {}; end local tag = line:gsub("^##%s*", ""); local k, v = tag:match("^([^:]+):%s*(.+)$"); if k then -- Tag format: ## tagkey:tagvalue parsed.tags[k] = v; else -- Tag format: ## tagfoobar parsed.tags[tag] = true; end else parsed.summary = (parsed.summary and parsed.summary.."\n" or "")..line:gsub("^[#-]+%s*", ""); end else -- Save as annotation for the following action if #line == 0 then if annotation then annotation.closed = true; end elseif annotation or not line:match("^%-+$") then if (not annotation) or annotation.closed then annotation = { line }; else table.insert(annotation, line); end 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; };