From d492dc5e0ff0949cb2b457aa73c7b41cc239b08f Mon Sep 17 00:00:00 2001 From: mpeterv Date: Sat, 18 Jan 2014 13:12:56 +0400 Subject: [PATCH] Finished working on new interface and stuff --- rockspecs/argparse-git-1.rockspec | 4 +- spec/arguments_spec.lua | 18 +- spec/options_spec.lua | 29 +- spec/utils_spec.lua | 39 --- src/argparse.lua | 491 +++++++++++++++--------------- src/interface.lua | 101 ------ src/interface_test.lua | 39 --- src/state.lua | 202 ------------ src/utils.lua | 31 -- 9 files changed, 264 insertions(+), 690 deletions(-) delete mode 100644 spec/utils_spec.lua delete mode 100644 src/interface.lua delete mode 100644 src/interface_test.lua delete mode 100644 src/state.lua delete mode 100644 src/utils.lua diff --git a/rockspecs/argparse-git-1.rockspec b/rockspecs/argparse-git-1.rockspec index 016b525..5437a5e 100644 --- a/rockspecs/argparse-git-1.rockspec +++ b/rockspecs/argparse-git-1.rockspec @@ -16,8 +16,6 @@ dependencies = { build = { type = "builtin", modules = { - argparse = "src/argparse.lua", - ["argparse.state"] = "src/state.lua", - ["argparse.utils"] = "src/utils.lua" + argparse = "src/argparse.lua" } } diff --git a/spec/arguments_spec.lua b/spec/arguments_spec.lua index 52acc47..de052f8 100644 --- a/spec/arguments_spec.lua +++ b/spec/arguments_spec.lua @@ -77,16 +77,6 @@ describe("tests related to positional arguments", function() end) describe("passing incorrect arguments", function() - local old_parser = argparse.parser - - setup(function() - argparse.parser = old_parser:extends() - function argparse.parser:error(fmt, ...) - error(fmt:format(...)) - end - end) - - it("handles extra arguments with empty parser correctly", function() local parser = argparse.parser() @@ -132,17 +122,17 @@ describe("tests related to positional arguments", function() it("handles too few arguments with multi-argument correctly", function() local parser = argparse.parser() - parser:argument("foo", { + parser:argument "foo" { args = "+" - }) + } assert.has_error(curry(parser.parse, parser, {}), "too few arguments") end) it("handles too many arguments with multi-argument correctly", function() local parser = argparse.parser() - parser:argument("foo", { + parser:argument "foo" { args = "2-4" - }) + } assert.has_error(curry(parser.parse, parser, {"foo", "bar", "baz", "qu", "quu"}), "too many arguments") end) diff --git a/spec/options_spec.lua b/spec/options_spec.lua index b225131..82e6679 100644 --- a/spec/options_spec.lua +++ b/spec/options_spec.lua @@ -151,16 +151,6 @@ describe("tests related to options", function() assert.same(args, {exclude = {{"Alice", "Bob"}, {"Emma", "Jacob"}}}) end) - it("handles multi-count option with optional argument correctly", function() - local parser = argparse.parser() - parser:option("-w", "--why", "--why-would-someone-use-this", { - count = "*", - args = "?" - }) - local args = parser:parse({"-w", "-wfoo", "--why=because", "-ww"}) - assert.same(args, {why = {{}, {"foo"}, {"because"}, {}, {}}}) - end) - it("handles multi-count flag correctly", function() local parser = argparse.parser() parser:flag("-q", "--quiet", { @@ -191,15 +181,6 @@ describe("tests related to options", function() end) describe("passing incorrect options", function() - local old_parser = argparse.parser - - setup(function() - argparse.parser = old_parser:extends() - function argparse.parser:error(fmt, ...) - error(fmt:format(...)) - end - end) - it("handles lack of required argument correctly", function() local parser = argparse.parser() parser:option("-s", "--server") @@ -222,9 +203,17 @@ describe("tests related to options", function() local parser = argparse.parser() parser:flag("-q", "--quiet", { count = 1, - no_overwrite = true + overwrite = false }) assert.has_error(curry(parser.parse, parser, {"-qq"}), "option -q must be used at most 1 times") end) + + it("handles too few invocations correctly", function() + local parser = argparse.parser() + parser:option("-f", "--foo", { + count = "3-4" + }) + assert.has_error(curry(parser.parse, parser, {"-fFOO", "-fBAR"}), "option -f must be used at least 3 times") + end) end) end) diff --git a/spec/utils_spec.lua b/spec/utils_spec.lua deleted file mode 100644 index bb70de7..0000000 --- a/spec/utils_spec.lua +++ /dev/null @@ -1,39 +0,0 @@ -local utils = require "argparse.utils" - -describe("tests related to utils.parse_boundaries", function() - it("handles * correctly", function() - local min, max = utils.parse_boundaries("*") - assert.equal(min, 0) - assert.equal(max, math.huge) - end) - - it("handles + correctly", function() - local min, max = utils.parse_boundaries("+") - assert.equal(min, 1) - assert.equal(max, math.huge) - end) - - it("handles ? correctly", function() - local min, max = utils.parse_boundaries("?") - assert.equal(min, 0) - assert.equal(max, 1) - end) - - it("handles numbers correctly", function() - local min, max = utils.parse_boundaries(42) - assert.equal(min, 42) - assert.equal(max, 42) - end) - - it("handles numbers+ correctly", function() - local min, max = utils.parse_boundaries("42+") - assert.equal(min, 42) - assert.equal(max, math.huge) - end) - - it("handles ranges correctly", function() - local min, max = utils.parse_boundaries("42-96") - assert.equal(min, 42) - assert.equal(max, 96) - end) -end) diff --git a/src/argparse.lua b/src/argparse.lua index d447a60..42c8616 100644 --- a/src/argparse.lua +++ b/src/argparse.lua @@ -2,203 +2,10 @@ local argparse = {} local class = require "30log" -function State:invoke(element) - if not self.invocatons then - - -function State:push(option) - if self.top_is_opt then - self:pop() - end - - self:invoke(option) - - if option.maxargs ~= 0 then - table.insert(self.stack, option) - self.top_is_opt = true - end -end - -function State:pop() - if self.top_is_opt - - -function State:handle_option(name) - local option = self:_assert(self.context[name], "unknown option %s", name) - - self:_open(option) -end - -function State:handle_argument(data) - if self._current then - if self:_can_pass(self._current) then - self:_pass(self._current, data) - return - else - self._current = nil - end - end - - local argument = self._arguments[self._next_arg_i] - if argument then - self:_open(argument) - self:_pass(argument, data) - else - local command = self.context[data] - if command and command.type == "command" then - self._result[command.target] = {{}} - self:_switch(command) - else - if #self._commands > 0 then - self:_error("unknown command %s", data) - else - self:_error("too many arguments") - end - end - end -end - -function State:get_result() - self:_check() - - local result = {} - - local invocations - for _, element in ipairs(self._all_elements) do - invocations = self._result[element.target] - - if element.maxcount == 1 then - if element.maxargs == 0 then - if #invocations > 0 then - result[element.target] = true - end - elseif element.maxargs == 1 and element.minargs == 1 then - if #invocations > 0 then - result[element.target] = invocations[1][1] - end - else - result[element.target] = invocations[1] - end - else - if element.maxargs == 0 then - result[element.target] = #invocations - elseif element.maxargs == 1 and element.minargs == 1 then - local new_result = {} - for i, passed in ipairs(invocations) do - new_result[i] = passed[1] - end - result[element.target] = new_result - else - result[element.target] = invocations - end - end - end - - return result -end - -function State:_check() - self:_assert(not self._parser.must_command, "a command is required") - - local invocations - for _, element in ipairs(self._all_elements) do - invocations = self._result[element.target] or {} - - if element.type == "argument" and #invocations == 0 then - invocations[1] = {} - end - - if #invocations > element.maxcount then - if element.no_overwrite then - self:_error("option %s must be used at most %d times", element.name, element.maxcount) - else - local new_invocations = {} - for i = 1, element.maxcount do - new_invocations[i] = invocations[#invocations-element.maxcount+i] - end - invocations = new_invocations - end - end - - self:_assert(#invocations >= element.mincount, "option %s must be used at least %d times", element.name, element.mincount) - - for _, passed in ipairs(invocations) do - self:_assert(#passed <= element.maxargs, "too many arguments") - if #passed < element.minargs then - if element.default then - for i = 1, element.minargs-#passed do - table.insert(passed, element.default) - end - else - self:_error("too few arguments") - end - end - end - - self._result[element.target] = invocations - end - - for _, group in ipairs(self._all_groups) do - local invoked - for _, element in ipairs(group.elements) do - if #self._result[element.target] > 0 then - if invoked then - self:_error("%s can not be used together with %s", invoked.name, element.name) - else - invoked = element - end - end - end - - if group.required then - self:_assert(invoked, "WIP(required mutually exclusive group)") - end - end -end - -function State:_open(element) - if not self._result[element.target] then - self._result[element.target] = {} - end - - table.insert(self._result[element.target], {}) - - if element.type == "argument" then - self._next_arg_i = self._next_arg_i+1 - end - - self._current = element -end - -function State:_can_pass(element) - local invocations = self._result[element.target] - local passed = invocations[#invocations] - - return #passed < element.maxargs -end - -function State:_pass(element, data) - local invocations = self._result[element.target] - local passed = invocations[#invocations] - - table.insert(passed, data) -end - -function State:_error(...) - return self._parser:error(...) -end - -function State:_assert(...) - return self._parser:assert(...) -end - - -local utils = require "argparse.utils" - local Declarative = {} function Declarative:__init(...) - return self(...) + self(...) end function Declarative:__call(...) @@ -228,6 +35,7 @@ function Declarative:__call(...) end local Parser = class { + __name = "Parser", arguments = {}, options = {}, commands = {}, @@ -235,54 +43,72 @@ local Parser = class { }:include(Declarative) local Command = Parser:extends { + __name = "Command", aliases = {} }:include(Declarative) local Argument = class { + __name = "Argument", args = 1, count = 1, - fields = {"name", "description", "target", "args", "default", "convert"} + fields = { + "name", "description", "target", "args", + "minargs", "maxargs", "default", "convert" + } }:include(Declarative) local Option = class { + __name = "Option", aliases = {}, args = 1, count = "?", - fields = {"name", "aliases", "description", "target", "args", "count", "default", "convert"} + overwrite = true, + fields = { + "name", "aliases", "description", "target", + "args", "minargs", "maxargs", "count", + "mincount", "maxcount", "default", "convert", + "overwrite" + } }:include(Declarative) local Flag = Option:extends { + __name = "Flag", args = 0 }:include(Declarative) function Parser:argument(...) - local argument = Argument(...) + local argument = Argument:new(...) table.insert(self.arguments, argument) return argument end function Parser:option(...) - local option = Option(...) + local option = Option:new(...) table.insert(self.options, option) return option end function Parser:flag(...) - local flag = Flag(...) + local flag = Flag:new(...) table.insert(self.options, flag) return flag end function Parser:command(...) - local command = Command(...) + local command = Command:new(...) table.insert(self.commands, command) return command end function Parser:error(fmt, ...) local msg = fmt:format(...) - io.stderr:write("Error: " .. msg .. "\n") - os.exit(1) + + if _TEST then + error(msg) + else + io.stderr:write("Error: " .. msg .. "\r\n") + os.exit(1) + end end function Parser:assert(assertion, ...) @@ -291,7 +117,7 @@ end function Parser:make_charset() if not self.charset then - self.charset = {} + self.charset = {["-"] = true} for _, command in ipairs(self.commands) do command:make_charset() @@ -332,7 +158,49 @@ function Parser:make_targets() end end -function self:make_command_names() +local function parse_boundaries(boundaries) + if tonumber(boundaries) then + return tonumber(boundaries), tonumber(boundaries) + end + + if boundaries == "*" then + return 0, math.huge + end + + if boundaries == "+" then + return 1, math.huge + end + + if boundaries == "?" then + return 0, 1 + end + + if boundaries:match "^%d+%-%d+$" then + local min, max = boundaries:match "^(%d+)%-(%d+)$" + return tonumber(min), tonumber(max) + end + + if boundaries:match "^%d+%+$" then + local min = boundaries:match "^(%d+)%+$" + return tonumber(min), math.huge + end +end + +function Parser:make_boundaries() + for _, elements in ipairs{self.arguments, self.options} do + for _, element in ipairs(elements) do + if not element.minargs or not element.maxargs then + element.minargs, element.maxargs = parse_boundaries(element.args) + end + + if not element.mincount or not element.maxcount then + element.mincount, element.maxcount = parse_boundaries(element.count) + end + end + end +end + +function Parser:make_command_names() for _, command in ipairs(self.commands) do command.name = self.name .. " " .. command.name end @@ -341,6 +209,7 @@ end function Parser:prepare() self:make_charset() self:make_targets() + self:make_boundaries() self:make_command_names() return self end @@ -353,9 +222,60 @@ function Parser:parse(args) local charset local options = {} local arguments, commands - local opt_context= {} + local opt_context = {} local com_context local result = {} + local cur_option, cur_arg_i, cur_arg + + local function close(element) + local invocations = result[element.target] + local passed = invocations[#invocations] + + if #passed < element.minargs then + if element.default then + while #passed < element.minargs do + table.insert(passed, element.default) + end + else + parser:error("too few arguments") + end + end + + if element == cur_option then + cur_option = nil + elseif element == cur_arg then + cur_arg_i = cur_arg_i+1 + cur_arg = arguments[cur_arg_i] + end + end + + local function invoke(element) + local invocations = result[element.target] + + if #invocations == element.maxcount then + if element.overwrite then + table.remove(invocations, 1) + else + parser:error("option %s must be used at most %d times", element.name, element.maxcount) + end + end + + table.insert(result[element.target], {}) + + if element.maxargs == 0 then + close(element) + end + end + + local function pass(element, data) + local invocations = result[element.target] + local passed = invocations[#invocations] + table.insert(passed, data) + + if #passed == element.maxargs then + close(element) + end + end local function switch(p) parser = p:prepare() @@ -367,9 +287,19 @@ function Parser:parse(args) for _, alias in ipairs(option.aliases) do opt_context[alias] = option end + + result[option.target] = {} end arguments = p.arguments + cur_arg_i = 1 + cur_arg = arguments[cur_arg_i] + + for _, argument in ipairs(arguments) do + result[argument.target] = {} + invoke(argument) + end + commands = p.commands com_context = {} @@ -381,65 +311,144 @@ function Parser:parse(args) end local function handle_argument(data) + if cur_option then + pass(cur_option, data) + elseif cur_arg then + pass(cur_arg, data) + else + local com = com_context[data] + if not com then + if #commands > 0 then + parser:error("wrong command") -- add lev-based guessing here + else + parser:error("too many arguments") + end + else + result[com.target] = true + switch(com) + end + end end local function handle_option(data) + if cur_option then + close(cur_option) + end + cur_option = opt_context[data] + invoke(cur_option) end - local handle_options = true + local function mainloop() + local handle_options = true - for _, data in ipairs(args) do - local plain = true - local first, name, option + for _, data in ipairs(args) do + local plain = true + local first, name, option - if handle_options then - first = data:sub(1, 1) - if self.charset[first] then - if #data > 1 then - if data:sub(2, 2):match "[a-zA-Z]" then - plain = false + if handle_options then + first = data:sub(1, 1) + if charset[first] then + if #data > 1 then + if data:sub(2, 2):match "[a-zA-Z]" then + plain = false - for i = 2, #data do - name = first .. data:sub(i, i) - option = self:assert(self.opt_context[name], "unknown option " .. name) - handle_option(name) + for i = 2, #data do + name = first .. data:sub(i, i) + option = parser:assert(opt_context[name], "unknown option " .. name) + handle_option(name) - if i ~= #data and not (options.minargs == 0 and self.opt_context[first .. data:sub(i+1, i+1)]) then - handle_argument(data:sub(i+1)) - break + if i ~= #data and option.minargs > 0 then + handle_argument(data:sub(i+1)) + break + end end - end - elseif data:sub(2, 2) == first then - if #data == 2 then - plain = false - handle_options = false - elseif data:sub(3, 3):match "[a-zA-Z]" then - plain = false + elseif data:sub(2, 2) == first then + if #data == 2 then + plain = false + handle_options = false + elseif data:sub(3, 3):match "[a-zA-Z]" then + plain = false - local equal = data:find "=" - if equal then - name = data:sub(1, equal-1) - option = self:assert(self.opt_context[name], "unknown option " .. name) - self:assert(option.maxargs > 0, "option " .. name .. " doesn't take arguments") + local equal = data:find "=" + if equal then + name = data:sub(1, equal-1) + option = parser:assert(opt_context[name], "unknown option " .. name) + parser:assert(option.maxargs > 0, "option " .. name .. " doesn't take arguments") - handle_option(data:sub(1, equal-1)) - handle_argument(data:sub(equal+1)) - else - handle_option(data) + handle_option(data:sub(1, equal-1)) + handle_argument(data:sub(equal+1)) + else + handle_option(data) + end end end end end end - end - if plain then - handle_argument(data) + if plain then + handle_argument(data) + end end end + local function format() + local new_result = {} + local invocations + + for _, elements in ipairs{options, arguments} do + for _, element in ipairs(elements) do + invocations = result[element.target] + + parser:assert(#invocations >= element.mincount, + "option %s must be used at least %d times", element.name, element.mincount) + + if element.maxcount == 1 then + if element.maxargs == 0 then + if #invocations > 0 then + new_result[element.target] = true + end + elseif element.maxargs == 1 and element.minargs == 1 then + if #invocations > 0 then + new_result[element.target] = invocations[1][1] + end + else + new_result[element.target] = invocations[1] + end + else + if element.maxargs == 0 then + new_result[element.target] = #invocations + elseif element.maxargs == 1 and element.minargs == 1 then + new_result[element.target] = {} + + for _, passed in ipairs(invocations) do + table.insert(new_result[element.target], passed[1]) + end + else + new_result[element.target] = invocations + end + end + end + end + + result = new_result + end + + switch(self) + mainloop() + + if cur_option then + close(cur_option) + end + + while cur_arg do + close(cur_arg) + end + + format() + return result end diff --git a/src/interface.lua b/src/interface.lua deleted file mode 100644 index 98322f0..0000000 --- a/src/interface.lua +++ /dev/null @@ -1,101 +0,0 @@ --- new, awesome declarative interface implementation - -local class = require "30log" - -local Declarative = class() - -function Declarative:__init(...) - return self(...) -end - -function Declarative:__call(...) - local name_or_options - - for i=1, select("#", ...) do - name_or_options = select(i, ...) - - if type(name_or_options) == "string" then - self:set_name(name_or_options) - elseif type(name_or_options) == "table" then - for _, field in ipairs(self.fields) do - if name_or_options[field] ~= nil then - self[field] = name_or_options[field] - end - end - end - end - - return self -end - -local Aliased = {} - -function Aliased:set_name(name) - table.insert(self.aliases, name) - - if not self.name then - self.name = name - end -end - -local Named = {} - -function Named:set_name(name) - self.name = name -end - -local Parser = class { - arguments = {}, - options = {}, - commands = {}, - groups = {}, - mutex_groups = {}, - fields = {"name", "description", "target"} -}:include(Declarative):include(Named) - -local Command = Parser:extends { - aliases = {} -}:include(Declarative):include(Aliased) - -local Argument = class { - args = 1, - count = 1, - fields = {"name", "description", "target", "args", "default", "convert"} -}:include(Declarative):include(Named) - -local Option = class { - aliases = {}, - args = 1, - count = "?", - fields = {"name", "aliases", "description", "target", "args", "count", "default", "convert"} -}:include(Declarative):include(Aliased) - -local Flag = Option:extends { - args = 0 -}:include(Declarative):include(Aliased) - -function Parser:argument(...) - local argument = Argument(...) - table.insert(self.arguments, argument) - return argument -end - -function Parser:option(...) - local option = Option(...) - table.insert(self.options, option) - return option -end - -function Parser:flag(...) - local flag = Flag(...) - table.insert(self.options, flag) - return flag -end - -function Parser:command(...) - local command = Command(...) - table.insert(self.commands, command) - return command -end - -return Parser diff --git a/src/interface_test.lua b/src/interface_test.lua deleted file mode 100644 index b56dd29..0000000 --- a/src/interface_test.lua +++ /dev/null @@ -1,39 +0,0 @@ ---Just some testing - -local MetaParser = require "interface" - -local parser = MetaParser "luarocks" { - description = "a module deployment system for Lua" -} - -parser:option "--server" "-s" { - description = "Fetch rocks/rockspecs from this server" -} - -parser:flag "--local" "-l" { - description = "Use the tree in the user's home directory." -} - -local install = parser:command "install" "i" - -install:argument "rock" - -install:argument "version" { - args = "?" -} - -assert(parser.description == "a module deployment system for Lua") -assert(parser.options[1].name == "--server") -assert(parser.options[1].aliases[1] == "--server") -assert(parser.options[1].aliases[2] == "-s") -assert(parser.options[1].description == "Fetch rocks/rockspecs from this server") -assert(parser.options[1].args == 1) -assert(parser.options[1].count == "?") -assert(parser.options[2].name == "--local") -assert(parser.options[2].args == 0) -assert(parser.commands[1] == install) -assert(install.arguments[1].name == "rock") -assert(install.aliases[2] == "i") -assert(install.arguments[2].name == "version") -assert(install.arguments[2].count == 1) -assert(install.arguments[2].args == "?") diff --git a/src/state.lua b/src/state.lua deleted file mode 100644 index 4f0f9ff..0000000 --- a/src/state.lua +++ /dev/null @@ -1,202 +0,0 @@ -local class = require "30log" - -local State = class { - context = {} -} - -function State:__init(parser) - self.context = {} - self._all_elements = {} - self._all_groups = {} - self:_switch(parser) - - self._result = {} -end - -function State:handle_option(name) - local option = self:_assert(self.context[name], "unknown option %s", name) - - self:_open(option) -end - -function State:handle_argument(data) - if self._current then - if self:_can_pass(self._current) then - self:_pass(self._current, data) - return - else - self._current = nil - end - end - - local argument = self._arguments[self._next_arg_i] - if argument then - self:_open(argument) - self:_pass(argument, data) - else - local command = self.context[data] - if command and command.type == "command" then - self._result[command.target] = {{}} - self:_switch(command) - else - if #self._commands > 0 then - self:_error("unknown command %s", data) - else - self:_error("too many arguments") - end - end - end -end - -function State:get_result() - self:_check() - - local result = {} - - local invocations - for _, element in ipairs(self._all_elements) do - invocations = self._result[element.target] - - if element.maxcount == 1 then - if element.maxargs == 0 then - if #invocations > 0 then - result[element.target] = true - end - elseif element.maxargs == 1 and element.minargs == 1 then - if #invocations > 0 then - result[element.target] = invocations[1][1] - end - else - result[element.target] = invocations[1] - end - else - if element.maxargs == 0 then - result[element.target] = #invocations - elseif element.maxargs == 1 and element.minargs == 1 then - local new_result = {} - for i, passed in ipairs(invocations) do - new_result[i] = passed[1] - end - result[element.target] = new_result - else - result[element.target] = invocations - end - end - end - - return result -end - -function State:_check() - self:_assert(not self._parser.must_command, "a command is required") - - local invocations - for _, element in ipairs(self._all_elements) do - invocations = self._result[element.target] or {} - - if element.type == "argument" and #invocations == 0 then - invocations[1] = {} - end - - if #invocations > element.maxcount then - if element.no_overwrite then - self:_error("option %s must be used at most %d times", element.name, element.maxcount) - else - local new_invocations = {} - for i = 1, element.maxcount do - new_invocations[i] = invocations[#invocations-element.maxcount+i] - end - invocations = new_invocations - end - end - - self:_assert(#invocations >= element.mincount, "option %s must be used at least %d times", element.name, element.mincount) - - for _, passed in ipairs(invocations) do - self:_assert(#passed <= element.maxargs, "too many arguments") - if #passed < element.minargs then - if element.default then - for i = 1, element.minargs-#passed do - table.insert(passed, element.default) - end - else - self:_error("too few arguments") - end - end - end - - self._result[element.target] = invocations - end - - for _, group in ipairs(self._all_groups) do - local invoked - for _, element in ipairs(group.elements) do - if #self._result[element.target] > 0 then - if invoked then - self:_error("%s can not be used together with %s", invoked.name, element.name) - else - invoked = element - end - end - end - - if group.required then - self:_assert(invoked, "WIP(required mutually exclusive group)") - end - end -end - -function State:_open(element) - if not self._result[element.target] then - self._result[element.target] = {} - end - - table.insert(self._result[element.target], {}) - - if element.type == "argument" then - self._next_arg_i = self._next_arg_i+1 - end - - self._current = element -end - -function State:_can_pass(element) - local invocations = self._result[element.target] - local passed = invocations[#invocations] - - return #passed < element.maxargs -end - -function State:_pass(element, data) - local invocations = self._result[element.target] - local passed = invocations[#invocations] - - table.insert(passed, data) -end - -function State:_switch(command) - self._parser = command - self._arguments = command.arguments - self._commands = command.commands - - for _, element in ipairs(command.elements) do - table.insert(self._all_elements, element) - end - - for _, group in ipairs(command.groups) do - table.insert(self._all_groups, group) - end - - self.context = setmetatable(command.context, {__index = self.context}) - self._next_arg_i = 1 -end - -function State:_error(...) - return self._parser:error(...) -end - -function State:_assert(...) - return self._parser:assert(...) -end - -return State diff --git a/src/utils.lua b/src/utils.lua deleted file mode 100644 index 945bb36..0000000 --- a/src/utils.lua +++ /dev/null @@ -1,31 +0,0 @@ -local utils = {} - -function utils.parse_boundaries(boundaries) - if tonumber(boundaries) then - return tonumber(boundaries), tonumber(boundaries) - end - - if boundaries == "*" then - return 0, math.huge - end - - if boundaries == "+" then - return 1, math.huge - end - - if boundaries == "?" then - return 0, 1 - end - - if boundaries:match "^%d+%-%d+$" then - local min, max = boundaries:match "^(%d+)%-(%d+)$" - return tonumber(min), tonumber(max) - end - - if boundaries:match "^%d+%+$" then - local min = boundaries:match "^(%d+)%+$" - return tonumber(min), math.huge - end -end - -return utils