fix empty function arguments

Previously, an empty argument was treated as "not an argument at all". Now,
every function call always has at least one argument -- i.e., %foo{} is a
function call whose only argument is "" -- and %foo{,bar} is valid syntax.
This commit is contained in:
Adrian Sampson 2011-12-16 12:08:39 -08:00
parent f1ebc82a55
commit 46a3bde5b5
3 changed files with 11 additions and 10 deletions

View file

@ -298,13 +298,9 @@ class Parser(object):
# Try to parse a subexpression in a subparser. # Try to parse a subexpression in a subparser.
expressions = [] expressions = []
while self.pos < len(self.string) and \ while self.pos < len(self.string):
self.string[self.pos] != GROUP_CLOSE:
subparser = Parser(self.string[self.pos:]) subparser = Parser(self.string[self.pos:])
subparser.parse_expression() subparser.parse_expression()
if subparser.pos == 0:
# No expression could be parsed.
break
# Extract and advance past the parsed expression. # Extract and advance past the parsed expression.
expressions.append(Expression(subparser.parts)) expressions.append(Expression(subparser.parts))
@ -316,6 +312,7 @@ class Parser(object):
break break
# Only other way to terminate an expression is with ,. # Only other way to terminate an expression is with ,.
# Continue to the next argument.
assert self.string[self.pos] == ARG_SEP assert self.string[self.pos] == ARG_SEP
self.pos += 1 self.pos += 1

View file

@ -398,8 +398,8 @@ class DestinationFunctionTest(unittest.TestCase):
self._assert_dest('/base/tle') self._assert_dest('/base/tle')
def test_if_false(self): def test_if_false(self):
self._setf(u'%if{,foo}') self._setf(u'x%if{,foo}')
self._assert_dest('/base/') self._assert_dest('/base/x')
def test_if_true(self): def test_if_true(self):
self._setf(u'%if{bar,foo}') self._setf(u'%if{bar,foo}')

View file

@ -147,10 +147,11 @@ class ParseTest(unittest.TestCase):
self.assertEqual(list(_normparse(u'foo %bar{bar,bar baz')), self.assertEqual(list(_normparse(u'foo %bar{bar,bar baz')),
[u'foo %bar{bar,bar baz']) [u'foo %bar{bar,bar baz'])
def test_call_no_args(self): def test_call_empty_arg(self):
parts = list(_normparse(u'%foo{}')) parts = list(_normparse(u'%foo{}'))
self.assertEqual(len(parts), 1) self.assertEqual(len(parts), 1)
self._assert_call(parts[0], u"foo", 0) self._assert_call(parts[0], u"foo", 1)
self.assertEqual(list(_normexpr(parts[0].args[0])), [])
def test_call_single_arg(self): def test_call_single_arg(self):
parts = list(_normparse(u'%foo{bar}')) parts = list(_normparse(u'%foo{bar}'))
@ -192,7 +193,7 @@ class ParseTest(unittest.TestCase):
self._assert_call(parts[0], u"foo", 2) self._assert_call(parts[0], u"foo", 2)
arg_parts = list(_normexpr(parts[0].args[0])) arg_parts = list(_normexpr(parts[0].args[0]))
self.assertEqual(len(arg_parts), 1) self.assertEqual(len(arg_parts), 1)
self._assert_call(arg_parts[0], u"bar", 0) self._assert_call(arg_parts[0], u"bar", 1)
self.assertEqual(list(_normexpr(parts[0].args[1])), [u"baz"]) self.assertEqual(list(_normexpr(parts[0].args[1])), [u"baz"])
def test_nested_call_with_argument(self): def test_nested_call_with_argument(self):
@ -253,6 +254,9 @@ class EvalTest(unittest.TestCase):
def test_not_subtitute_func_with_no_args(self): def test_not_subtitute_func_with_no_args(self):
self.assertEqual(self._eval(u"%lower"), u"%lower") self.assertEqual(self._eval(u"%lower"), u"%lower")
def test_function_call_with_empty_arg(self):
self.assertEqual(self._eval(u"%len{}"), u"0")
def suite(): def suite():
return unittest.TestLoader().loadTestsFromName(__name__) return unittest.TestLoader().loadTestsFromName(__name__)