|
|
@@ -0,0 +1,115 @@
|
|
|
+#!/usr/bin/python3
|
|
|
+
|
|
|
+import argparse
|
|
|
+import sys
|
|
|
+from os import path
|
|
|
+
|
|
|
+
|
|
|
+ch_add = {'+'}
|
|
|
+ch_sub = {'-'}
|
|
|
+ch_left = {'<'}
|
|
|
+ch_right = {'>'}
|
|
|
+ch_print = {'.'}
|
|
|
+ch_start = {'['}
|
|
|
+ch_stop = {']'}
|
|
|
+
|
|
|
+def compileBF(filename):
|
|
|
+ program = []
|
|
|
+ # Init program
|
|
|
+ # $ra: Current value
|
|
|
+ # $rb: ??
|
|
|
+ # $rc: Memory pointer
|
|
|
+ # $re: The +/- 1 value
|
|
|
+
|
|
|
+ program.append("CPY $rc 0xFF")
|
|
|
+ program.append("CPY $re 1")
|
|
|
+ program.append("memInitStart:")
|
|
|
+ program.append("JEQ $ra $rc memInitFinish")
|
|
|
+ program.append("SW $rb $ra")
|
|
|
+ program.append("ADD $ra $re")
|
|
|
+ program.append("JMP memInitStart")
|
|
|
+ program.append("memInitFinish:")
|
|
|
+ program.append("CPY $rb 0")
|
|
|
+ program.append("CPY $ra $rb")
|
|
|
+ program.append("CPY $rc $rb")
|
|
|
+
|
|
|
+ f = open(filename, 'r')
|
|
|
+ pc = 0
|
|
|
+ nc = 0
|
|
|
+ lc = 0
|
|
|
+ rc = 0
|
|
|
+ nodePrev = []
|
|
|
+ nodeCount = 0
|
|
|
+ while 1:
|
|
|
+ c = f.read(1)
|
|
|
+ if c == '':
|
|
|
+ break
|
|
|
+ if c in ch_add:
|
|
|
+ pc += 1
|
|
|
+ elif pc > 0:
|
|
|
+ program.append(f"CPY $re {pc}")
|
|
|
+ pc = 0
|
|
|
+ program.append("ADD $ra $re")
|
|
|
+
|
|
|
+ if c in ch_sub:
|
|
|
+ nc += 1
|
|
|
+ elif nc > 0:
|
|
|
+ program.append(f"CPY $re {nc}")
|
|
|
+ nc = 0
|
|
|
+ program.append("SUB $ra $re")
|
|
|
+
|
|
|
+ if c in ch_right:
|
|
|
+ rc += 1
|
|
|
+ elif rc > 0:
|
|
|
+ program.append("SW $ra $rc")
|
|
|
+ program.append(f"CPY $re {rc}")
|
|
|
+ program.append("ADD $rc $re")
|
|
|
+ program.append("LW $ra $rc")
|
|
|
+ rc = 0
|
|
|
+
|
|
|
+ if c in ch_left:
|
|
|
+ lc += 1
|
|
|
+ elif lc > 0:
|
|
|
+ program.append("SW $ra $rc")
|
|
|
+ program.append(f"CPY $re {lc}")
|
|
|
+ program.append("SUB $rc $re")
|
|
|
+ program.append("LW $ra $rc")
|
|
|
+ lc = 0
|
|
|
+
|
|
|
+ if c in ch_print:
|
|
|
+ program.append("CPY $re 0xFF")
|
|
|
+ program.append("SW $ra $re")
|
|
|
+
|
|
|
+ if c in ch_start:
|
|
|
+ nodePrev.append(nodeCount)
|
|
|
+ program.append(f"node{nodeCount:04d}s:")
|
|
|
+ program.append(f"JEQ $ra $rb node{nodeCount:04d}e")
|
|
|
+ nodeCount += 1
|
|
|
+
|
|
|
+ if c in ch_stop:
|
|
|
+ node = nodePrev.pop(-1)
|
|
|
+ program.append(f"JMP node{node:04d}s")
|
|
|
+ program.append(f"node{node:04d}e:")
|
|
|
+
|
|
|
+ f.close()
|
|
|
+ return program
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == '__main__':
|
|
|
+ parser = argparse.ArgumentParser(description='Assembly compiler', add_help=True)
|
|
|
+ parser.add_argument('file', help='Files to compile')
|
|
|
+ # parser.add_argument('-t', '--output_type', choices=['asm', 'mem', 'binary'], default='mem', help='Output type')
|
|
|
+ parser.add_argument('-o', '--output', help='Output file')
|
|
|
+ parser.add_argument('-f', '--force', action='store_true', help='Force override output file')
|
|
|
+ args = parser.parse_args(sys.argv[1:])
|
|
|
+ if not path.isfile(args.file):
|
|
|
+ print(f'No file {args.file}!')
|
|
|
+ sys.exit(1)
|
|
|
+ asm = compileBF(args.file)
|
|
|
+ data = '\n'.join(asm)
|
|
|
+ if args.output and (not path.isfile(args.output) or args.force):
|
|
|
+ with open(args.output, 'w') as o:
|
|
|
+ o.write(data)
|
|
|
+ elif args.output is None:
|
|
|
+ print(data)
|
|
|
+
|