class GUI(QMainWindow, Ui_MainWindow, AF_Dialog, GR_Dialog): def __init__(self): QMainWindow.__init__(self) #self.fa = NFA({}, "", {}) self.fa = None self.rg = RegularGrammar("", {}) self.setupUi(self) #self.resize(600, 400) # Botões self.regex_to_fa_button.clicked.connect(self.regex_to_fa) self.determinize_button.clicked.connect(self.determinize) self.minimize_button.clicked.connect(self.minimize) self.reverse_button.clicked.connect(self.reverse) self.complement_button.clicked.connect(self.complement) self.test_button.clicked.connect(self.test_word) self.rg_to_fa_button.clicked.connect(self.rg_to_fa) self.fa_to_rg_button.clicked.connect(self.fa_to_rg) self.open_button.clicked.connect(self.open_fa) self.save_button.clicked.connect(self.save_fa) self.list.itemClicked.connect(self.select_fa) self.operations_button.clicked.connect(self.fa_op_dialog) self.rg_operations_button.clicked.connect(self.rg_op_dialog) self.words_button.clicked.connect(self.words_op_dialog) self.transition_table.cellClicked.connect(self.click_cell) # Ações self.actionSalvar.triggered.connect(self.save_fa) self.actionAbrir.triggered.connect(self.open_fa) self.actionSalvar_GR.triggered.connect(self.save_rg) self.actionImportar_GR.triggered.connect(self.open_rg) self.actionSalvar_ER.triggered.connect(self.save_regex) self.actionImportar_ER.triggered.connect(self.open_regex) # Correspondência entre index do QListWidgetItem e autômato self.list_fas = [] def click_cell(self): self.table_label.setText(self.transition_table.currentItem().text()) def select_fa(self): self.fa = self.list_fas[self.list.currentRow()] self.update_fa_table() def regex_to_fa(self): regex_str = self.regex_input.text() try: self.fa = Regex(regex_str).dfa except SyntaxError as e: self.show_error(e) return self.fa.regex_str = regex_str self.add_fa_to_list() def fa_to_rg(self): if self.fa: self.rg = RegularGrammar.from_nfa(self.fa) self.update_rg_text() else: self.show_error("Não há AF selecionado!") return def show_error(self, e): box = QErrorMessage(self) box.showMessage(str(e)) def rg_to_fa(self): if self.rg_text.toPlainText(): try: self.rg = parse_rg(self.rg_text.toPlainText()) except SyntaxError as e: self.show_error(e) return self.fa = NFA.from_rg(self.rg) self.fa.rg_str = self.rg.rg_str self.add_fa_to_list() else: self.show_error("Defina uma gramática!") return def determinize(self): if not self.fa: self.show_error("Não há AF selecionado!") return fa = copy.deepcopy(self.fa) fa.determinize() self.fa = fa self.add_fa_to_list() def minimize(self): if not self.fa: self.show_error("Não há AF selecionado!") return fa = copy.deepcopy(self.fa) fa.minimize() self.fa = fa self.add_fa_to_list() def reverse(self): if not self.fa: self.show_error("Não há AF selecionado!") return self.fa = self.fa.reverse() self.add_fa_to_list() def complement(self): if not self.fa: self.show_error("Não há AF selecionado!") return fa = copy.deepcopy(self.fa) fa.complement() self.fa = fa self.add_fa_to_list() def test_word(self): if not self.fa: self.show_error("Não há AF selecionado!") return if self.fa.accepts(self.word_input.text()): self.statusbar.showMessage("Sentença aceita") else: self.statusbar.showMessage("Sentença rejeitada") def update_fa_table(self): # restaura regex / gramática if self.fa.regex_str: self.regex_input.setText(self.fa.regex_str) if self.fa.rg_str: self.rg_text.setPlainText(self.fa.rg_str) alphabet = sorted(self.fa.alphabet()) states = [] for state in self.fa.states(): special = "" if state == '-': continue if state in self.fa.accepting: special += "*" if state is self.fa.initial: special += "->" states.append(special + state) self.transition_table.setRowCount(len(states)) self.transition_table.setColumnCount(len(alphabet)) self.transition_table.setVerticalHeaderLabels(states) self.transition_table.setHorizontalHeaderLabels(alphabet) transitions = self.fa.transitions for i, state in enumerate(self.fa.states()): for j, symbol in enumerate(alphabet): transition = '-' if state in transitions: if symbol in transitions[state]: transition = ", ".join( \ sorted(transitions[state][symbol])) self.transition_table.setItem(i, j, QTableWidgetItem(transition)) def add_fa_to_list(self): fa = self.fa name = self.name_field.text() if name: fa.name = name self.list_fas.append(fa) item = QListWidgetItem(crop(fa.name), self.list) self.list.setCurrentItem(item) self.update_fa_table() def save_fa(self): if not self.fa: self.show_error("Não há AF selecionado!") return path, _ = QFileDialog.getSaveFileName(self) if path: self.fa.save(path) def open_fa(self): path, _ = QFileDialog.getOpenFileName(self) if path: nfa = NFA.open(path) self.fa = nfa self.add_fa_to_list() def fa_op_dialog(self): Dialog = QtWidgets.QDialog() ui = AF_Dialog() ui.setupUi(Dialog) ui.union_radio.setChecked(True) ui.fa_1_combo.addItems(fa.name for fa in self.list_fas) ui.fa_2_combo.addItems(fa.name for fa in self.list_fas) ui.op_buttonBox.accepted.connect(lambda: self.create_fa_by_op(ui)) Dialog.exec_() def words_op_dialog(self): Dialog = QtWidgets.QDialog() ui = Words_Dialog() ui.setupUi(Dialog) try: size = int(self.n_field.text()) if self.n_field.text() else 3 except: self.show_error("Tamanho deve ser um número") if not self.fa: self.show_error("Não há autômato selecionado") return words = self.fa.words_of_size(size) msg = "Palavras de tamanho " + str(size) + " em " + self.fa.name if len(words) == 10000: msg += "\nPalavras demais, mostrando resultado parcial" ui.words.setPlainText(msg + '\n\n' + '\n'.join(words)) Dialog.exec_() def create_fa_by_op(self, dialog): fa1 = self.list_fas[dialog.fa_1_combo.currentIndex()] fa2 = self.list_fas[dialog.fa_2_combo.currentIndex()] if dialog.difference_radio.isChecked(): self.difference(fa1, fa2) elif dialog.intersection_radio.isChecked(): self.intersection(fa1, fa2) else: self.union(fa1, fa2) def difference(self, fa1, fa2): self.fa = fa1.difference(fa2) self.add_fa_to_list() def intersection(self, fa1, fa2): self.fa = fa1.intersection(fa2) self.add_fa_to_list() def union(self, fa1, fa2): self.fa = fa1.union(fa2) self.add_fa_to_list() def rg_op_dialog(self): Dialog = QtWidgets.QDialog() ui = GR_Dialog() ui.setupUi(Dialog) ui.unionrg_radio.setChecked(True) ui.import_gr_1_button.clicked.connect( lambda: self.open_rg_dialog(ui, 1)) ui.import_gr_2_button.clicked.connect( lambda: self.open_rg_dialog(ui, 2)) ui.op_rg_buttonBox.accepted.connect(lambda: self.create_rg_by_op(ui)) Dialog.exec_() def create_rg_by_op(self, dialog): rg1 = None rg2 = None if dialog.rg_1_input.toPlainText(): rg1 = self.parse_rg(dialog.rg_1_input.toPlainText()) if dialog.rg_2_input.toPlainText(): rg2 = self.parse_rg(dialog.rg_2_input.toPlainText()) if dialog.concatenation_radio.isChecked(): if not rg1 or not rg2: self.show_error("Defina duas gramáticas!") return self.concatenation(rg1, rg2) elif dialog.kleene_radio.isChecked(): if not rg1 and not rg2 or rg1 and rg2: self.show_error("Defina apenas uma gramática!") return if rg1: self.kleene(rg1) elif rg2: self.kleene(rg2) else: if not rg1 or not rg2: self.show_error("Defina duas gramáticas!") return self.union_rg(rg1, rg2) # Importa GR no diálogo de operações def open_rg_dialog(self, dialog, input_number): path, _ = QFileDialog.getOpenFileName(self) rg_string = "" if path: file = open(path, 'r') rg_string = file.read() file.close() rg = parse_rg(rg_string) else: return if input_number is 1: dialog.rg_1_input.setPlainText(rg.to_string()) else: dialog.rg_2_input.setPlainText(rg.to_string()) def concatenation(self, rg1, rg2): self.rg = rg1.concatenation(rg2) self.update_rg_text() def kleene(rg1): self.rg = rg1.kleene_closure() self.update_rg_text() def union_rg(self, rg1, rg2): self.rg = rg1.union(rg2) self.update_rg_text() def update_rg_text(self): self.rg_text.setPlainText(self.rg.to_string()) # Salva GR da janela principal def save_rg(self): rg = parse_rg(self.rg_text.toPlainText()) path, _ = QFileDialog.getSaveFileName(self) if path: file = open(path, 'w') file.write(rg.to_string()) file.close() else: return # Importa GR na janela principal def open_rg(self): path, _ = QFileDialog.getOpenFileName(self) rg_string = "" if path: file = open(path, 'r') rg_string = file.read() file.close() self.rg = parse_rg(rg_string) self.update_rg_text() # Parse sem salvar na GR principal def parse_rg(self, str): try: rg = parse_rg(str) except (SyntaxError) as e: self.show_error(e) return return rg def save_regex(self): regex = Regex(self.regex_input.text()) path, _ = QFileDialog.getSaveFileName(self) if path: file = open(path, 'w') file.write(regex.regex_str) file.close() else: return def open_regex(self): path, _ = QFileDialog.getOpenFileName(self) string = "" if path: file = open(path, 'r') string = file.read() try: regex = Regex(string) self.regex_input.setText(regex.regex_str) except SyntaxError as e: self.show_error(e) return file.close()