Mercurial > lcfOS
view 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 source
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, name): self.inputs = [] 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 Section(Input): def __init__(self, section_name): self.section_name = section_name def __repr__(self): return 'Section({})'.format(self.section_name) class Align(Input): def __init__(self, alignment): self.alignment = alignment def __repr__(self): return 'Align({})'.format(self.alignment) 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, kws): toks = ['ID', 'NUMBER', '{', '}', '.', ':', '=', '(', ')', pyyacc.EPS, pyyacc.EOF] + kws g = pyyacc.Grammar(toks) 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) 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)