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 --- AsmParser.py | 88 +++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 33 deletions(-) (limited to 'AsmParser.py') diff --git a/AsmParser.py b/AsmParser.py index 40ad384..4ab25ed 100644 --- a/AsmParser.py +++ b/AsmParser.py @@ -18,7 +18,8 @@ __version__ = "1.0" __maintainer__ = "Peter Wu" __email__ = "uwretep@gmail.com" -from Asm import Asm +from AsmLine import AsmLine +from NamedId import NamedId import re class AsmParser(object): @@ -27,13 +28,14 @@ class AsmParser(object): self.parent = parent self.defined_names = parent.defined_names else: + self.parent = None self.data = [] self.code = [] - # defined labels for the assembly files. key: label, value: mapped - # label (to avoid name clashes with the other code) - self.labels = {} - # defined words/storage - self.defined_names = [] + # defined labels for the assembly files + self.labels = [] + # dictionary for holding NamedId objects for defined labels and + # identifiers (variables) + self.defined_names = {} # valid values: None, DATA and CODE self.in_section = None @@ -41,7 +43,6 @@ class AsmParser(object): self.constants = {} self.re_whitespace = re.compile("\s+") - self.asm = Asm() file = open(filename, "rU") while True: @@ -52,6 +53,11 @@ class AsmParser(object): else: break file.close() + # substitute constants and remove the name + for name, value in self.constants.iteritems(): + if name in self.defined_names: + self.defined_names[name].rename(value) + del self.defined_names[name] def parseLine(self, line): """Processes the a line from assembly""" if line.startswith("@"): @@ -80,7 +86,7 @@ class AsmParser(object): raise RuntimeError("Unrecognized command '{}'".format(cmd)) elif self.in_section in ("DATA", "CODE"): match = re.split(self.re_whitespace, line, 2) - if len(match) == 2: + if len(match) == 3: name, what, data = match if what == "EQU": self.setConstant(name, data) @@ -88,14 +94,23 @@ class AsmParser(object): elif what in ("DS", "DW"): if self.in_section == "CODE": raise RuntimeError("DS or DW found in @CODE section") - self.addName(name) - self.addData(line) + # we shouldn't need to change the name for DS/DW stuff + #self.addName(name) + if what == "DS": + # DS initializes names with zero, let's convert it to + # DW to make it compatible with the Parser + self.addData(name, [0 for x in range(0, int(data))]) + else: + self.addData(name, data.split(",")) + line = "" if line: if self.in_section == "DATA": - raise RuntimeError("Found non definition data in @DATA") - label = self.asm.get_label(line) - self.addLabel(label) - self.addCode(line) + raise RuntimeError("Found non-definition data in @DATA, " + "namely: " + line) + lineobj = AsmLine(line, id_dict=self.defined_names) + if lineobj.label: + self.labels.append(lineobj.label) + self.addCode(lineobj) else: # ignore other lines pass @@ -111,37 +126,44 @@ class AsmParser(object): self.parent.addCode(line) else: self.code.append(line) - def addData(self, line): - """Add a line to the @DATA section""" + def addData(self, name, words): + """Define a name in the @DATA section initialized with words + + Keyword arguments: + name -- The name as it appears in the @DATA section + words -- A list of words to be initialized + """ if self.parent: - self.parent.addData(line) + self.parent.addData(name, words) + elif name in self.data: + raise RuntimeError("Redefinition of '{}'".format(name)) else: - self.data.append(line) + self.data[name] = words def evaluateConstant(self, expression): """Evaluates a constant expression in an EQU""" if not expression.isdigit(): raise RuntimeError("I am lazy and do not support values other than" " digits in an EQU") return expression - def addLabel(self, label): - """Adds a label to the list of labels""" - if self.parent: - self.parent.addLabel(label) - elif label in self.labels: - raise RuntimeError("Label '{}' is already defined".format(label)) - else: - self.labels[label] = label def addName(self, name): - """Adds a name to the list of define words/ storage""" + """Adds a NamedId object for the name of a label or variable to the + list of defined names + """ if self.parent: self.parent.addName(name) elif name in self.defined_names: raise RuntimeError("Name '{}' is already defined".format(name)) else: - self.defined_names.append(name) - def mapLabel(self, label, new_label): - """Renames a label""" - if not name in self.labels: + self.defined_names[name] = NamedId(name) + def renameId(self, name, new_name): + """Renames an identifier for a label or variable""" + if not name in self.defined_names: raise RuntimeError("Attempt to rename an undefined '{}' to '{}'" - .format(label, new_label)) - self.labels[label] = new_label + .format(name, new_name)) + self.defined_names[name].rename(new_name) + def getCodeLines(self): + """Returns the known assembly lines for the @CODE section as a list""" + if self.parent: + raise RuntimeError("You can only get the lines for @CODE from the" + " root node") + return [elm for elm in self.code] -- cgit v1.2.1