interpreter.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. def unbleach(n):
  2. return n.replace(' ', 's').replace('\t', 't').replace('\n', 'n')
  3. # solution
  4. class White:
  5. def __init__(self):
  6. self.output = ''
  7. self.stack = []
  8. self.heap = {}
  9. self.input = ''
  10. self.index = 0
  11. self.input_index = 0
  12. self.input_list = []
  13. self.instruction = []
  14. self.input_str = ''
  15. self.command = {' ': self.push_to_stack,
  16. ' \t ': self.duplicate_value,
  17. ' \t\n': self.discard_value,
  18. ' \n ': self.duplicate_top,
  19. ' \n\t': self.swap,
  20. ' \n\n': self.discard_top,
  21. '\t ': self.adding,
  22. '\t \t': self.subtract,
  23. '\t \n': self.multiple,
  24. '\t \t ': self.division,
  25. '\t \t\t': self.division_part,
  26. '\t\t ': self.heap_store,
  27. '\t\t\t': self.heap_pop,
  28. '\t\n ': self.output_character,
  29. '\t\n \t': self.output_number,
  30. '\t\n\t ': self.read_char,
  31. '\t\n\t\t': self.read_number,
  32. '\n ': self.mark_location,
  33. '\n \t': self.call_subroutine,
  34. '\n \n': self.jump,
  35. '\n\t ': self.jump_stack,
  36. '\n\t\t': self.jump_stack_bzero,
  37. '\n\t\n': self.subroutine_end,
  38. '\n\n\n': self.end}
  39. self.command_par = {' ': 0,
  40. ' \t ': 0,
  41. ' \t\n': 0,
  42. '\n ': 1,
  43. '\n \t': 1,
  44. '\n \n': 1,
  45. '\n\t ': 1,
  46. '\n\t\t': 1}
  47. self.error_marker = False
  48. self.end = False
  49. def parsing_code(self):
  50. help_list = []
  51. item_set = {' ', '\t', '\n'}
  52. for i in range(len(self.input_str)):
  53. if self.input_str[i] in item_set:
  54. help_list.append(self.input_str[i])
  55. self.input_str = ''.join(help_list)
  56. while self.index < len(self.input_str) - 1:
  57. help_str, i = '', 0
  58. while self.index < len(self.input_str) and i < 5 and self.command.get(help_str) is None:
  59. help_str = help_str + self.input_str[self.index]
  60. i += 1
  61. self.index += 1
  62. if self.command.get(help_str) is None:
  63. self.index = self.index - i
  64. self.instruction.append(self.input_str[self.index])
  65. self.index += 1
  66. else:
  67. self.instruction.append(help_str)
  68. if self.command_par.get(help_str) is not None:
  69. help_list = []
  70. while self.input_str[self.index] != '\n':
  71. help_list.append(self.input_str[self.index])
  72. self.index += 1
  73. if self.command_par[help_str] == 0:
  74. self.instruction.append(self.parsing_number(help_list))
  75. else:
  76. self.instruction.append(self.parsing_label(help_list))
  77. self.index += 1
  78. self.index = 0
  79. def parsing_label(self, container):
  80. return ''.join(container)
  81. def parsing_number(self, container):
  82. number, place = 0, 0
  83. while len(container) > 1:
  84. x = container.pop()
  85. if ord(x) == 9:
  86. number += 2 ** place
  87. place += 1
  88. x = container.pop()
  89. if ord(x) == 9:
  90. number = -1 * number
  91. return number
  92. def command_check(self):
  93. i = 0
  94. while i < len(self.instruction):
  95. if self.command.get(self.instruction[i]) is None:
  96. raise Exception('Invalid command')
  97. if self.command_par.get(self.instruction[i]) is not None:
  98. i += 1
  99. i += 1
  100. def push_to_stack(self):
  101. self.index += 1
  102. self.stack.append(self.instruction[self.index])
  103. def duplicate_value(self):
  104. self.index += 1
  105. if len(self.stack) - 1 < self.instruction[self.index]:
  106. self.error_marker = True
  107. value = self.stack[len(self.stack) - self.instruction[self.index] - 1]
  108. self.stack.append(value)
  109. def discard_value(self):
  110. self.index += 1
  111. value = self.stack.pop()
  112. number = self.instruction[self.index]
  113. if number < 0 or number >= len(self.stack):
  114. self.stack = [value]
  115. else:
  116. for i in range(number):
  117. self.stack.pop()
  118. self.stack.append(value)
  119. def duplicate_top(self):
  120. value = self.stack[len(self.stack) - 1]
  121. self.stack.append(value)
  122. def swap(self):
  123. a = self.stack.pop()
  124. b = self.stack.pop()
  125. self.stack.append(a)
  126. self.stack.append(b)
  127. def discard_top(self):
  128. self.stack.pop()
  129. def adding(self):
  130. a = self.stack.pop()
  131. b = self.stack.pop()
  132. self.stack.append(a + b)
  133. def subtract(self):
  134. a = self.stack.pop()
  135. b = self.stack.pop()
  136. self.stack.append(b - a)
  137. def multiple(self):
  138. a = self.stack.pop()
  139. b = self.stack.pop()
  140. self.stack.append(b * a)
  141. def division(self):
  142. a = self.stack.pop()
  143. b = self.stack.pop()
  144. self.stack.append(b // a)
  145. def division_part(self):
  146. a = self.stack.pop()
  147. b = self.stack.pop()
  148. sign = a // abs(a)
  149. return self.stack.append(sign * abs(b % a))
  150. def heap_store(self):
  151. a = self.stack.pop()
  152. b = self.stack.pop()
  153. self.heap[b] = a
  154. def heap_pop(self):
  155. a = self.stack.pop()
  156. self.stack.append(self.heap[a])
  157. def output_character(self):
  158. self.output = self.output + chr(self.stack.pop())
  159. def output_number(self):
  160. self.output = self.output + str(self.stack.pop())
  161. def read_char(self):
  162. b = self.stack.pop()
  163. self.heap[b] = ord(self.input[self.input_index])
  164. self.input_index += 1
  165. def read_number(self):
  166. b = self.stack.pop()
  167. number_list = []
  168. while self.input_index < len(self.input) - 1 and self.input[self.input_index] != '\n':
  169. number_list.append(self.input[self.input_index])
  170. self.input_index += 1
  171. self.input_index += 1
  172. self.heap[b] = int(''.join(number_list))
  173. def mark_location(self):
  174. self.index += 1
  175. def label_location_check(self, label):
  176. quantity = 0
  177. for i in range(len(self.instruction) - 1):
  178. if self.instruction[i] == '\n ' and self.instruction[i + 1] == label:
  179. quantity += 1
  180. if quantity != 1:
  181. raise ValueError('Unknown or repeated label')
  182. def call_subroutine(self):
  183. index_help, flag = 0, 0
  184. while flag == 0:
  185. if self.instruction[index_help] == '\n ' and self.instruction[index_help + 1] == self.instruction[
  186. self.index + 1]:
  187. flag = 1
  188. index_help += 1
  189. mem = self.index + 1
  190. self.index = index_help + 1
  191. while self.instruction[self.index] != '\n\t\n':
  192. self.command[self.instruction[self.index]]()
  193. self.index += 1
  194. if self.instruction[self.index] == '\n\n\n':
  195. self.end = True
  196. break
  197. self.index = mem
  198. def jump(self):
  199. self.label_location_check(self.instruction[self.index + 1])
  200. index_help, flag = 0, 0
  201. self.index += 1
  202. while flag == 0:
  203. if self.instruction[index_help] == '\n ' and self.instruction[index_help + 1] == self.instruction[
  204. self.index]:
  205. flag = 1
  206. index_help += 1
  207. self.index = index_help
  208. def jump_stack(self):
  209. self.label_location_check(self.instruction[self.index + 1])
  210. a = self.stack.pop()
  211. self.index += 1
  212. if a == 0:
  213. index_help, flag = 0, 0
  214. while flag == 0:
  215. if self.instruction[index_help] == '\n ' and self.instruction[index_help + 1] == self.instruction[
  216. self.index]:
  217. flag = 1
  218. index_help += 1
  219. self.index = index_help
  220. def jump_stack_bzero(self):
  221. self.label_location_check(self.instruction[self.index + 1])
  222. a = self.stack.pop()
  223. self.index += 1
  224. if a < 0:
  225. index_help, flag = 0, 0
  226. while flag == 0:
  227. if self.instruction[index_help] == '\n ' and (self.instruction[index_help + 1]
  228. == self.instruction[self.index]):
  229. flag = 1
  230. index_help += 1
  231. self.index = index_help
  232. def subroutine_end(self):
  233. self.index += 1
  234. def end(self):
  235. pass
  236. def whitespace(code, inp=''):
  237. w = White()
  238. w.input_str = code
  239. w.input = inp
  240. w.parsing_code()
  241. w.command_check()
  242. while w.instruction[w.index] != '\n\n\n':
  243. w.command[w.instruction[w.index]]()
  244. if w.error_marker is True:
  245. raise Exception('stack index out of range')
  246. if w.end is True:
  247. return w.output
  248. w.index += 1
  249. return w.output
  250. with open('./WS/example.ws') as source:
  251. print(whitespace(source.read()))