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)
+