Mercurial > lcfOS
comparison python/asm.py @ 200:5e391d9a3381
Split off asm nodes
author | Windel Bouwman |
---|---|
date | Sun, 09 Jun 2013 16:06:49 +0200 |
parents | a690473b79e2 |
children | ca1ea402f6a1 |
comparison
equal
deleted
inserted
replaced
199:a690473b79e2 | 200:5e391d9a3381 |
---|---|
1 import re, sys, argparse | 1 import re, sys, argparse |
2 import pyyacc | 2 import pyyacc |
3 from ppci import Token, CompilerError, SourceLocation | 3 from ppci import Token, CompilerError, SourceLocation |
4 from target import Target | 4 from target import Target |
5 from asmnodes import ALabel, AInstruction, ABinop, AUnop, ASymbol, ANumber | |
5 | 6 |
6 def tokenize(s): | 7 def tokenize(s): |
7 """ | 8 """ |
8 Tokenizer, generates an iterator that | 9 Tokenizer, generates an iterator that |
9 returns tokens! | 10 returns tokens! |
63 return t | 64 return t |
64 @property | 65 @property |
65 def Peak(self): | 66 def Peak(self): |
66 return self.curTok | 67 return self.curTok |
67 | 68 |
68 class ANode: | |
69 def __eq__(self, other): | |
70 return self.__repr__() == other.__repr__() | |
71 | |
72 class ALabel(ANode): | |
73 def __init__(self, name): | |
74 self.name = name | |
75 def __repr__(self): | |
76 return '{0}:'.format(self.name) | |
77 | |
78 class AInstruction(ANode): | |
79 def __init__(self, opcode, operands): | |
80 self.opcode = opcode | |
81 self.operands = operands | |
82 def __repr__(self): | |
83 ops = ', '.join(map(str, self.operands)) | |
84 return '{0} {1}'.format(self.opcode, ops) | |
85 | |
86 class AExpression(ANode): | |
87 def __add__(self, other): | |
88 assert isinstance(other, AExpression) | |
89 return ABinop('+', self, other) | |
90 def __mul__(self, other): | |
91 assert isinstance(other, AExpression) | |
92 return ABinop('*', self, other) | |
93 | |
94 class ABinop(AExpression): | |
95 def __init__(self, op, arg1, arg2): | |
96 self.op = op | |
97 self.arg1 = arg1 | |
98 self.arg2 = arg2 | |
99 def __repr__(self): | |
100 return '{0} {1} {2}'.format(self.op, self.arg1, self.arg2) | |
101 | |
102 class AUnop(AExpression): | |
103 def __init__(self, op, arg): | |
104 self.op = op | |
105 self.arg = arg | |
106 def __repr__(self): | |
107 return '{0} {1}'.format(self.op, self.arg) | |
108 | |
109 class ASymbol(AExpression): | |
110 def __init__(self, name): | |
111 self.name = name | |
112 def __repr__(self): | |
113 return self.name | |
114 | |
115 class ANumber(AExpression): | |
116 def __init__(self, n): | |
117 assert type(n) is int | |
118 self.n = n | |
119 def __repr__(self): | |
120 return '{0}'.format(self.n) | |
121 | 69 |
122 class Assembler: | 70 class Assembler: |
123 def __init__(self, target=None): | 71 def __init__(self, target=None): |
124 self.target = target | 72 self.target = target |
125 self.output = [] | 73 self.restart() |
126 # Construct a parser given a grammar: | 74 # Construct a parser given a grammar: |
127 ident = lambda x: x # Identity helper function | 75 ident = lambda x: x # Identity helper function |
128 g = pyyacc.Grammar(['ID', 'NUMBER', ',', '[', ']', ':', '+', '-', '*', pyyacc.EPS, 'COMMENT']) | 76 g = pyyacc.Grammar(['ID', 'NUMBER', ',', '[', ']', ':', '+', '-', '*', pyyacc.EPS, 'COMMENT']) |
129 g.add_production('asmline', ['asmline2']) | 77 g.add_production('asmline', ['asmline2']) |
130 g.add_production('asmline', ['asmline2', 'COMMENT']) | 78 g.add_production('asmline', ['asmline2', 'COMMENT']) |
147 g.add_production('addop', ['-'], ident) | 95 g.add_production('addop', ['-'], ident) |
148 g.add_production('addop', ['+'], ident) | 96 g.add_production('addop', ['+'], ident) |
149 g.add_production('mulop', ['*'], ident) | 97 g.add_production('mulop', ['*'], ident) |
150 g.add_production('term', ['factor'], ident) | 98 g.add_production('term', ['factor'], ident) |
151 g.add_production('term', ['term', 'mulop', 'factor'], self.p_binop) | 99 g.add_production('term', ['term', 'mulop', 'factor'], self.p_binop) |
152 g.add_production('factor', ['ID'], self.p_symbol) | 100 g.add_production('factor', ['ID'], lambda name: ASymbol(name)) |
153 g.add_production('factor', ['NUMBER'], self.p_number) | 101 g.add_production('factor', ['NUMBER'], lambda num: ANumber(int(num))) |
154 g.start_symbol = 'asmline' | 102 g.start_symbol = 'asmline' |
155 self.p = g.genParser() | 103 self.p = g.genParser() |
156 | 104 |
157 # Parser handlers: | 105 # Parser handlers: |
158 def p_ins_1(self, opc, ops): | 106 def p_ins_1(self, opc, ops): |
171 def p_label(self, lname, cn): | 119 def p_label(self, lname, cn): |
172 lab = ALabel(lname) | 120 lab = ALabel(lname) |
173 self.emit(lab) | 121 self.emit(lab) |
174 def p_binop(self, exp1, op, exp2): | 122 def p_binop(self, exp1, op, exp2): |
175 return ABinop(op, exp1, exp2) | 123 return ABinop(op, exp1, exp2) |
176 def p_symbol(self, name): | |
177 return ASymbol(name) | |
178 def p_number(self, n): | |
179 n = int(n) | |
180 return ANumber(n) | |
181 | 124 |
182 # Top level interface: | 125 # Top level interface: |
183 def restart(self): | 126 def restart(self): |
184 pass | 127 self.output = [] |
128 self.binout = bytearray() | |
129 self.current_section = '.text' | |
185 | 130 |
186 def emit(self, a): | 131 def emit(self, a): |
187 """ Emit a parsed instruction """ | 132 """ Emit a parsed instruction """ |
188 self.output.append(a) | 133 self.output.append(a) |
189 # Determine the bit pattern from a lookup table: | 134 # Determine the bit pattern from a lookup table: |
190 # TODO | 135 # TODO |
191 | |
192 | 136 |
193 def parse_line(self, line): | 137 def parse_line(self, line): |
194 """ Parse line into asm AST """ | 138 """ Parse line into asm AST """ |
195 tokens = tokenize(line) | 139 tokens = tokenize(line) |
196 self.p.parse(tokens) | 140 self.p.parse(tokens) |
213 """ Assemble a parsed asm line """ | 157 """ Assemble a parsed asm line """ |
214 # TODO | 158 # TODO |
215 if not self.target: | 159 if not self.target: |
216 raise CompilerError('Cannot assemble without target') | 160 raise CompilerError('Cannot assemble without target') |
217 while self.output: | 161 while self.output: |
218 i = self.output.pop(0) | 162 vi = self.output.pop(0) |
219 self.target.createInstruction(i) | 163 ri = self.target.mapInstruction(vi) |
164 b = ri.encode() | |
165 assert type(b) is bytes | |
166 self.binout.extend(b) | |
220 | 167 |
221 def back_patch(self): | 168 def back_patch(self): |
222 """ Fix references to earlier labels """ | 169 """ Fix references to earlier labels """ |
223 pass | 170 pass |
224 | 171 |