summaryrefslogtreecommitdiff
path: root/AsmParser.py
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-12-02 18:43:48 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-12-02 18:43:48 +0000
commita6f9617bd891074bba20cc1fc220e60a226e7fb4 (patch)
treed5634a2db32c64275aa593d8a13ca066270c3ba9 /AsmParser.py
parent45f82a1acf465c8420690a578192cdabf4bc7c04 (diff)
downloadpp2cc-a6f9617bd891074bba20cc1fc220e60a226e7fb4.tar.gz
WIP for supporting ASM parsing and initialization of variables in @DATA
Diffstat (limited to 'AsmParser.py')
-rw-r--r--AsmParser.py88
1 files changed, 55 insertions, 33 deletions
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]