diff python/libasm.py @ 195:37ac6c016e0f

Expanded asm subsystem
author Windel Bouwman
date Fri, 31 May 2013 21:06:44 +0200
parents b01429a5d695
children ec2b423cdbea
line wrap: on
line diff
--- a/python/libasm.py	Wed May 29 22:36:37 2013 +0200
+++ b/python/libasm.py	Fri May 31 21:06:44 2013 +0200
@@ -78,35 +78,118 @@
    def Peak(self):
       return self.curTok
 
-class Assembler:
-    def handle_ins(self, id0):
-        self.ins = id0
-    def p_label(self, lname, cn):
-        self.label = lname
+class ANode:
+    def __eq__(self, other):
+        return self.__repr__() == other.__repr__()
+
+class ALabel(ANode):
+    def __init__(self, name):
+        self.name = name
+    def __repr__(self):
+        return '{0}:'.format(self.name)
+
+class AInstruction(ANode):
+    def __init__(self, opcode, operands):
+        self.opcode = opcode
+        self.operands = operands
+    def __repr__(self):
+        ops = ', '.join(map(str, self.operands))
+        return '{0} {1}'.format(self.opcode, ops)
+
+class AExpression(ANode):
+    def __add__(self, other):
+        return ABinop('+', self, other)
+    def __mul__(self, other):
+        return ABinop('*', self, other)
 
+class ABinop(AExpression):
+    def __init__(self, op, arg1, arg2):
+        self.op = op
+        self.arg1 = arg1
+        self.arg2 = arg2
+    def __repr__(self):
+        return '{0} {1} {2}'.format(self.op, self.arg1, self.arg2)
+
+class AUnop(AExpression):
+    def __init__(self, op, arg):
+        self.op = op
+        self.arg = arg
+    def __repr__(self):
+        return '{0} {1}'.format(self.op, self.arg)
+
+class ASymbol(AExpression):
+    def __init__(self, name):
+        self.name = name
+    def __repr__(self):
+        return self.name
+
+class ANumber(AExpression):
+    def __init__(self, n):
+        self.n = n
+    def __repr__(self):
+        return '{0}'.format(self.n)
+
+class Assembler:
     def __init__(self):
+        self.output = []
         # Construct a parser given a grammar:
-        g = pyyacc.Grammar(['ID', 'NUMBER', ',', '[', ']', ':', '+', '-', pyyacc.EPS])
-
-        g.add_production('asmline', ['label', 'instruction', 'operands'])
-        g.add_production('asmline', ['instruction', 'operands'])
+        ident = lambda x: x   # Identity helper function
+        g = pyyacc.Grammar(['ID', 'NUMBER', ',', '[', ']', ':', '+', '-', '*', pyyacc.EPS])
+        g.add_production('asmline', ['label', 'instruction'])
+        g.add_production('asmline', ['instruction'])
+        g.add_production('asmline', ['label'])
         g.add_production('label', ['ID', ':'], self.p_label)
-        g.add_production('instruction', ['ID'], self.handle_ins)
-        g.add_production('operands', ['operand'])
-        g.add_production('operands', ['operands', ',', 'operand'])
-        g.add_production('operand', ['expression'])
-        g.add_production('operand', ['[', 'expression', ']'])
-        g.add_production('expression', ['term'])
-        g.add_production('expression', ['expression', 'addop', 'term'])
-        g.add_production('addop', ['-'])
-        g.add_production('addop', ['+'])
-        g.add_production('term', ['factor'])
-        g.add_production('factor', ['ID'])
-        g.add_production('factor', ['NUMBER'])
-        # TODO: expand grammar
+        g.add_production('instruction', ['opcode', 'operands'], self.p_ins_1)
+        g.add_production('instruction', ['opcode'], self.p_ins_2)
+        g.add_production('opcode', ['ID'], ident)
+        g.add_production('operands', ['operand'], self.p_operands_1)
+        g.add_production('operands', ['operands', ',', 'operand'], self.p_operands_2)
+        g.add_production('operand', ['expression'], ident)
+        g.add_production('operand', ['[', 'expression', ']'], self.p_mem_op)
+        g.add_production('expression', ['term'], ident)
+        g.add_production('expression', ['expression', 'addop', 'term'], self.p_binop)
+        g.add_production('addop', ['-'], ident)
+        g.add_production('addop', ['+'], ident)
+        g.add_production('mulop', ['*'], ident)
+        g.add_production('term', ['factor'], ident)
+        g.add_production('term', ['term', 'mulop', 'factor'], self.p_binop)
+        g.add_production('factor', ['ID'], self.p_symbol)
+        g.add_production('factor', ['NUMBER'], self.p_number)
         g.start_symbol = 'asmline'
+        self.p = g.genParser()
 
-        self.p = g.genParser()
+    # Parser handlers:
+    def p_ins_1(self, opc, ops):
+        ins = AInstruction(opc, ops)
+        self.emit(ins)
+    def p_ins_2(self, opc):
+        self.p_ins_1(opc, [])
+    def p_operands_1(self, op1):
+        return [op1]
+    def p_operands_2(self, ops, comma, op2):
+        assert type(ops) is list
+        ops.append(op2)
+        return ops
+    def p_mem_op(self, brace_open, exp, brace_close):
+        return AUnop('[]', exp)
+    def handle_ins(self, id0, operands):
+        ins = AInstruction(id0)
+        self.emit(ins)
+    def p_label(self, lname, cn):
+        lab = ALabel(lname)
+        self.emit(lab)
+    def p_binop(self, exp1, op, exp2):
+        return ABinop(op, exp1, exp2)
+    def p_symbol(self, name):
+        return ASymbol(name)
+    def p_number(self, n):
+        n = int(n)
+        return ANumber(n)
+
+    # Top level:
+    def emit(self, a):
+        self.output.append(a)
+
     def parse_line(self, line):
         """ Parse line into asm AST """
         tokens = tokenize(line)