77 lines
3.3 KiB
Python
77 lines
3.3 KiB
Python
# (c) Stephan Diehl, University of Trier, Germany, 2025
|
|
from . import tram
|
|
|
|
class Assembler:
|
|
@staticmethod
|
|
def read_tram_code(filename):
|
|
code = []
|
|
lines = []
|
|
labelmap = {}
|
|
linemap = {}
|
|
|
|
try:
|
|
with open(filename, 'r', encoding='utf-8') as f:
|
|
line_number = 0
|
|
for raw_line in f:
|
|
line = raw_line.strip()
|
|
if line.startswith("//") or line.startswith("#") or not line:
|
|
continue
|
|
if ":" in line:
|
|
labels_part = line[:line.index(':')]
|
|
labels = [label.strip() for label in labels_part.split(',')]
|
|
linemap[line_number] = labels
|
|
for label in labels:
|
|
labelmap[label] = tram.Label(line_number,label)
|
|
line = line[line.index(':') + 1:].strip()
|
|
lines.append(line)
|
|
line_number += 1
|
|
except IOError as e:
|
|
print(f"Fehler beim Lesen der Datei: {e}")
|
|
|
|
for i, line in enumerate(lines):
|
|
labels = [labelmap.get(label,None) for label in linemap.get(i,[])]
|
|
instr = Assembler.convert_to_instruction(line, labelmap, labels)
|
|
code.append(instr)
|
|
|
|
return code
|
|
|
|
@staticmethod
|
|
def convert_to_instruction(line, labelmap={}, labels=None):
|
|
parts = line.split()
|
|
instr =parts[0].upper()
|
|
arg1 = Assembler.arg_to_number(parts, 1, labelmap)
|
|
arg2 = Assembler.arg_to_number(parts, 2, labelmap)
|
|
arg3 = Assembler.arg_to_number(parts, 3, labelmap)
|
|
if instr == "CONST": code=tram.const(arg1,assigned_label=labels)
|
|
elif instr == "LOAD": code=tram.load(arg1, arg2,assigned_label=labels)
|
|
elif instr == "STORE": code=tram.store(arg1,arg2,assigned_label=labels)
|
|
elif instr == "ADD": code=tram.add(assigned_label=labels)
|
|
elif instr == "SUB": code=tram.sub(assigned_label=labels)
|
|
elif instr == "MUL": code=tram.mul(assigned_label=labels)
|
|
elif instr == "DIV": code=tram.div(assigned_label=labels)
|
|
elif instr == "LT": code=tram.lt(assigned_label=labels)
|
|
elif instr == "GT": code=tram.gt(assigned_label=labels)
|
|
elif instr == "EQ": code=tram.eq(assigned_label=labels)
|
|
elif instr == "NEQ": code=tram.neq(assigned_label=labels)
|
|
elif instr == "IFZERO": code=tram.ifzero(arg1,assigned_label=labels)
|
|
elif instr == "GOTO": code=tram.goto(arg1,assigned_label=labels)
|
|
elif instr == "HALT": code=tram.halt(assigned_label=labels)
|
|
elif instr == "NOP": code=tram.nop(assigned_label=labels)
|
|
elif instr == "INVOKE": code=tram.invoke(arg1,arg2,arg3,assigned_label=labels)
|
|
elif instr == "RETURN": code=tram.ireturn(assigned_label=labels)
|
|
elif instr == "POP": code=tram.pop(assigned_label=labels)
|
|
else:
|
|
print(f"Keine gültige Instruktion: {line}")
|
|
code = None
|
|
return code
|
|
|
|
@staticmethod
|
|
def arg_to_number(parts, index, labelmap):
|
|
if index >= len(parts):
|
|
return 0
|
|
arg = parts[index]
|
|
try:
|
|
return int(arg)
|
|
except ValueError:
|
|
return labelmap.get(arg, 0)
|