-
Notifications
You must be signed in to change notification settings - Fork 0
/
program.py
116 lines (85 loc) · 2.7 KB
/
program.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import sys
import os
from parser_module import Parser
from code_module import Code
from symbols_module import SymbolTable
def main():
input_filename = get_full_input_filename()
if not input_filename:
print('You need to specify an input filename.')
return
if not os.path.exists(input_filename):
print('The file {} does not exists.'.format(input_filename))
return
output_filename = get_full_output_filename(input_filename)
# parse labels
st = SymbolTable()
p0 = Parser(input_filename)
position_address = 0
while True:
if not p0.has_more_commands():
break
p0.advance()
command_type = p0.command_type()
symbol = p0.symbol()
if command_type == 'L_COMMAND':
if not st.contains(symbol):
st.add_entry(symbol, position_address)
else:
position_address += 1
# parse addresses
p1 = Parser(input_filename)
variable_address = 16
while True:
if not p1.has_more_commands():
break
p1.advance()
command_type = p1.command_type()
symbol = p1.symbol()
if command_type == 'A_COMMAND':
if not st.contains(symbol) and not is_number(symbol):
st.add_entry(symbol, variable_address)
variable_address += 1
# second pass
p2 = Parser(input_filename)
with open(output_filename, 'w') as fout:
while True:
if not p2.has_more_commands():
break
p2.advance()
command = decode_command(p2, st)
if command:
fout.write(command + '\n')
def decimal_to_binary_str(dec_value):
return format(dec_value, '015b')
def is_number(string):
try:
int(string)
return True
except:
return False
def decode_command(p, st):
command_type = p.command_type()
command_decoded = None
c = Code()
if command_type == 'A_COMMAND':
symbol = p.symbol()
if st.contains(symbol):
symbol_value = st.get_address(symbol)
command_decoded = '0' + decimal_to_binary_str(symbol_value)
else:
command_decoded = '0' + decimal_to_binary_str(int(symbol))
elif command_type == 'C_COMMAND':
command_decoded = '111' + \
c.comp(p.comp()) + c.dest(p.dest()) + c.jump(p.jump())
return command_decoded
def get_full_input_filename():
try:
input_filename = sys.argv[1]
return os.path.abspath(os.path.join(input_filename))
except IndexError:
return None
def get_full_output_filename(input_filename):
return input_filename[:-3] + 'hack'
if __name__ == "__main__":
main()