154 lines
3.5 KiB
Python
154 lines
3.5 KiB
Python
'''
|
|
1. Kreieren der Symboltabelle
|
|
2. Einlesen der Datei
|
|
a. Entfernen der Kommentare -- erledigt
|
|
b. Suchen der (Label) und Ablegen dieser in die Symboltabelle -- erledigt
|
|
c. Entfernen der (Label) aus dem ASM-File
|
|
d. HACK-Code erzeugen
|
|
'''
|
|
|
|
import sys, os
|
|
from pathlib import Path
|
|
import re
|
|
from icecream import ic
|
|
|
|
symboltable = {}
|
|
asm = []
|
|
|
|
def appendTable(table, id, item):
|
|
print("appendTable ",id, " ", item )
|
|
|
|
table["@"+ str(item)] = id
|
|
symboltable = table
|
|
|
|
|
|
def createSymboltable():
|
|
return {
|
|
key: (value)
|
|
for key, value in {
|
|
**{'@SP': 0,
|
|
'@LCL': 1,
|
|
'@ARG': 2,
|
|
'@THIS': 3,
|
|
'@THAT': 4,
|
|
'@SCREEN': 0x4000,
|
|
'@KBD': 0x6000,},
|
|
**{f'@R{i}': i
|
|
for i in range(16)}
|
|
}.items()}
|
|
|
|
def load_asm_file(filename):
|
|
fp = open(filename, 'r')
|
|
comment = r"^/"
|
|
eol = r"^\n"
|
|
tmp = []
|
|
t = fp.readlines()
|
|
for l in t:
|
|
if re.match(comment, l):
|
|
pass
|
|
elif re.match(eol, l):
|
|
pass
|
|
else:
|
|
tmp.append(re.sub('\s', '', l).split('//')[0]) # Wenn noch ein Kommentar hinter der Anweisung steht dann Abtrenen
|
|
fp.close()
|
|
#ic("tmp = ", tmp)
|
|
return tmp
|
|
|
|
def label_to_symboltable(data):
|
|
#ic(len(data))
|
|
i = 0
|
|
tmp = {}
|
|
for l in data:
|
|
if (l.startswith('(') and l.endswith(')')):
|
|
l = l[:-1]
|
|
l = l.lstrip('(')
|
|
tmp['@'+str(l)] = i
|
|
#ic(l)
|
|
else:
|
|
i=i+1
|
|
|
|
if len(tmp) != 0:
|
|
symboltable.update(tmp)
|
|
#ic(symboltable)
|
|
#ic (data)
|
|
|
|
# c. Löschen der (Label) aus der Liste
|
|
count = 0
|
|
for i in tmp:
|
|
#ic(tmp[i]) # Zeilennummern
|
|
data.pop(tmp[i]-count)
|
|
|
|
#ic(len(data))
|
|
searchSymbols(data)
|
|
|
|
|
|
|
|
def searchSymbols(asm):
|
|
'''
|
|
wenn Zeile mit @ beginnt schauen ob Variable in Symboltable
|
|
sonst
|
|
ist Variable @x ein int, dann ohne @ in die Symboltable übernehmen
|
|
'''
|
|
#ic(asm)
|
|
i = 16
|
|
for line in asm:
|
|
if line.startswith('@'):
|
|
#ic (i, " ",line[1:])
|
|
if line[1:].isdigit():
|
|
if line not in symboltable:
|
|
addtoSymboltable(line, int(line[1:]))
|
|
elif line not in symboltable:
|
|
#ic("Symbol nicht in Table")
|
|
addtoSymboltable(line, i)
|
|
i = i+1
|
|
|
|
def ciinstruction(ci):
|
|
c = "1110000000000000"
|
|
|
|
if ci.__contains__('='):
|
|
c2 = ci.split('=')
|
|
|
|
ic(c2)
|
|
|
|
#ic("Dest = ", ci[0], " Comp = ", ci[2])
|
|
|
|
|
|
return c +"\n"
|
|
#return '{0:016b}'.format(c)+"\n"
|
|
#return bin(c)[2:]+"\n" # 111 in binär --> falscher Weg
|
|
# dest = comp; jump
|
|
|
|
|
|
|
|
def addtoSymboltable(key,value):
|
|
ic(key, value)
|
|
symboltable[key]=value
|
|
|
|
|
|
def createAsmFile():
|
|
datename = os.path.splitext(os.path.basename(filename))[0]+".hack"
|
|
ic(datename)
|
|
f = open(datename,"w")
|
|
for line in asm:
|
|
if line in symboltable:
|
|
f.write('{0:016b}'.format(symboltable[line]) + "\n")
|
|
else:
|
|
#M=D
|
|
f.write(ciinstruction(line))
|
|
f.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
filename = sys.argv[1]
|
|
#filename = "Pong.asm"
|
|
symboltable = createSymboltable()
|
|
asm = load_asm_file(filename)
|
|
label_to_symboltable(asm)
|
|
searchSymbols(asm)
|
|
createAsmFile()
|
|
|
|
#print("Symtable = ",symboltable)
|
|
|
|
|
|
|