diff options
Diffstat (limited to 'subv.py')
| -rw-r--r-- | subv.py | 45 |
1 files changed, 43 insertions, 2 deletions
@@ -2,7 +2,7 @@ import re white = re.compile(r'[ \t\.\n]+') hex = re.compile(r'^\-?(0x)?[0-9a-f]+$') num = re.compile(r'^\d+$') -slice_re = re.compile(r'^([^\[]+)(?:\[(\d+):(\d+)\])?$') +ref_re = re.compile(r'^([^\[+-]+)(?:([+-]\d+))?(?:\[(\d+):(\d+)\])?$') field_re = re.compile(r'^(imm|off)(\d+)$') # parsing @@ -91,13 +91,22 @@ def parse_reference(part): >>> parse_reference(('lbl', 'imm32')) {'label': 'lbl', 'mode': 'imm', 'size': 32, 'meta': ()} + >>> parse_reference(('lbl+0', 'imm32')) + {'label': 'lbl', 'mode': 'imm', 'size': 32, 'meta': (), 'offset': 0} + + >>> parse_reference(('lbl+2', 'imm32')) + {'label': 'lbl', 'mode': 'imm', 'size': 32, 'meta': (), 'offset': 2} + >>> parse_reference(('x[11:0]', 'off12')) {'label': 'x', 'mode': 'off', 'size': 12, 'meta': (), 'hi': 11, 'lo': 0} + + >>> parse_reference(('x-16[11:0]', 'off12')) + {'label': 'x', 'mode': 'off', 'size': 12, 'meta': (), 'offset': -16, 'hi': 11, 'lo': 0} """ ref = part[0] field = part[1] - label, hi, lo = slice_re.match(ref).groups() + label, off, hi, lo = ref_re.match(ref).groups() mode, size = field_re.match(field).groups() ref = { @@ -107,6 +116,9 @@ def parse_reference(part): 'meta': part[2:], } + if off is not None: + ref['offset'] = int(off) + if hi is not None: ref['hi'] = int(hi) ref['lo'] = int(lo) @@ -177,12 +189,18 @@ def is_reference(part): True >>> is_reference(('hello:world',)) True + >>> is_reference(('hello-4',)) + True + >>> is_reference(('hello[11:0]',)) + True >>> is_reference(('$label',)) True >>> is_reference(('$label:extra',)) True >>> is_reference(('$label:extra', 'off20')) True + >>> is_reference(('$label+3[31:12]', 'off20')) + True >>> is_reference(('plain', 'off20')) True @@ -225,6 +243,29 @@ def untag(part, expect=None): raise ValueError("expected {} to be labelled {}".format(part, expect)) return part[0] +def format_reference(ref): + """ opposite of parse_reference.. + + >>> format_reference({'label': 'lbl', 'mode': 'imm', 'size': 32, 'meta': ()}) + ('lbl', 'imm32') + >>> format_reference({'label': 'lbl', 'offset': 0, 'mode': 'imm', 'size': 32, 'meta': ()}) + ('lbl+0', 'imm32') + >>> format_reference({'label': 'lbl', 'offset': 2, 'mode': 'imm', 'size': 32, 'meta': ()}) + ('lbl+2', 'imm32') + >>> format_reference({'label': 'x', 'mode': 'off', 'size': 12, 'meta': (), 'hi': 11, 'lo': 0}) + ('x[11:0]', 'off12') + >>> format_reference({'label': 'x', 'offset': -16, 'mode': 'off', 'size': 12, 'meta': (), 'hi': 11, 'lo': 0}) + ('x-16[11:0]', 'off12') + >>> format_reference({'label': 'x', 'offset': -16, 'mode': 'off', 'size': 12, 'meta': ('extra', 'stuff'), 'hi': 11, 'lo': 0}) + ('x-16[11:0]', 'off12', 'extra', 'stuff') + """ + label = ref['label'] + if 'offset' in ref: + label += '{:+}'.format(ref['offset']) + if 'hi' in ref: + label += '[{hi}:{lo}]'.format(**ref) + return (label, '{mode}{size}'.format(**ref), *ref['meta']) + def format_part(part): """ opposite of parse_part. |
