X-Git-Url: https://plomlompom.com/repos/?a=blobdiff_plain;f=parser.py;h=03b688f24e8eccf18cd1c024e5804ef96e1087d5;hb=b62222032f8fae375b7631832c59e811ac51dbda;hp=38283bba6c164462cee08b0d4176f65ae58110f1;hpb=0d4ba3af892734c4ca9baef16bb3d1847b401542;p=plomrogue2-experiments diff --git a/parser.py b/parser.py index 38283bb..03b688f 100644 --- a/parser.py +++ b/parser.py @@ -1,5 +1,4 @@ import unittest -from functools import partial class ArgError(Exception): @@ -45,27 +44,25 @@ class Parser: return tokens def parse(self, msg): - """Parse msg as call to self.game method, return method with arguments. + """Parse msg as call to function, return function with args tuple. - Respects method signatures defined in methods' .argtypes attributes. + Respects function signature defined in function's .argtypes attribute. """ tokens = self.tokenize(msg) if len(tokens) == 0: - return None - method_candidate = 'cmd_' + tokens[0] - if not hasattr(self.game, method_candidate): - return None - method = getattr(self.game, method_candidate) + return None, () + func, argtypes = self.game.get_command_signature(tokens[0]) + if func is None: + return None, () + if len(argtypes) == 0: + if len(tokens) > 1: + raise ArgError('Command expects no argument(s).') + return func, () if len(tokens) == 1: - if not hasattr(method, 'argtypes'): - return method - else: - raise ArgError('Command expects argument(s).') + raise ArgError('Command expects argument(s).') args_candidates = tokens[1:] - if not hasattr(method, 'argtypes'): - raise ArgError('Command expects no argument(s).') - args, kwargs = self.argsparse(method.argtypes, args_candidates) - return partial(method, *args, **kwargs) + args = self.argsparse(argtypes, args_candidates) + return func, args def parse_yx_tuple(self, yx_string, range_): """Parse yx_string as yx_tuple:nonneg argtype, return result. @@ -93,11 +90,12 @@ class Parser: return (y, x) def argsparse(self, signature, args_tokens): - """Parse into / return args_tokens as args/kwargs defined by signature. + """Parse into / return args_tokens as args defined by signature. Expects signature to be a ' '-delimited sequence of any of the strings 'int:nonneg', 'yx_tuple:nonneg', 'yx_tuple:pos', 'string', - 'seq:int:nonneg', defining the respective argument types. + 'seq:int:nonneg', 'string:' + an option type string accepted by + self.game.get_string_options, defining the respective argument types. """ tmpl_tokens = signature.split() if len(tmpl_tokens) != len(args_tokens): @@ -105,6 +103,7 @@ class Parser: ') not expected number (' + str(len(tmpl_tokens)) + ').') args = [] + string_string = 'string' for i in range(len(tmpl_tokens)): tmpl = tmpl_tokens[i] arg = args_tokens[i] @@ -116,8 +115,6 @@ class Parser: args += [self.parse_yx_tuple(arg, 'nonneg')] elif tmpl == 'yx_tuple:pos': args += [self.parse_yx_tuple(arg, 'pos')] - elif tmpl == 'string': - args += [arg] elif tmpl == 'seq:int:nonneg': sub_tokens = arg.split(',') if len(sub_tokens) < 1: @@ -129,9 +126,22 @@ class Parser: 'non-negative integers.') seq += [int(tok)] args += [seq] + elif tmpl == string_string: + args += [arg] + elif tmpl[:len(string_string) + 1] == string_string + ':': + if not hasattr(self.game, 'get_string_options'): + raise ArgError('No string option directory.') + string_option_type = tmpl[len(string_string) + 1:] + options = self.game.get_string_options(string_option_type) + if options is None: + raise ArgError('Unknown string option type.') + if arg not in options: + msg = 'Argument #%s must be one of: %s' % (i + 1, options) + raise ArgError(msg) + args += [arg] else: raise ArgError('Unknown argument type.') - return args, {} + return args class TestParser(unittest.TestCase):