From 0f60f9b3f602b138b6977d99ae65538e8ceb548f Mon Sep 17 00:00:00 2001 From: Mike Naberezny Date: Sun, 18 Nov 2012 16:15:19 -0800 Subject: [PATCH] Catch bad label syntax and raise KeyError --- py65/tests/utils/test_addressing.py | 9 +++++ py65/utils/addressing.py | 63 ++++++++++++++++------------- 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/py65/tests/utils/test_addressing.py b/py65/tests/utils/test_addressing.py index 2281f8f..e2c171e 100644 --- a/py65/tests/utils/test_addressing.py +++ b/py65/tests/utils/test_addressing.py @@ -97,6 +97,15 @@ class AddressParserTests(unittest.TestCase): except KeyError, why: self.assertEqual('Label not found: bad_label', why[0]) + def test_number_bad_label_syntax(self): + parser = AddressParser() + parser.labels = {'foo': 0xFFFF} + try: + parser.number('#$foo') + self.fail() + except KeyError, why: + self.assertEqual('Label not found: #$foo', why[0]) + def test_number_constrains_address_at_zero_or_above(self): parser = AddressParser() self.assertEqual(0x0000, parser.number('-1')) diff --git a/py65/utils/addressing.py b/py65/utils/addressing.py index 607d084..4798a60 100644 --- a/py65/utils/addressing.py +++ b/py65/utils/addressing.py @@ -37,41 +37,46 @@ class AddressParser(object): def number(self, num): """Parse a string containing a label or number into an address. """ - if num.startswith('$'): - return self._constrain(int(num[1:], 16)) + try: + if num.startswith('$'): + # hexadecimal + return self._constrain(int(num[1:], 16)) - elif num.startswith('+'): - return self._constrain(int(num[1:], 10)) + elif num.startswith('+'): + # decimal + return self._constrain(int(num[1:], 10)) - elif num.startswith('%'): - return self._constrain(int(num[1:], 2)) + elif num.startswith('%'): + # binary + return self._constrain(int(num[1:], 2)) - elif num in self.labels: - return self.labels[num] - - else: - matches = re.match('^([^\s+-]+)\s*([+\-])\s*([$+%]?\d+)$', num) - if matches: - label, sign, offset = matches.groups() - - if label not in self.labels: - raise KeyError("Label not found: %s" % label) - - base = self.labels[label] - offset = self.number(offset) - - if sign == '+': - address = base + offset - else: - address = base - offset - - return self._constrain(address) + elif num in self.labels: + # label name + return self.labels[num] else: - try: + matches = re.match('^([^\s+-]+)\s*([+\-])\s*([$+%]?\d+)$', num) + if matches: + label, sign, offset = matches.groups() + + if label not in self.labels: + raise KeyError("Label not found: %s" % label) + + base = self.labels[label] + offset = self.number(offset) + + if sign == '+': + address = base + offset + else: + address = base - offset + + return self._constrain(address) + + else: return self._constrain(int(num, self.radix)) - except ValueError: - raise KeyError("Label not found: %s" % num) + + except ValueError: + raise KeyError("Label not found: %s" % num) def range(self, addresses): """Parse a string containing an address or a range of addresses