Py502/lang-to-asm.py

117 lines
4.3 KiB
Python

def parse_math_to_instructions(math_expression, memory_map):
"""
Converts a simple math expression or variable assignment to assembly instructions.
:param math_expression: The math expression to convert.
:param memory_map: A dictionary tracking variable memory locations.
:return: A list of assembly instructions.
"""
instructions = []
temp_memory_address = 0xFF # Starting memory address for variables
# Check for assignment
if '=' in math_expression:
var_name, expr = map(str.strip, math_expression.split('='))
expr = expr.strip(';') # Remove trailing semicolon
var_name = var_name.strip()
var_name = var_name.strip("int ")
# Generate instructions for the expression
expr_instructions, result_register = parse_expression(expr, memory_map, temp_memory_address)
instructions.extend(expr_instructions)
# Assign the result to the variable
if var_name not in memory_map:
memory_map[var_name] = temp_memory_address
temp_memory_address -= 1
instructions.append(f"str {result_register}, 0x{memory_map[var_name]:X} ; Save variable {var_name} in memory")
else:
# Generate instructions for the expression
expr_instructions, _ = parse_expression(math_expression, memory_map, temp_memory_address)
instructions.extend(expr_instructions)
return instructions
def precedence(op):
"""
Returns the precedence of the given operator.
"""
if op in ('+', '-'):
return 1
if op in ('*', '/'):
return 2
return 0
def apply_operator(instructions, operand_stack, operator):
"""
Applies an operator to the top two operands in the operand stack and generates instructions.
"""
b = operand_stack.pop()
a = operand_stack.pop()
if operator == '+':
instructions.append("add a, b")
elif operator == '-':
instructions.append("sub a, b")
elif operator == '*':
instructions.append("mul a, b")
elif operator == '/':
instructions.append("div a, b")
operand_stack.append('a')
def parse_expression(expr, memory_map, temp_memory_address):
"""
Parses a math expression and generates instructions.
:param expr: The math expression.
:param memory_map: Memory map for variables.
:param temp_memory_address: Memory address to use for new variables.
:return: (list of instructions, result_register)
"""
instructions = []
tokens = expr.replace('(', ' ( ').replace(')', ' ) ').split()
operator_stack = []
operand_stack = []
for token in tokens:
if token.isdigit():
if 'a' not in operand_stack:
instructions.append(f"ldw a, {token}")
operand_stack.append('a')
else:
instructions.append(f"ldw b, {token}")
operand_stack.append('b')
elif token in memory_map:
if 'a' not in operand_stack:
instructions.append(f"ldr a, 0x{memory_map[token]:X}")
operand_stack.append('a')
else:
instructions.append(f"ldr b, 0x{memory_map[token]:X}")
operand_stack.append('b')
elif token in ['+', '-', '*', '/']:
while (operator_stack and precedence(operator_stack[-1]) >= precedence(token)):
apply_operator(instructions, operand_stack, operator_stack.pop())
operator_stack.append(token)
elif token == '(':
operator_stack.append(token)
elif token == ')':
while operator_stack and operator_stack[-1] != '(':
apply_operator(instructions, operand_stack, operator_stack.pop())
operator_stack.pop() # Remove '('
while operator_stack:
apply_operator(instructions, operand_stack, operator_stack.pop())
return instructions, 'a'
# Example Usage
memory_map = {}
expressions = [
"1 + ( 3 + 8 )",
"int variable = 1 + ( 3 + 8 );",
"int variable_dose = variable + ( 4 + 4 );"
]
for expr in expressions:
instructions = parse_math_to_instructions(expr, memory_map)
for instr in instructions:
print(instr)
print('; - - - - - - - - - -')