diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2013-02-10 00:50:46 +0200 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2013-02-10 00:50:46 +0200 |
commit | 45ecded01d814d0d0bf9b84c0dafa65575ab2bdd (patch) | |
tree | c65e38fb0455cc815ceddbe99f305fb8d0ebe7a8 | |
parent | da2e9f6688ea9545ccc056195ea36421e3e019aa (diff) | |
download | meson-45ecded01d814d0d0bf9b84c0dafa65575ab2bdd.zip meson-45ecded01d814d0d0bf9b84c0dafa65575ab2bdd.tar.gz meson-45ecded01d814d0d0bf9b84c0dafa65575ab2bdd.tar.bz2 |
Started work on keyword arguments.
-rwxr-xr-x | bparser.py | 19 | ||||
-rwxr-xr-x | interpreter.py | 43 | ||||
-rw-r--r-- | nodes.py | 17 | ||||
-rw-r--r-- | test cases/1 trivial/builder.txt | 6 |
4 files changed, 61 insertions, 24 deletions
@@ -42,6 +42,7 @@ tokens = ['LPAREN', 'INT', 'EOL_CONTINUE', 'EOL', + 'COLON', ] + list(reserved.values()) t_ASSIGN = '=' @@ -56,6 +57,7 @@ t_RBRACE = '\}' t_COMMENT = '\#[^\n]*' t_COMMA = ',' t_DOT = '\.' +t_COLON = ':' t_ignore = ' \t' @@ -162,19 +164,32 @@ def p_statement_expression(t): 'statement : expression' t[0] = nodes.statement_from_expression(t[1]) + def p_args_multiple(t): 'args : statement COMMA args' args = t[3] args.prepend(t[1]) t[0] = args -def p_args_single(t): +def p_kwargs_multiple(t): + 'args : expression COLON statement COMMA args' + args = t[5] + args.add_kwarg(t[1], t[3]) + t[0] = args + +def p_args_single_pos(t): 'args : statement' args = nodes.Arguments(t.lineno(1)) args.prepend(t[1]) t[0] = args -def p_args_none(t): +def p_args_single_kw(t): + 'args : expression COLON statement' + a = nodes.Arguments(t.lineno(1)) + a.set_kwarg(t[1], t[2]) + t[0] = a + +def p_posargs_none(t): 'args :' t[0] = nodes.Arguments(t.lineno(0)) diff --git a/interpreter.py b/interpreter.py index 11c11f5..028154d 100755 --- a/interpreter.py +++ b/interpreter.py @@ -465,7 +465,7 @@ class Interpreter(): t = Test(args[0], args[1]) self.build.tests.append(t) print('Adding test "%s"' % args[0]) - + def func_headers(self, node, args): for a in args: if not isinstance(a, str): @@ -534,6 +534,8 @@ class Interpreter(): for a in args: if isinstance(a, list): result = result + self.flatten(a) + if isinstance(a, nodes.StringStatement): + result.append(a.get_value()) else: result.append(a) return result @@ -559,9 +561,9 @@ class Interpreter(): def function_call(self, node): func_name = node.get_function_name() - args = self.reduce_arguments(node.arguments) + (posargs, kwargs) = self.reduce_arguments(node.arguments) if func_name in self.funcs: - return self.funcs[func_name](node, args) + return self.funcs[func_name](node, posargs) else: raise InvalidCode('Unknown function "%s".' % func_name) @@ -587,24 +589,27 @@ class Interpreter(): raise InvalidCode('Line %d: Tried to assign an invalid value to variable.' % node.lineno()) self.set_variable(var_name, value) return value - + + def reduce_single(self, arg): + if isinstance(arg, nodes.AtomExpression) or isinstance(arg, nodes.AtomStatement): + return self.get_variable(arg.value) + elif isinstance(arg, nodes.StringExpression) or isinstance(arg, nodes.StringStatement): + return arg.get_value() + elif isinstance(arg, nodes.FunctionCall): + return self.function_call(arg) + elif isinstance(arg, nodes.MethodCall): + return self.method_call(arg) + else: + raise InvalidCode('Line %d: Irreducible argument.' % args.lineno()) + def reduce_arguments(self, args): assert(isinstance(args, nodes.Arguments)) - reduced = [] - for arg in args.arguments: - if isinstance(arg, nodes.AtomExpression) or isinstance(arg, nodes.AtomStatement): - r = self.get_variable(arg.value) - elif isinstance(arg, nodes.StringExpression) or isinstance(arg, nodes.StringStatement): - r = arg.get_value() - elif isinstance(arg, nodes.FunctionCall): - r = self.function_call(arg) - elif isinstance(arg, nodes.MethodCall): - r = self.method_call(arg) - else: - raise InvalidCode('Line %d: Irreducible argument.' % args.lineno()) - reduced.append(r) - assert(len(reduced) == len(args)) - return reduced + reduced_pos = [self.reduce_single(arg) for arg in args.arguments] + for key in args.kwargs.keys(): + if not isinstance(key, str): + raise InvalidArguments('Line %d: keyword argument name is not a string.' % args.lineno()) + reduced_kw = {} + return (reduced_pos, reduced_kw) def method_call(self, node): object_name = node.object_name.get_value() @@ -170,13 +170,26 @@ class Arguments(Statement): def __init__(self, lineno): Statement.__init__(self, lineno) self.arguments = [] - + self.kwargs = {} + self.order_error = False + def prepend(self, statement): self.arguments = [statement] + self.arguments - def __len__(self): + def set_kwarg(self, name, value): + if self.num_args() > 0: + self.order_error = True + self.kwargs[name.get_value()] = value + + def num_args(self): return len(self.arguments) + def num_kwargs(self): + return len(self.kwargs) + + def __len__(self): + return self.num_args() # Fixme + def statement_from_expression(expr): if isinstance(expr, AtomExpression): return AtomStatement(expr.value, expr.lineno()) diff --git a/test cases/1 trivial/builder.txt b/test cases/1 trivial/builder.txt index dc2a992..34264c5 100644 --- a/test cases/1 trivial/builder.txt +++ b/test cases/1 trivial/builder.txt @@ -1,3 +1,7 @@ project('trivial test', 'c') -exe = executable('trivialprog', 'trivial.c') + +sources = 'trivial.c' + +exe = executable('trivialprog', sources : sources) + add_test('runtest', exe) |