Mercurial > lcfOS
diff python/ppci/layout.py @ 383:173e20a47fda
Added linker description loader
author | Windel Bouwman |
---|---|
date | Sun, 27 Apr 2014 17:40:39 +0200 |
parents | 0c44e494ef58 |
children | d056b552d3f4 |
line wrap: on
line diff
--- a/python/ppci/layout.py Sun Apr 27 12:24:21 2014 +0200 +++ b/python/ppci/layout.py Sun Apr 27 17:40:39 2014 +0200 @@ -1,58 +1,131 @@ +from baselex import BaseLexer +import pyyacc +from . import make_num + class Layout: def __init__(self): self.mems = [] + def add_memory(self, memory): + self.mems.append(memory) + def __eq__(self, other): return self.mems == other.mems + def __repr__(self): + return str(self.mems) + class Memory: - def __init__(self, address=0x0): + def __init__(self, name): self.inputs = [] - self.address = address + self.name = name + self.location = 0x0 self.size = 0x0 def add_input(self, inp): assert isinstance(inp, Input) self.inputs.append(inp) + def __repr__(self): + return 'MEM {} loc={:08X} size={:08X}'.format(self.name, self.location, self.size) + str(self.inputs) + + def __eq__(self, other): + return str(self) == str(other) class Input: pass -class SectionInput(Input): +class Section(Input): def __init__(self, section_name): self.section_name = section_name + def __repr__(self): + return 'Section({})'.format(self.section_name) -def load_layout(f): - return deserialize(json.load(f)) + +class Align(Input): + def __init__(self, alignment): + self.alignment = alignment + + def __repr__(self): + return 'Align({})'.format(self.alignment) -def make_int(txt): - if txt.startswith('0x'): - return int(txt[2:], 16) - else: - return int(txt) +class LayoutLexer(BaseLexer): + def __init__(self): + tok_spec = [ + ('HEXNUMBER', r'0x[\da-fA-F]+', self.handle_number), + ('NUMBER', r'\d+', self.handle_number), + ('ID', r'[A-Za-z][A-Za-z\d_]*', self.handle_id), + ('SKIP', r'[ \t\r\n]', None), + ('LEESTEKEN', r':=|[\.,=:\-+*\[\]/\(\)]|>=|<=|<>|>|<|}|{', lambda typ, val: (val, val)), + ('STRING', r"'.*?'", lambda typ, val: (typ, val[1:-1])), + ] + super().__init__(tok_spec) + self.kws = ['MEMORY', 'ALIGN', 'LOCATION','SECTION','SIZE'] + + def handle_id(self, typ, val): + if val in self.kws: + typ = val + return typ, val + + def handle_number(self, typ, val): + val = make_num(val) + typ = 'NUMBER' + return typ, val class LayoutParser: - def __init__(self): - toks = ['ID', '{', '}', 'MEMORY', 'ALIGN', '.', pyyacc.EPS, pyyacc.EOF] + def __init__(self, kws): + toks = ['ID', 'NUMBER', '{', '}', '.', ':', '=', '(', ')', pyyacc.EPS, pyyacc.EOF] + kws g = pyyacc.Grammar(toks) - g.add_production('layout', ['MEMORY', '{', 'input_list', '}']) - g.add_production('input_list', ['MEMORY', '{', 'input_list', '}']) + g.add_production('layout', ['mem_list']) + g.add_one_or_more('mem', 'mem_list') + g.add_production('mem', ['MEMORY', 'ID', 'LOCATION', '=', 'NUMBER', 'SIZE', '=', 'NUMBER', '{', 'input_list', '}'], self.handle_mem) + g.add_one_or_more('input', 'input_list') + g.add_production('input', ['ALIGN', '(', 'NUMBER', ')'], self.handle_align) + g.add_production('input', ['SECTION', '(', 'ID', ')'], self.handle_section) + + g.start_symbol = 'layout' + self.p = g.generate_parser() + + def parse(self, lexer, layout): + self.layout = layout + self.p.parse(lexer) + + def handle_mem(self, mem_tag, mem_name, loc_tag, eq1, loc, size_tag, eq2, size, lbrace, inps, rbrace): + m = Memory(mem_name.val) + m.size = size.val + m.location = loc.val + for inp in inps: + m.add_input(inp) + self.layout.add_memory(m) + + def handle_align(self, align_tag, lbrace, alignment, rbrace): + return Align(alignment.val) + + def handle_section(self, section_tag, lbrace, section_name, rbrace): + return Section(section_name.val) -def deserialize(d): - layout = Layout() - for mem_node in d['memories']: - m = Memory() - m.address = make_int(mem_node['address']) - m.size = make_int(mem_node['size']) - for input_node in mem_node['inputs']: - pass - return layout +class LayoutLoader: + def __init__(self): + self.lexer = LayoutLexer() + self.parser = LayoutParser(self.lexer.kws) + def load_layout(self, f): + layout = Layout() + self.lexer.feed(f.read()) # TODO: perhaps the read is better in the lexer? + self.parser.parse(self.lexer, layout) + return layout + +# Single definition: +_lloader = LayoutLoader() + + +def load_layout(f): + return _lloader.load_layout(f) +