def test_empty_stack_copy(self) -> None: s = Stack() self.assertEqual(str(s.contents()), '[]') r = s.copy() print("Type s = %s, Type r = %s" % (type(s), type(r))) x = s.tos() y = r.tos() self.assertEqual(x, y) self.assertEqual(len(s), 0) self.assertEqual(len(r), 0)
def make_ladder(self): queue = Queue() stack = Stack() stack.push(self.w1) queue.enqueue(stack) seen = set() seen.add(self.w1) while not queue.isEmpty(): stack = queue.dequeue() top = stack.peek() for word in gen_words(top): if word in self.wordlist and word not in seen: duplicate = stack.copy() duplicate.push(word) if word == self.w2: return duplicate queue.enqueue(duplicate) seen.add(word)
def test_stack_copy(self) -> None: s = Stack() s.push(1) s.push(2) s.push(3) self.assertEqual(str(s.contents()), '[1, 2, 3]') r = s.copy() #print("Type s = %s, Type r = %s" % (type(s),type(r))) self.assertEqual(type(s), type(r)) x = s.tos() y = r.tos() self.assertEqual(x, y) self.assertEqual(s.pop(), r.pop()) self.assertEqual(s.pop(), r.pop()) self.assertEqual(s.pop(), r.pop()) self.assertEqual(len(s), len(s))
class AnalyserLr: def __init__( self, non_terminals=('E', 'T', 'F'), terminals=('id', '+', '*', '(', ')', '$'), ): self.non_terminals = non_terminals self.terminals = terminals self.stack = Stack() self.table = {} self.state = '0' self.action = self.terminals[0] self.create_table() self.derivations = list() self.create_derivations() self.entry_idx = 0 self.entry = '' self.goto = None self.state = '0' self.output = [] self.actual_value = None self.actual_production_idx = None self.actual_production = None self.accepted = False def analyse(self, entry): print_lt = [] if not entry: raise Exception('Empty entry') self.reset_entry(entry) self.stack.push(('0', '')) while not self.accepted: print_stack = self.stack.copy() # (0) print_entry = self.get_cur_entry() action = self.get_current_action() # id state = self.state # 0 goto = self.goto # None # print(1) # print(goto) state, action, goto, actual_value = self.update( state, action, goto) # s = 5, acti = *, None, d5 self.state = state self.goto = goto # print((print_stack, print_entry, self.get_actual_action_str(), self.get_printable_got(goto))) print_lt.append( (print_stack, print_entry, self.get_actual_action_str(), self.get_printable_goto(goto))) self.print_table(print_lt) def print_table(self, print_lt): len_of_col = [85, 46, 15, 17] should_print = True for row in print_lt: if should_print: stack, entry, action_str, goto = row stk = '$ ' for elm in stack: if not elm[1]: stk += elm[0] + ' ' else: stk += '(%s, %s)' % (elm[0], elm[1]) stack = stk entry = ' '.join(entry) if goto: should_print = False print(('| {:%d}| {:%d}| {:%d}| {:%d}|' % (len_of_col[0], len_of_col[1], len_of_col[2], len_of_col[3])).format(stack, entry, action_str, goto)) else: should_print = True def get_printable_goto(self, goto): if goto: # todo fix try: elm = self.get_elm_from_table(self.state, goto) except: elm = 2 return 'Goto (%s, %s) = %s' % (self.state, goto, elm) else: return '' def get_actual_action_str(self): if self.actual_production: return self.actual_value + ' (' + get_prod_str( self.actual_production) + ')' else: return self.actual_value def get_cur_entry(self): return self.entry[self.entry_idx:] def get_elm_from_table(self, state, action): key = state + action value = self.table[key] return value def reset_entry(self, entry): self.entry = entry self.entry_idx = 0 def increase_idx(self): self.entry_idx += 1 def get_current_action(self): return self.entry[self.entry_idx] def update(self, state, action, goto=None): self.actual_production_idx = None self.actual_production = None if goto is None: if action is None: raise Exception('Goto and action none') try: key = state + action except: print(1) if key not in self.table: raise Exception('Compilation Error: key not in table') # value = 'act' # else: value = self.table[key] self.actual_value = value if value == 'act': self.accepted = True return state, action, goto, self.actual_value elif value[0] == 'd': new_state = value[1:] self.increase_idx() action = self.get_current_action() state = new_state goto = goto self.stack.push((state, self.actual_value)) return state, action, goto, self.actual_value elif value[0] == 'r': derivation_first_part = self.get_derivation_first_part( value[1:]) self.actual_production_idx = value[1:] self.actual_production = self.derivations[int(value[1:])] goto = derivation_first_part for i in range(len(self.actual_production[1])): self.stack.pop() state = self.stack.top()[0] return state, action, goto, self.actual_value else: key = state + goto if key not in self.table: raise Exception('Compilation Error: key not in table') # self.stack.pop() # state = self.stack.top()[0] # key = state + goto value = self.table[key] self.actual_value = value new_state = value state = new_state self.stack.push((state, goto)) goto = None return state, action, goto, self.actual_value def get_derivation_first_part(self, number_str): return self.derivations[int(number_str)][0] def create_derivations(self): self.derivations = [] self.derivations.append(None) self.derivations.append(('E', ['E', '+', 'T'])) self.derivations.append(('E', ['T'])) self.derivations.append(('T', ['T', '*', 'F'])) self.derivations.append(('T', ['F'])) self.derivations.append(('F', ['(', 'E', ')'])) self.derivations.append(('F', ['id'])) def create_table(self): self.table = dict() self.table['0' + 'id'] = 'd5' self.table['4' + 'id'] = 'd5' self.table['6' + 'id'] = 'd5' self.table['7' + 'id'] = 'd5' self.table['1' + '+'] = 'd6' self.table['2' + '+'] = 'r2' self.table['3' + '+'] = 'r4' self.table['5' + '+'] = 'r6' self.table['8' + '+'] = 'd6' self.table['9' + '+'] = 'r1' self.table['10' + '+'] = 'r3' self.table['11' + '+'] = 'r5' self.table['2' + '*'] = 'd7' self.table['3' + '*'] = 'r4' self.table['5' + '*'] = 'r6' self.table['9' + '*'] = 'd7' self.table['10' + '*'] = 'r3' self.table['11' + '*'] = 'r5' self.table['0' + '('] = 'd4' self.table['4' + '('] = 'd4' self.table['6' + '('] = 'd4' self.table['7' + '('] = 'd4' self.table['2' + ')'] = 'r2' self.table['3' + ')'] = 'r4' self.table['5' + ')'] = 'r6' self.table['8' + ')'] = 'd11' self.table['9' + ')'] = 'r1' self.table['10' + ')'] = 'r3' self.table['11' + ')'] = 'r5' self.table['1' + '$'] = 'act' self.table['2' + '$'] = 'r2' self.table['3' + '$'] = 'r4' self.table['5' + '$'] = 'r6' self.table['9' + '$'] = 'r1' self.table['10' + '$'] = 'r3' self.table['11' + '$'] = 'r5' self.table['0' + 'E'] = '1' self.table['4' + 'E'] = '8' self.table['0' + 'T'] = '2' self.table['4' + 'T'] = '2' self.table['6' + 'T'] = '9' self.table['0' + 'F'] = '3' self.table['4' + 'F'] = '3' self.table['6' + 'F'] = '3' self.table['7' + 'F'] = '10'
class Analyser: def __init__(self): self.end_atom = END_ATOM self.atoms = ['id', '+', '*', '(', ')', self.end_atom] self.non_terminals = ['E', "E'", 'T', "T'", 'F'] self.stack = Stack() self.entry = [self.end_atom] self.actual_char = self.end_atom self.actual_char_idx = 0 self.table = self.__create_table() def analyse(self, entry): if not self.non_terminals: raise Exception('non terminals are empty') if not self.entry: raise Exception('empty entry') self.__reset_entry(entry) self.stack.push(self.end_atom) self.stack.push(self.non_terminals[0]) self.__print_title() while not self.stack.is_empty(): actual_production = self.stack.top() actual_char = self.__get_actual_char() initial_stack = self.stack.copy() initial_entry = self.__get_entry_state() if self.__is_non_terminal(actual_production): self.stack.pop() actual_actions = Expand_action next_productions = self.table[actual_production + actual_char] if not next_productions: print("Compilation Error") print(actual_production) print(actual_char) print(self.stack.s) return for production in next_productions[::-1]: if production != epsilon: self.stack.push(production) else: actual_actions = unstack_action next_productions = None self.__next_char() self.stack.pop() self.__print_current_action(initial_stack, initial_entry, actual_actions, actual_production, next_productions) self.__print_success_finish() def __get_entry_state(self): return self.entry[self.actual_char_idx:] def __is_non_terminal(self, prod): return prod in self.non_terminals def __set_entry(self, entry): self.entry = entry def __get_actual_char(self): return self.entry[self.actual_char_idx] def __next_char(self): if self.actual_char_idx < len(self.entry) - 1: self.actual_char_idx += 1 return self.entry[self.actual_char_idx] def __reset_entry(self, entry=[END_ATOM]): self.entry = entry self.actual_char = self.entry[0] self.actual_char_idx = 0 def __create_table(self): self.table = dict() self.table[self.non_terminals[0] + self.atoms[0]] = ['T', "E'"] self.table[self.non_terminals[1] + self.atoms[0]] = [] self.table[self.non_terminals[2] + self.atoms[0]] = ['F', "T'"] self.table[self.non_terminals[3] + self.atoms[0]] = [] self.table[self.non_terminals[4] + self.atoms[0]] = ['id'] self.table[self.non_terminals[0] + self.atoms[1]] = [] self.table[self.non_terminals[1] + self.atoms[1]] = ['+', 'T', "E'"] self.table[self.non_terminals[2] + self.atoms[1]] = [] self.table[self.non_terminals[3] + self.atoms[1]] = [epsilon] self.table[self.non_terminals[4] + self.atoms[1]] = [] self.table[self.non_terminals[0] + self.atoms[2]] = [] self.table[self.non_terminals[1] + self.atoms[2]] = [] self.table[self.non_terminals[2] + self.atoms[2]] = [] self.table[self.non_terminals[3] + self.atoms[2]] = ['*', 'F', "T'"] self.table[self.non_terminals[4] + self.atoms[2]] = [] self.table[self.non_terminals[0] + self.atoms[3]] = ['T', "E'"] self.table[self.non_terminals[1] + self.atoms[3]] = [] self.table[self.non_terminals[2] + self.atoms[3]] = ['F', "T'"] self.table[self.non_terminals[3] + self.atoms[3]] = [] self.table[self.non_terminals[4] + self.atoms[3]] = ['(', 'E', ')'] self.table[self.non_terminals[0] + self.atoms[4]] = [] self.table[self.non_terminals[1] + self.atoms[4]] = [epsilon] self.table[self.non_terminals[2] + self.atoms[4]] = [] self.table[self.non_terminals[3] + self.atoms[4]] = [epsilon] self.table[self.non_terminals[4] + self.atoms[4]] = [] self.table[self.non_terminals[0] + self.atoms[5]] = [] self.table[self.non_terminals[1] + self.atoms[5]] = [epsilon] self.table[self.non_terminals[2] + self.atoms[5]] = [] self.table[self.non_terminals[3] + self.atoms[5]] = [epsilon] self.table[self.non_terminals[4] + self.atoms[5]] = [] return self.table def __print_current_action(self, stack, entry, action, production, next_productions): if next_productions is not None: prod = production + ' -> ' + ''.join(next_productions) else: prod = '' string = '|{:40}|{:50}|{:20}|{:13}|'.format(' '.join(stack), ' '.join(entry), action, prod) print(string) def __print_success_finish(self): action = success_action string = '|{:40}|{:50}|{:20}|{:13}|'.format('', '', action, '') print(string) print('|{:40}|{:50}|{:20}|{:13}|'.format('-' * 40, '-' * 50, '-' * 20, '-' * 13)) def __print_title(self): print('|{:40}|{:50}|{:20}|{:13}|'.format('-' * 40, '-' * 50, '-' * 20, '-' * 13)) print('|{:^40}|{:^50}|{:^20}|{:^13}|'.format('Pilha', 'Entrada', 'Ação', 'Produção')) print('|{:40}|{:50}|{:20}|{:13}|'.format('-' * 40, '-' * 50, '-' * 20, '-' * 13))