feat: working assembler! second pass implemenation. mnemonic parsing and binary construction and writing
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
from pathlib import Path
|
||||
|
||||
from assembler.code import Code
|
||||
from assembler.constants.command_types import CommandType
|
||||
from assembler.parser import Parser
|
||||
|
||||
@@ -47,13 +48,16 @@ class Assembler:
|
||||
Main assembly process - coordinates first and second pass.
|
||||
Public API method that CLI will call.
|
||||
"""
|
||||
print("[] - Starting First Pass..")
|
||||
print("[ ] - Starting First Pass..")
|
||||
self._first_pass()
|
||||
print("Symbol Table After First Pass")
|
||||
print(self.symbol_table.symbols)
|
||||
print("[x] - First Pass Done..")
|
||||
print("[] - Starting Second Pass..")
|
||||
print("[ ] - Starting Second Pass..")
|
||||
self._second_pass()
|
||||
print("[x] - Second pass done..")
|
||||
print("[ ] - Writing output file..")
|
||||
self._write_output()
|
||||
print("[x] - Output file written..")
|
||||
self._assembled_success()
|
||||
|
||||
def _trim_comments_and_whitespace(self, lines: list[str]) -> list[str]:
|
||||
"""
|
||||
@@ -88,7 +92,6 @@ class Assembler:
|
||||
|
||||
while self.parser.has_more_commands():
|
||||
self.parser.advance() # Move to next command
|
||||
print(self.parser.command_type())
|
||||
cmd_type = self.parser.command_type()
|
||||
if cmd_type == CommandType.L_COMMAND:
|
||||
label = self.parser.symbol() # Extract label name
|
||||
@@ -105,43 +108,59 @@ class Assembler:
|
||||
Second pass: Translate instructions to binary.
|
||||
Handles A-commands, C-commands, and resolves symbols.
|
||||
"""
|
||||
print(self.cleaned_lines)
|
||||
|
||||
while self.parser.has_more_commands():
|
||||
self.parser.advance() # Move to next command
|
||||
print(self.parser.command_type())
|
||||
|
||||
# cmd cmd_type
|
||||
cmd_type = self.parser.command_type()
|
||||
if cmd_type == CommandType.L_COMMAND:
|
||||
continue
|
||||
elif cmd_type == CommandType.A_COMMAND:
|
||||
print("....")
|
||||
binary = self._translate_a_command(self.parser.symbol())
|
||||
self.binary_instructions.append(binary) # Store resultp
|
||||
# Do A command things
|
||||
elif cmd_type == CommandType.C_COMMAND:
|
||||
print("..")
|
||||
# Do C command Things
|
||||
binary = self._translate_c_command()
|
||||
self.binary_instructions.append(binary) # Store resultp
|
||||
|
||||
# Do C command Things
|
||||
|
||||
def _translate_a_command(self, symbol: str) -> str:
|
||||
"""
|
||||
Translate A-command to 16-bit binary.
|
||||
Handles: numeric constants, predefined symbols, variables.
|
||||
"""
|
||||
raise NotImplementedError("Not implemented")
|
||||
# Case 1: Check if symbol is a numeric constant (e.g., "2", "100")
|
||||
if symbol.isdigit():
|
||||
address = int(symbol)
|
||||
|
||||
# Case 2: Check if symbol exists in symbol table (predefined or label)
|
||||
elif self.symbol_table.contains(symbol):
|
||||
address = self.symbol_table.get_address(symbol)
|
||||
|
||||
# Case 3: It's a new variable - allocate next available address
|
||||
else:
|
||||
address = self.next_variable_address
|
||||
self.symbol_table.add_entry(symbol, address)
|
||||
self.next_variable_address += 1
|
||||
|
||||
# Convert address to 16-bit binary string (format: 0xxxxxxxxxxxxxxx)
|
||||
return format(address, "016b")
|
||||
|
||||
def _translate_c_command(self) -> str:
|
||||
"""
|
||||
Translate C-command to 16-bit binary.
|
||||
Format: 111 a c1c2c3c4c5c6 d1d2d3 j1j2j3
|
||||
"""
|
||||
raise NotImplementedError("Not implemented")
|
||||
|
||||
comp = Code.comp(self.parser.comp())
|
||||
dest = Code.dest(self.parser.dest())
|
||||
jump = Code.jump(self.parser.jump())
|
||||
|
||||
binary = f"111{comp}{dest}{jump}"
|
||||
return binary
|
||||
|
||||
def _write_output(self) -> None:
|
||||
"""Write binary instructions to output file."""
|
||||
with open(self.output_file, "w") as f:
|
||||
f.write(f"// Assembled from {self.input_file.name}\n")
|
||||
f.write(f"// {len(self.cleaned_lines)} lines processed\n")
|
||||
raise NotImplementedError("Not implemented")
|
||||
f.write("\n".join(self.binary_instructions))
|
||||
|
||||
def _assembled_success(self) -> None:
|
||||
"""Success Message"""
|
||||
|
||||
@@ -28,7 +28,6 @@ def main():
|
||||
try:
|
||||
assembler = Assembler(input_path, output_path)
|
||||
assembler.assemble()
|
||||
print(f"Successfully assembled {input_path} -> {output_path}")
|
||||
except ValueError as e:
|
||||
# Handle validation errors (empty labels, invalid syntax, etc.)
|
||||
print(f"Assembly Error: {e}", file=sys.stderr)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from .code_tables import DEST_TABLE, COMP_TABLE, JUMP_TABLE
|
||||
from .code_tables import COMP_TABLE, DEST_TABLE, JUMP_TABLE
|
||||
|
||||
|
||||
class Code:
|
||||
|
||||
Reference in New Issue
Block a user