-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhack_assembler.py
More file actions
131 lines (102 loc) · 4.74 KB
/
Copy pathhack_assembler.py
File metadata and controls
131 lines (102 loc) · 4.74 KB
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python3
print()
print("Starting the Hack Assembler ...")
print("Importing the symbol table manager class ...")
from symtblmgr import SymbolTableManager
print("Symbol table manager class imported.")
print("Importing the parser class ...")
from parser import Parser
print("Parser class imported.")
print("Importing the translator class ...")
from translator import Translator
print("Translator class imported.")
import sys
import os
progname = "prog"
#_______________________________ Function : PARSE-TRANSLATE ROUTINE ____________________________________
def parse_trans_loop(sym_table):
is_first_instr = True
print("Parsing through and translating instructions ...")
# Translate to .hack file on-the-fly :
with open('3_' + progname + '_nodecl.asm', 'r') as input_file, open(progname + '.hack', 'w') as output_file:
for instr in input_file:
prs = Parser()
trans = Translator()
instr = instr.strip()
if(is_first_instr):
is_first_instr = False
else:
output_file.write('\n')
output_file.write(trans.get_bin_instr(prs.get_fields(instr, sym_table)))
#_____________________________________ Function : RESULT DISPLAY _______________________________________
def show_content(filename):
print(f"Displaying contents of the file '{filename}' ...")
with open(filename, 'r') as file:
for line in file:
print(line, end='') # Print each line without adding extra newline
#_________________________________ Function : FILTERING OUT COMMENTS ___________________________________
def filter_ln_cmts(prog_asm):
first_instr = True
print(f"Generating non-code filtration files for program \'{progname}\' ...")
# Filtering out whole-line comments :
with open(progname + '.asm', 'r') as input_file, open('1_' + progname + '_nsl.asm', 'w') as output_file:
for line in input_file:
subject = line.strip()
if(subject != ''):
#print(f"Subject: {subject}")
if(subject[0]=='D' or subject[0]=='M' or subject[0]=='A' or subject[0]=='0' or subject[0]=='@' or subject[0]=='('):
if(first_instr):
first_instr = False
else:
output_file.write('\n')
output_file.write(subject)
# Filtering out inline comments :
first_instr = True
with open('1_' + progname + '_nsl.asm', 'r') as input_file, open('2_' + progname + '_pure.asm', 'w') as output_file:
for line in input_file:
if(first_instr):
first_instr = False
else:
output_file.write('\n')
substrings = line.split('//')
instruction = substrings[0].strip()
output_file.write(instruction)
first_instr = False
def filter_comments(prog_asm):
#filter_mltln_cmts(prog_asm)
filter_ln_cmts(prog_asm)
#______________________________________ Function : ARG CHECK ___________________________________________
def is_arg_good():
if(len(sys.argv) > 1): # "Presence of argument 1" test
asm_in = sys.argv[1]
if os.path.exists(asm_in): # "Presence of the file" test
if(".asm" in asm_in): # "Recognition as .asm" test
print(f"Detected file {asm_in}. Processing ... ")
return asm_in
else:
print(f"The file '{asm_in}' is not recognized as an assembly file.")
return False
else:
print(f"The file '{asm_in}' is not in the working directory.")
return False
else:
print("Operand assembly file name not provided.")
return False
############################################ Script body : #############################################
if(prog_asm := is_arg_good()): # arg check
progname, the_rest = prog_asm.split('.') # extracting the generic program name
filter_comments(prog_asm) # comment filtration
symgr = SymbolTableManager() # Symbol table built with pre-defined elements.
symgr.map_labels(progname)
symgr.map_vars(progname)
parse_trans_loop(symgr.table)
#__________________________________________________________________________________________________
# Clean-up :
print(f"File {progname}.hack generated.")
#show_content(progname + '.hack')
print("Removing auxiliary files ...")
os.remove('1_' + progname + '_nsl.asm')
os.remove('2_' + progname + '_pure.asm')
os.remove('3_' + progname + '_nodecl.asm')
#os.remove(progname + '.hack')
print("Clean-up completed.")