From a6f9617bd891074bba20cc1fc220e60a226e7fb4 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Fri, 2 Dec 2011 18:43:48 +0000 Subject: WIP for supporting ASM parsing and initialization of variables in @DATA --- AsmLine.py | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 AsmLine.py (limited to 'AsmLine.py') diff --git a/AsmLine.py b/AsmLine.py new file mode 100644 index 0000000..4561b30 --- /dev/null +++ b/AsmLine.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +"""Compiles C into assembly for the practicum processor (PP2) + +All rights reserved, you may not redistribute or use this program without prior +permission from Peter Wu or Xander Houtman. Use of this program is entirely +your own risk. In no circumstances can the authors of this program be held +responsible for any damage including, but not limited to, financial damage or +data loss. Modification of this program is not allowed without prior +permission. The generated output (assembly and messages) are not subject to +this license. +""" + +__author__ = "Peter Wu" +__copyright__ = "Copyright 2011, Peter Wu" +__credits__ = ["Peter Wu"] +__license__ = "Proprietary" +__version__ = "1.0" +__maintainer__ = "Peter Wu" +__email__ = "uwretep@gmail.com" + +import re +from Asm import Asm +from Registers import Registers +from NamedId import NamedId + +class AsmLine(object): + asm = Asm() + registers = Registers() + re_whitespace = re.compile("\s+") + def __init__(self, line, id_dict=None): + # for storing NamedId objects + self.id_dict = id_dict + self.label = "" + self.register = "" + self.operand = "" + line = line.split(";", 1)[0].strip() + + if ":" in line: + self.label, line = line.split(":", 1) + self.label = self.label.strip() + line = line.strip() + if self.asm.is_identifier(self.label): + # for easier label name manipulation + self.getNamedId(self.label) + else: + self.label = "" + line = label + ":" + line + + parts = self.re_whitespace.split(line, 1) + instruction = parts[0] + + if instruction in Asm.operators_binary: + # a label for sure + reg, operand = self.re_whitespace.split(parts[1], 1) + self.register = reg + self.setOperand(operand) + elif instruction in Asm.operators_branch: + # skip validation of reg for speed + self.register = parts[1] + elif instruction in Asm.operators_unary: + self.setOperand(parts[1]) + elif instruction in Asm.operators_misc_reg: + self.register = parts[1] + elif instruction in Asm.operators_misc_noreg: + # no args + pass + else: + raise RuntimeError("Unknown instruction '{}'".format(instruction)) + def setOperand(self, str): + """Sets the operand for this object either as a string or an identifier + object + """ + if self.id_dict is None: + self.operand = str + elif self.registers.is_register(str): + # register + self.operand = [str] + else: + if str.startswith("["): + # split by [ ] and +, grouping multiple occurences + self.operand = re.split("([\[\]+]+)", str) + else: + # value + self.operand = [str] + for i, part in enumerate(self.operand): + # skip empty elements, registers and [ ] + + if (part and not self.registers.is_register(part) and + part[0] not in "[]+"): + # turn named items in an object for easier manipulation of + # the names later + # if performance is an issue, you may want to skip the name + # validity check on the cost of NamedIds pollution + if self.asm.is_identifier(part): + self.operand[i] = self.getNamedId(part) + def getNamedId(self, name): + """Returns an NamedId object for keeping a track of all names at once + """ + # if there is no dictionary to store names, just return the name + if self.id_dict is None: + return name + if name not in self.id_dict: + self.id_dict[name] = NamedId(name) + return self.id_dict[name] + def __str__(self): + """Returns a line of assembly""" + line = "" + if self.label: + line += str(self.label) + ": " + line += self.instruction + if self.register: + line += " " + self.register + if self.operand: + # join all operand parts together + line += " " + "".join(str(elm) for elm in self.operand) -- cgit v1.2.1