Skip to content

Instantly share code, notes, and snippets.

@Jragon
Last active October 27, 2018 16:37
Show Gist options
  • Save Jragon/2d3ebb09934b2d82de2d6e13a3c1c459 to your computer and use it in GitHub Desktop.
Save Jragon/2d3ebb09934b2d82de2d6e13a3c1c459 to your computer and use it in GitHub Desktop.
import re
import collections
variableAssignmentRegex = re.compile(r"([a-zA-Z_]+)\s*=\s*(\d*)")
commandRegex = re.compile(r"^(:\w+:)?\s*([A-Z]+)\s*([-\w]+)?(')?")
jumpRegex = re.compile(r"(C[FB][\+\?])(:\w+:)")
variableInitFormat = "N{} {}"
lineerror = "Error in line [{}]: {}"
variables = collections.OrderedDict() # {varname: initialValue}
labels = collections.OrderedDict() # {labelname: commandLine}
commands = []
romout = []
with open('input.txt') as rom:
for lineno, line in enumerate(rom, 1):
if line.startswith('#') or line.isspace():
continue
if '=' in line:
varmatch = variableAssignmentRegex.match(line)
if varmatch is None:
print(lineerror.format(lineno, 'Varmatch failed'))
continue
variables[varmatch.group(1).strip()] = varmatch.group(2)
else:
if line.strip() in ['-', '+', '/', '*']:
commands.append(line.strip())
continue
elif 'CB' in line or 'CF' in line:
commands.append(line.strip())
continue
match = commandRegex.match(line)
if match is None:
print(lineerror.format(lineno, 'commatch failed'))
continue
if match.group(3) is not None:
try:
literal = int(match.group(3))
except ValueError:
literal = None
if literal is not None: # replace literal with variable
variables[str(literal)] = literal
commands.append(line.strip())
for i, (varName, value) in enumerate(variables.items()):
# add assignment to variables
romout.append(variableInitFormat.format(i, value))
for index, command in enumerate(commands):
if command in ['-', '+', '/', '*']:
romout.append(command)
continue
if 'CB' in command or 'CF' in command:
romout.append(command)
continue
match = commandRegex.match(command)
if match is None:
print("Error matching command - shouldn't happen idk\n", command, index)
continue
if match.group(3) in variables.keys(): # replace var with memloc
romout.append("{} {}{}".format(match.group(2),
list(variables.keys()).index(match.group(3)),
match.group(4) if match.group(4) is not None else '')) # add the '
else:
romout.append(match.group(2))
if match.group(1): # if there's a label
labels[match.group(1)] = len(romout) - 1
# sort out labels
for lineno, line in enumerate(romout):
if ':' not in line:
continue
match = jumpRegex.match(line)
if match is None:
print(lineerror.format(lineno, "jump regex error : " + line))
continue
# calculate how many instructions to go back
if match.group(2) in labels.keys():
if 'CB' in line:
diff = lineno - labels[match.group(2)]
else:
diff = labels[match.group(2)] - lineno - 1
romout[lineno] = ("{}{}".format(match.group(1), diff))
for line in romout:
print(line)
A = 0
B = 0
C = 0
D = 0
# if D = 0
+
L D
L -1
CF?:ifDZero:
CF+:DNotZero:
:ifDZero: B
CF+:END:
# A = B + C
:DNotZero: L B
L C
S A
/
# A = A / D
L A
L D
S A'
# if 100 - A < 0
-
L 100
L A
CF?:AGreaterThan100:
CF+:END:
:AGreaterThan100: L 100
L 0
S A
:END: B
N0 0
N1 0
N2 0
N3 0
N4 -1
N5 100
N6 0
+
L 3
L 4
CF?1
CF+2
B
CF+15
L 1
L 2
S 0
/
L 0
L 3
S 0'
-
L 5
L 0
CF?1
CF+3
L 5
L 6
S 0
B
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment