bs_compiler.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #!/usr/bin/python3
  2. import argparse
  3. import sys
  4. from os import path
  5. ch_add = {'+'}
  6. ch_sub = {'-'}
  7. ch_left = {'<'}
  8. ch_right = {'>'}
  9. ch_print = {'.'}
  10. ch_start = {'['}
  11. ch_stop = {']'}
  12. def compileBF(filename):
  13. program = []
  14. # Init program
  15. # $ra: Current value
  16. # $rb: ??
  17. # $rc: Memory pointer
  18. # $re: The +/- 1 value
  19. program.append("CPY $rc 0xFF")
  20. program.append("CPY $re 1")
  21. program.append("memInitStart:")
  22. program.append("JEQ $ra $rc memInitFinish")
  23. program.append("SW $rb $ra")
  24. program.append("ADD $ra $re")
  25. program.append("JMP memInitStart")
  26. program.append("memInitFinish:")
  27. program.append("CPY $rb 0")
  28. program.append("CPY $ra $rb")
  29. program.append("CPY $rc $rb")
  30. f = open(filename, 'r')
  31. pc = 0
  32. nc = 0
  33. lc = 0
  34. rc = 0
  35. nodePrev = []
  36. nodeCount = 0
  37. while 1:
  38. c = f.read(1)
  39. if c == '':
  40. break
  41. if c in ch_add:
  42. pc += 1
  43. elif pc > 0:
  44. program.append(f"CPY $re {pc}")
  45. pc = 0
  46. program.append("ADD $ra $re")
  47. if c in ch_sub:
  48. nc += 1
  49. elif nc > 0:
  50. program.append(f"CPY $re {nc}")
  51. nc = 0
  52. program.append("SUB $ra $re")
  53. if c in ch_right:
  54. rc += 1
  55. elif rc > 0:
  56. program.append("SW $ra $rc")
  57. program.append(f"CPY $re {rc}")
  58. program.append("ADD $rc $re")
  59. program.append("LW $ra $rc")
  60. rc = 0
  61. if c in ch_left:
  62. lc += 1
  63. elif lc > 0:
  64. program.append("SW $ra $rc")
  65. program.append(f"CPY $re {lc}")
  66. program.append("SUB $rc $re")
  67. program.append("LW $ra $rc")
  68. lc = 0
  69. if c in ch_print:
  70. program.append("CPY $re 0xFF")
  71. program.append("SW $ra $re")
  72. if c in ch_start:
  73. nodePrev.append(nodeCount)
  74. program.append(f"node{nodeCount:04d}s:")
  75. program.append(f"JEQ $ra $rb node{nodeCount:04d}e")
  76. nodeCount += 1
  77. if c in ch_stop:
  78. node = nodePrev.pop(-1)
  79. program.append(f"JMP node{node:04d}s")
  80. program.append(f"node{node:04d}e:")
  81. f.close()
  82. return program
  83. if __name__ == '__main__':
  84. parser = argparse.ArgumentParser(description='Assembly compiler', add_help=True)
  85. parser.add_argument('file', help='Files to compile')
  86. # parser.add_argument('-t', '--output_type', choices=['asm', 'mem', 'binary'], default='mem', help='Output type')
  87. parser.add_argument('-o', '--output', help='Output file')
  88. parser.add_argument('-f', '--force', action='store_true', help='Force override output file')
  89. args = parser.parse_args(sys.argv[1:])
  90. if not path.isfile(args.file):
  91. print(f'No file {args.file}!')
  92. sys.exit(1)
  93. asm = compileBF(args.file)
  94. data = '\n'.join(asm)
  95. if args.output and (not path.isfile(args.output) or args.force):
  96. with open(args.output, 'w') as o:
  97. o.write(data)
  98. elif args.output is None:
  99. print(data)