General Improvements

This commit is contained in:
2021-04-02 21:06:06 +03:00
parent 0abb223169
commit 51c5a3efba
4 changed files with 83 additions and 34 deletions
+35 -29
View File
@@ -1,35 +1,35 @@
class ParserModule:
def parse_file(self,file_name):
#Reads the content of a file, deletes the comments and white space,
#labels each line base on the command type and separates it into usefull chunks
assembly_file=open(file_name,"r")
segmented_file=[]
for line in assembly_file:
if len(line)>1:
command=[None,None]
if "//" in line:
line=line[:line.find("//")]
if line =="":
continue
line = line.strip()
if "(" in line:
command[0]="L"
command[1]=line.strip("()")
elif "@" in line:
command[0]="A"
command[1]=line.strip("@")
else:
command[0]="C"
c_command=[None,None,None]
start=0
end=len(line)
if "=" in line:
c_command[0]=line.split("=")[0]
start=line.index("=")+1
if ";" in line:
c_command[2]=line.split(";")[1]
end = line.index(";")
c_command[1]=line[start:end]
command[1]=c_command
segmented_file.append(command)
command=[None,None]
line=line[:line.find("//")]
if line =="":
continue
line = line.strip()
if "(" in line:
command[0]="L"
command[1]=line.strip("()")
elif "@" in line:
command[0]="A"
command[1]=line.strip("@")
else:
command[0]="C"
c_command=[None,None,None]
start=0
end=len(line)
if "=" in line:
c_command[0]=line.split("=")[0]
start=line.index("=")+1
if ";" in line:
c_command[2]=line.split(";")[1]
end = line.index(";")
c_command[1]=line[start:end]
command[1]=c_command
segmented_file.append(command)
assembly_file.close()
return segmented_file
@@ -37,8 +37,9 @@ class SymbolTableModule:
def __init__(self):
self.c_commands=[{None:"000","M":"001","D":"010","MD":"011","A":"100","AM":"101","AD":"110","AMD":"111"},{"0":"0101010","1":"0111111","-1":"0111010","D":"0001100","A":"0110000","!D":"0001101","!A":"0110001","-D":"0001111","-A":"0110011","D+1":"0011111","A+1":"0110111","D-1":"0001110","A-1":"0110010","D+A":"0000010","D-A":"0010011","A-D":"0000111","D&A":"0000000","D|A":"0010101","M":"1110000","!M":"1110001","-M":"1110011","M+1":"1110111","M-1":"1110010","D+M":"1000010","D-M":"1010011","M-D":"1000111","D&M":"1000000","D|M":"1010101"},{None:"000","JGT":"001","JEG":"010","JGE":"011","JLT":"100","JNE":"101","JLE":"110","JMP":"111"}]
self.a_commands={"SP":"0000000000000000","LCL":"0000000000000001","ARG":"0000000000000010","THIS":"0000000000000011","THAT":"0000000000000100","R0":"0000000000000000","R1":"0000000000000001","R2":"0000000000000010","R3":"0000000000000011","R4":"0000000000000100","R5":"0000000000000101","R6":"0000000000000110","R7":"0000000000000111","R8":"0000000000001000","R9":"0000000000001001","R10":"0000000000001010","R11":"0000000000001011","R12":"0000000000001100","R13":"0000000000001101","R14":"0000000000001110","R15":"0000000000001111","SCREEN":"0100000000000000","KBD":"0110000000000000"}
self.counter=1024
self.counter=16
def translate_l_commands(self,assembly_array):
#Maps each symbol label to a certain place in ROM
line_idx=0
for command in assembly_array:
if not command[0] == "L":
@@ -47,6 +48,7 @@ class SymbolTableModule:
self.a_commands[command[1]]=self.decimal_to_binary(line_idx)
def translate_a_commands(self,assembly_array):
#Maps each symbol label to a certain place in RAM
for command in assembly_array:
if command[0] == "A" and not self.a_commands.get(command[1]):
if not command[1].isdecimal():
@@ -57,6 +59,7 @@ class SymbolTableModule:
def check_command(self,command_array):
#Returns the equivalent machine code for the assembly command
command_type,command=command_array
if command_type == "A":
return self.a_commands.get(command)
@@ -65,6 +68,7 @@ class SymbolTableModule:
return None
def decimal_to_binary(self,value):
#Transforms a decimal value into a 16-bit binary number
binary_power=16
binary_array=["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]
while value > 0:
@@ -79,6 +83,8 @@ class Assembler:
self.parser=ParserModule()
self.symbol_table=SymbolTableModule()
def assemble_file(self,file_name):
#Uses the ParserModule and SymbolTableModule to create a machine code file
#in the same directory as the assembly file.
assembly_array=self.parser.parse_file(file_name)
self.symbol_table.translate_l_commands(assembly_array)
self.symbol_table.translate_a_commands(assembly_array)
@@ -88,7 +94,7 @@ class Assembler:
if machine_code_line != None:
machine_code_array.append(machine_code_line)
file_content="\n".join(machine_code_array)
machine_code_file=open(file_name[:-3]+"hack","x")
machine_code_file=open(file_name[:file_name.find(".")]+".hack","x")
machine_code_file.write(file_content)
machine_code_file.close()
+23
View File
@@ -0,0 +1,23 @@
// Adds 1 + ... + 100
@i
M=1 // i=1
@sum
M=0 // sum=0
(LOOP)
@i
D=M // D=i
@100
D=D-A // D=i-100
@END
D;JGT // if (i-100)>0 goto END
@i
D=M // D=i
@sum
M=D+M // sum=sum+i
@i
M=M+1 // i=i+1
@LOOP
0;JMP // goto LOOP
(END)
@END
0;JMP // infinite loop
+20
View File
@@ -0,0 +1,20 @@
0000000000010000
1110111111001000
0000000000010001
1110101010001000
0000000000010000
1111110000010000
0000000001100100
1110010011010000
0000000000010010
1110001100000001
0000000000010000
1111110000010000
0000000000010001
1111000010001000
0000000000010000
1111110111001000
0000000000000100
1110101010000111
0000000000010010
1110101010000111
+5 -5
View File
@@ -1,20 +1,20 @@
*Nand2Tetris - Chapter 4 Project*
*Nand2Tetris - Chapter 6 Project*
Main Goal:
Build a fully fuctional Assembler that takes the Assembly writen code and transforms it into machine code for the Hack Computer
To Do:
1.Build the Parser Module - Complete - no comments added
1.Build the Parser Module - Complete - Comments added
Description: Will break each assembly command into is components to be later process by the other modules.
2.Build the Code Module - Incomplete
2.Build the Code Module - Replace by the Assembler Class
Description: Will take the data from the parser module and translate it into machine code.
3.Build the Symbol Table Module - Complete - no comments added
3.Build the Symbol Table Module - Complete - Comments added
Description: Will take data from the parser module and transform symbols into acutal addresses which will be store into a python dictionary.
4.Connect the 3 modules together - Incomplete
4.Connect the 3 modules together - Replace by the Assembler Class
Description: The workflow of the Assembler Program will involve importing the assembly text from a ".asm" file. Afterward, the parser module will break the code into smaller chunks. This chunks will be than fed to the symbol table module which will build a dictionary for the user generated symbol. The dictionary will be initialize with a series of predefined symbols. Lastly, the code module translates each chunk fed from the parser module into machine code. In case of symbol, the code module will use the symbol table to translate it. The translated program will than be store in a ".hack" file.
For more information: https://www.nand2tetris.org/