annotate python/ppci/assembler.py @ 382:0c44e494ef58

Made lexer more generic
author Windel Bouwman
date Sun, 27 Apr 2014 12:24:21 +0200
parents 6df89163e114
children 94f5b719ad0b
rev   line source
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
1
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
2 import re
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
3 import pyyacc
382
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
4 from baselex import BaseLexer
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
5 from . import Token, CompilerError, SourceLocation
342
86b02c98a717 Moved target directory
Windel Bouwman
parents: 341
diff changeset
6 from .target import Target, Label
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
7
340
c7cc54c0dfdf Test featurebranch
Windel Bouwman
parents: 337
diff changeset
8
341
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
9 def bit_type(value):
345
b4882ff0ed06 Added more arm isa tests
Windel Bouwman
parents: 342
diff changeset
10 assert value < (2**32)
341
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
11 assert value >= 0
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
12 t = 'val32'
345
b4882ff0ed06 Added more arm isa tests
Windel Bouwman
parents: 342
diff changeset
13 for n in [16, 12, 8, 5, 3]:
341
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
14 if value < (2**n):
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
15 t = 'val{}'.format(n)
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
16 return t
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
17
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
18
382
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
19 class AsmLexer(BaseLexer):
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
20 def __init__(self, kws):
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
21 tok_spec = [
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
22 ('REAL', r'\d+\.\d+', lambda typ, val: (typ, float(val))),
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
23 ('HEXNUMBER', r'0x[\da-fA-F]+', self.handle_number),
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
24 ('NUMBER', r'\d+', self.handle_number),
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
25 ('ID', r'[A-Za-z][A-Za-z\d_]*', self.handle_id),
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
26 ('SKIP', r'[ \t]', None),
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
27 ('LEESTEKEN', r':=|[\.,=:\-+*\[\]/\(\)]|>=|<=|<>|>|<|}|{', lambda typ, val: (val, val)),
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
28 ('STRING', r"'.*?'", lambda typ, val: (typ, val[1:-1])),
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
29 ('COMMENT', r";.*", None)
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
30 ]
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
31 super().__init__(tok_spec)
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
32 self.kws = kws
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
33
382
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
34 def handle_id(self, typ, val):
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
35 if val.lower() in self.kws:
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
36 typ = val.lower()
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
37 return (typ, val)
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
38
382
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
39 def handle_number(self, typ, val):
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
40 if val.startswith('0x'):
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
41 val = int(val[2:], 16)
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
42 else:
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
43 val = int(val)
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
44 typ = bit_type(val)
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
45 return typ, val
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
46
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
47
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
48 class Parser:
341
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
49 def add_rule(self, prod, rhs, f):
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
50 """ Helper function to add a rule, why this is required? """
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
51 if prod == 'instruction':
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
52 def f_wrap(*args):
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
53 i = f(args)
381
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 375
diff changeset
54 if i:
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 375
diff changeset
55 self.emit(i)
341
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
56 else:
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
57 def f_wrap(*rhs):
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
58 return f(rhs)
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
59 self.g.add_production(prod, rhs, f_wrap)
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
60
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
61 def __init__(self, kws, instruction_rules, emit):
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
62 # Construct a parser given a grammar:
375
19eacf4f7270 Started on memory manager
Windel Bouwman
parents: 346
diff changeset
63 tokens2 = ['ID', 'NUMBER', ',', '[', ']', ':', '+', '-', '*', '=',
341
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
64 pyyacc.EPS, 'COMMENT', '{', '}',
345
b4882ff0ed06 Added more arm isa tests
Windel Bouwman
parents: 342
diff changeset
65 pyyacc.EOF, 'val32', 'val16', 'val12', 'val8', 'val5', 'val3']
341
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
66 tokens2.extend(kws)
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
67 self.kws = kws
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
68 g = pyyacc.Grammar(tokens2)
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
69 self.g = g
340
c7cc54c0dfdf Test featurebranch
Windel Bouwman
parents: 337
diff changeset
70 # Global structure of assembly line:
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
71 g.add_production('asmline', ['asmline2'])
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
72 g.add_production('asmline', ['asmline2', 'COMMENT'])
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
73 g.add_production('asmline2', ['label', 'instruction'])
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
74 g.add_production('asmline2', ['instruction'])
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
75 g.add_production('asmline2', ['label'])
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
76 g.add_production('asmline2', [])
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
77 g.add_production('label', ['ID', ':'], self.p_label)
340
c7cc54c0dfdf Test featurebranch
Windel Bouwman
parents: 337
diff changeset
78
c7cc54c0dfdf Test featurebranch
Windel Bouwman
parents: 337
diff changeset
79 # Add instruction rules for the target in question:
c7cc54c0dfdf Test featurebranch
Windel Bouwman
parents: 337
diff changeset
80 for prod, rhs, f in instruction_rules:
341
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
81 self.add_rule(prod, rhs, f)
340
c7cc54c0dfdf Test featurebranch
Windel Bouwman
parents: 337
diff changeset
82
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
83 #g.add_production('instruction', [])
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
84 g.start_symbol = 'asmline'
341
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
85 self.emit = emit
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
86 self.p = g.generate_parser()
342
86b02c98a717 Moved target directory
Windel Bouwman
parents: 341
diff changeset
87 # print('length of table:', len(self.p.action_table))
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
88
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
89 # Parser handlers:
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
90
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
91 def p_label(self, lname, cn):
341
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
92 lab = Label(lname.val)
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
93 self.emit(lab)
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
94
341
4d204f6f7d4e Rewrite of assembler parts
Windel Bouwman
parents: 340
diff changeset
95 def parse(self, lexer):
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
96 self.p.parse(lexer)
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
97
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
98
381
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 375
diff changeset
99 class BaseAssembler:
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 375
diff changeset
100 """ Assembler base class, inherited by assemblers specific for a target """
346
3bb7dcfe5529 expanded arm target
Windel Bouwman
parents: 345
diff changeset
101 def __init__(self, target):
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
102 self.target = target
340
c7cc54c0dfdf Test featurebranch
Windel Bouwman
parents: 337
diff changeset
103 assert isinstance(target, Target)
381
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 375
diff changeset
104
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 375
diff changeset
105 def make_parser(self):
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 375
diff changeset
106 self.parser = Parser(self.target.asm_keywords, self.target.assembler_rules, self.emit)
382
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
107 self.lexer = AsmLexer(self.target.asm_keywords)
346
3bb7dcfe5529 expanded arm target
Windel Bouwman
parents: 345
diff changeset
108
3bb7dcfe5529 expanded arm target
Windel Bouwman
parents: 345
diff changeset
109 def emit(self, *args):
3bb7dcfe5529 expanded arm target
Windel Bouwman
parents: 345
diff changeset
110 self.stream.emit(*args)
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
111
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
112 # Top level interface:
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
113 def parse_line(self, line):
340
c7cc54c0dfdf Test featurebranch
Windel Bouwman
parents: 337
diff changeset
114 """ Parse line into assembly instructions """
382
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
115 self.lexer.feed(line)
0c44e494ef58 Made lexer more generic
Windel Bouwman
parents: 381
diff changeset
116 self.parser.parse(self.lexer)
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
117
346
3bb7dcfe5529 expanded arm target
Windel Bouwman
parents: 345
diff changeset
118 def assemble(self, asmsrc, stream):
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
119 """ Assemble this source snippet """
381
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 375
diff changeset
120 if type(asmsrc) is str:
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 375
diff changeset
121 pass
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 375
diff changeset
122 elif hasattr(asmsrc, 'read'):
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
123 asmsrc2 = asmsrc.read()
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
124 asmsrc.close()
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
125 asmsrc = asmsrc2
340
c7cc54c0dfdf Test featurebranch
Windel Bouwman
parents: 337
diff changeset
126 # TODO: use generic newline??
c7cc54c0dfdf Test featurebranch
Windel Bouwman
parents: 337
diff changeset
127 # TODO: the bothersome newline ...
346
3bb7dcfe5529 expanded arm target
Windel Bouwman
parents: 345
diff changeset
128 self.stream = stream
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
129 for line in asmsrc.split('\n'):
340
c7cc54c0dfdf Test featurebranch
Windel Bouwman
parents: 337
diff changeset
130 self.parse_line(line)
334
6f4753202b9a Added more recipes
Windel Bouwman
parents:
diff changeset
131
381
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 375
diff changeset
132 def flush(self):
6df89163e114 Fix section and ldr pseudo instruction
Windel Bouwman
parents: 375
diff changeset
133 pass