| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- def unbleach(n):
- return n.replace(' ', 's').replace('\t', 't').replace('\n', 'n')
- # solution
- class White:
- def __init__(self):
- self.output = ''
- self.stack = []
- self.heap = {}
- self.input = ''
- self.index = 0
- self.input_index = 0
- self.input_list = []
- self.instruction = []
- self.input_str = ''
- self.command = {' ': self.push_to_stack,
- ' \t ': self.duplicate_value,
- ' \t\n': self.discard_value,
- ' \n ': self.duplicate_top,
- ' \n\t': self.swap,
- ' \n\n': self.discard_top,
- '\t ': self.adding,
- '\t \t': self.subtract,
- '\t \n': self.multiple,
- '\t \t ': self.division,
- '\t \t\t': self.division_part,
- '\t\t ': self.heap_store,
- '\t\t\t': self.heap_pop,
- '\t\n ': self.output_character,
- '\t\n \t': self.output_number,
- '\t\n\t ': self.read_char,
- '\t\n\t\t': self.read_number,
- '\n ': self.mark_location,
- '\n \t': self.call_subroutine,
- '\n \n': self.jump,
- '\n\t ': self.jump_stack,
- '\n\t\t': self.jump_stack_bzero,
- '\n\t\n': self.subroutine_end,
- '\n\n\n': self.end}
- self.command_par = {' ': 0,
- ' \t ': 0,
- ' \t\n': 0,
- '\n ': 1,
- '\n \t': 1,
- '\n \n': 1,
- '\n\t ': 1,
- '\n\t\t': 1}
- self.error_marker = False
- self.end = False
- def parsing_code(self):
- help_list = []
- item_set = {' ', '\t', '\n'}
- for i in range(len(self.input_str)):
- if self.input_str[i] in item_set:
- help_list.append(self.input_str[i])
- self.input_str = ''.join(help_list)
- while self.index < len(self.input_str) - 1:
- help_str, i = '', 0
- while self.index < len(self.input_str) and i < 5 and self.command.get(help_str) is None:
- help_str = help_str + self.input_str[self.index]
- i += 1
- self.index += 1
- if self.command.get(help_str) is None:
- self.index = self.index - i
- self.instruction.append(self.input_str[self.index])
- self.index += 1
- else:
- self.instruction.append(help_str)
- if self.command_par.get(help_str) is not None:
- help_list = []
- while self.input_str[self.index] != '\n':
- help_list.append(self.input_str[self.index])
- self.index += 1
- if self.command_par[help_str] == 0:
- self.instruction.append(self.parsing_number(help_list))
- else:
- self.instruction.append(self.parsing_label(help_list))
- self.index += 1
- self.index = 0
- def parsing_label(self, container):
- return ''.join(container)
- def parsing_number(self, container):
- number, place = 0, 0
- while len(container) > 1:
- x = container.pop()
- if ord(x) == 9:
- number += 2 ** place
- place += 1
- x = container.pop()
- if ord(x) == 9:
- number = -1 * number
- return number
- def command_check(self):
- i = 0
- while i < len(self.instruction):
- if self.command.get(self.instruction[i]) is None:
- raise Exception('Invalid command')
- if self.command_par.get(self.instruction[i]) is not None:
- i += 1
- i += 1
- def push_to_stack(self):
- self.index += 1
- self.stack.append(self.instruction[self.index])
- def duplicate_value(self):
- self.index += 1
- if len(self.stack) - 1 < self.instruction[self.index]:
- self.error_marker = True
- value = self.stack[len(self.stack) - self.instruction[self.index] - 1]
- self.stack.append(value)
- def discard_value(self):
- self.index += 1
- value = self.stack.pop()
- number = self.instruction[self.index]
- if number < 0 or number >= len(self.stack):
- self.stack = [value]
- else:
- for i in range(number):
- self.stack.pop()
- self.stack.append(value)
- def duplicate_top(self):
- value = self.stack[len(self.stack) - 1]
- self.stack.append(value)
- def swap(self):
- a = self.stack.pop()
- b = self.stack.pop()
- self.stack.append(a)
- self.stack.append(b)
- def discard_top(self):
- self.stack.pop()
- def adding(self):
- a = self.stack.pop()
- b = self.stack.pop()
- self.stack.append(a + b)
- def subtract(self):
- a = self.stack.pop()
- b = self.stack.pop()
- self.stack.append(b - a)
- def multiple(self):
- a = self.stack.pop()
- b = self.stack.pop()
- self.stack.append(b * a)
- def division(self):
- a = self.stack.pop()
- b = self.stack.pop()
- self.stack.append(b // a)
- def division_part(self):
- a = self.stack.pop()
- b = self.stack.pop()
- sign = a // abs(a)
- return self.stack.append(sign * abs(b % a))
- def heap_store(self):
- a = self.stack.pop()
- b = self.stack.pop()
- self.heap[b] = a
- def heap_pop(self):
- a = self.stack.pop()
- self.stack.append(self.heap[a])
- def output_character(self):
- self.output = self.output + chr(self.stack.pop())
- def output_number(self):
- self.output = self.output + str(self.stack.pop())
- def read_char(self):
- b = self.stack.pop()
- self.heap[b] = ord(self.input[self.input_index])
- self.input_index += 1
- def read_number(self):
- b = self.stack.pop()
- number_list = []
- while self.input_index < len(self.input) - 1 and self.input[self.input_index] != '\n':
- number_list.append(self.input[self.input_index])
- self.input_index += 1
- self.input_index += 1
- self.heap[b] = int(''.join(number_list))
- def mark_location(self):
- self.index += 1
- def label_location_check(self, label):
- quantity = 0
- for i in range(len(self.instruction) - 1):
- if self.instruction[i] == '\n ' and self.instruction[i + 1] == label:
- quantity += 1
- if quantity != 1:
- raise ValueError('Unknown or repeated label')
- def call_subroutine(self):
- index_help, flag = 0, 0
- while flag == 0:
- if self.instruction[index_help] == '\n ' and self.instruction[index_help + 1] == self.instruction[
- self.index + 1]:
- flag = 1
- index_help += 1
- mem = self.index + 1
- self.index = index_help + 1
- while self.instruction[self.index] != '\n\t\n':
- self.command[self.instruction[self.index]]()
- self.index += 1
- if self.instruction[self.index] == '\n\n\n':
- self.end = True
- break
- self.index = mem
- def jump(self):
- self.label_location_check(self.instruction[self.index + 1])
- index_help, flag = 0, 0
- self.index += 1
- while flag == 0:
- if self.instruction[index_help] == '\n ' and self.instruction[index_help + 1] == self.instruction[
- self.index]:
- flag = 1
- index_help += 1
- self.index = index_help
- def jump_stack(self):
- self.label_location_check(self.instruction[self.index + 1])
- a = self.stack.pop()
- self.index += 1
- if a == 0:
- index_help, flag = 0, 0
- while flag == 0:
- if self.instruction[index_help] == '\n ' and self.instruction[index_help + 1] == self.instruction[
- self.index]:
- flag = 1
- index_help += 1
- self.index = index_help
- def jump_stack_bzero(self):
- self.label_location_check(self.instruction[self.index + 1])
- a = self.stack.pop()
- self.index += 1
- if a < 0:
- index_help, flag = 0, 0
- while flag == 0:
- if self.instruction[index_help] == '\n ' and (self.instruction[index_help + 1]
- == self.instruction[self.index]):
- flag = 1
- index_help += 1
- self.index = index_help
- def subroutine_end(self):
- self.index += 1
- def end(self):
- pass
- def whitespace(code, inp=''):
- w = White()
- w.input_str = code
- w.input = inp
- w.parsing_code()
- w.command_check()
- while w.instruction[w.index] != '\n\n\n':
- w.command[w.instruction[w.index]]()
- if w.error_marker is True:
- raise Exception('stack index out of range')
- if w.end is True:
- return w.output
- w.index += 1
- return w.output
- with open('./WS/example.ws') as source:
- print(whitespace(source.read()))
|