From fa2c659825031c599f59e0a863e8266614e6756f Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 15 Mar 2015 22:31:10 +0200 Subject: [PATCH] Parse arguments iteratively instead of recursively to support argument lists of arbitrary size. --- mparser.py | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/mparser.py b/mparser.py index 33924668b..29208bbdd 100644 --- a/mparser.py +++ b/mparser.py @@ -131,6 +131,9 @@ class IdNode: self.value = token.value assert(isinstance(self.value, str)) + def __str__(self): + return "Id node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) + class NumberNode: def __init__(self, token): self.lineno = token.lineno @@ -145,6 +148,9 @@ class StringNode: self.value = token.value assert(isinstance(self.value, str)) + def __str__(self): + return "String node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) + class ArrayNode: def __init__(self, args): self.lineno = args.lineno @@ -255,16 +261,18 @@ class ArgumentNode(): self.order_error = False def prepend(self, statement): + if self.num_kwargs() > 0: + self.order_error = True if not isinstance(statement, EmptyNode): self.arguments = [statement] + self.arguments def append(self, statement): + if self.num_kwargs() > 0: + self.order_error = True if not isinstance(statement, EmptyNode): self.arguments = self.arguments + [statement] def set_kwarg(self, name, value): - if self.num_args() > 0: - self.order_error = True self.kwargs[name] = value def num_args(self): @@ -427,26 +435,22 @@ class Parser: def args(self): s = self.statement() - if isinstance(s, EmptyNode): - ArgumentNode(s) - - if self.accept('comma'): - rest = self.args() - rest.prepend(s) - return rest - if self.accept('colon'): - if not isinstance(s, IdNode): - raise ParseException('Keyword argument must be a plain identifier.', - s.lineno, s.colno) - value = self.statement() + a = ArgumentNode(s) + + while not isinstance(s, EmptyNode): if self.accept('comma'): - a = self.args() + a.append(s) + elif self.accept('colon'): + if not isinstance(s, IdNode): + raise ParseException('Keyword argument must be a plain identifier.', + s.lineno, s.colno) + a.set_kwarg(s.value, self.statement()) + if not self.accept('comma'): + return a else: - a = ArgumentNode(self.current) - a.set_kwarg(s.value, value) - return a - a = ArgumentNode(self.current) - a.append(s) + a.append(s) + return a + s = self.statement() return a def method_call(self, source_object):