local lpeg = require "lpeg" local PKGBASE = "pkgbase" local PKGNAME = "pkgname" local modes = { [PKGBASE] = PKGBASE, [PKGNAME] = PKGNAME, } function apply (state, method, ...) if state[method] then return state[method](state, ...) end return nil end local identifier = lpeg.R"az" + lpeg.R"09" + lpeg.S"@+_" identifier = identifier * (identifier + lpeg.S".-")^0 local whitespace = lpeg.S" \t"^0 local newline = lpeg.P"\r\n" + "\n" local rest = (1 - newline)^0 local definition = lpeg.Cc"definition" * whitespace * lpeg.C(identifier) * whitespace * "=" * whitespace * lpeg.C(rest) local comment = lpeg.Cc"comment" * lpeg.P"#" * whitespace * lpeg.C(rest) local empty = lpeg.Cc"empty" * whitespace local invalid = lpeg.Cc"invalid" * lpeg.C(rest) local line = lpeg.Carg(1) * (definition + comment + empty + invalid) / apply * newline local capture = lpeg.Ct(line^0) * -lpeg.P(1) local function srcinfo (text, options) options = options or {} mode = modes[options.mode] or PKGNAME return capture:match( text, nil, { mode = mode, base = nil, current = nil, definition = function (self, name, value) if name == PKGBASE then self.base = {name=value} self.current = self.base if self.mode == PKGBASE then self.base.packages = {} return self.current end elseif name == PKGNAME then self.current = {name=value} if self.mode == PKGNAME then self.current.base = self.base return self.current else table.insert(self.base.packages, self.current) end else local current_value = self.current[name] if type(current_value) == "table" then table.insert(current_value, value) elseif current_value ~= nil then self.current[name] = {current_value, value} else self.current[name] = value end end end, comment = function (self, text) end, empty = function (self) end, invalid = function (self, text) return text end, } ) end return srcinfo