def update_grammar(self): try: self._grammar = Grammar(self.prodTextEdit.toPlainText()) return True except ValueError as error: QMessageBox.critical(self, 'Error', error.args[0]) return False
def __init__(self): QMainWindow.__init__(self) self.setupUi(self) self.message = QMessageBox() self.message.setIcon(QMessageBox.Information) self._grammar = Grammar() self._grammar_list = list() #Grammar Buttons self.listButton.clicked.connect(self.add_grammar_to_list) self.importGrammarButton.clicked.connect(self.import_grammar) self.exportGrammarButton.clicked.connect(self.export_grammar) self.firstButton.clicked.connect(self.first) self.firstNTButton.clicked.connect(self.firstNT) self.followButton.clicked.connect(self.follow) self.factorableButton.clicked.connect(self.factorable) self.checkEmptyButton.clicked.connect(self.check_empty) self.runproductiveButton.clicked.connect(self.remove_unproductive) self.runreachableButton.clicked.connect(self.remove_unreachable) self.rsimpleProdButton.clicked.connect(self.remove_simple_productions) self.rleftrecursionButton.clicked.connect(self.remove_left_recursion) self.tepsilonButton.clicked.connect(self.t_epsilon) self.tproperButton.clicked.connect(self.t_proper) #Grammar List self.grammarList.itemDoubleClicked.connect( self.grammar_list_double_clicked)
def __init__(self): QMainWindow.__init__(self) self.setupUi(self) self.message = QMessageBox() self.message.setIcon(QMessageBox.Information) self._regex = Regex() self._automata = Automata() self._grammar = Grammar() self._automata_list = list() self._item_data = '' self._table_data = '' #Regex self.importRegexButton.clicked.connect(self.import_regex) self.exportRegexButton.clicked.connect(self.export_regex) self.convertRegexButton.clicked.connect(self.convert_regex) #Automata self.importAutomataButton.clicked.connect(self.import_automata) self.exportAutomataButton.clicked.connect(self.export_automata) self.convertAutomataButton.clicked.connect(self.convert_automata) self.addStateButton.clicked.connect(self.add_state) self.removeStateButton.clicked.connect(self.remove_state) self.addSymbolButton.clicked.connect(self.add_symbol) self.removeSymbolButton.clicked.connect(self.remove_symbol) self.setFinalStatesButton.clicked.connect(self.set_final_states) self.enumerateButton.clicked.connect(self.enumerate_strings) self.checkStringButton.clicked.connect(self.check_string) self.transitionTable.itemClicked.connect(self.table_item_clicked) self.transitionTable.itemDoubleClicked.connect(self.table_item_double_clicked) self.transitionTable.cellChanged.connect(self.update_automata) #Grammar self.importGrammarButton.clicked.connect(self.import_grammar) self.exportGrammarButton.clicked.connect(self.export_grammar) self.convertGrammarButton.clicked.connect(self.convert_grammar) self.addProdButton.clicked.connect(self.add_production) self.removeProdButton.clicked.connect(self.remove_production) self.productionList.itemClicked.connect(self.grammar_item_clicked) self.productionList.itemDoubleClicked.connect(self.grammar_item_double_clicked) self.productionList.itemChanged.connect(self.update_grammar) #Automata List self.automataList.itemDoubleClicked.connect(self.automata_list_double_clicked) #Operations self.actionIntersection.triggered.connect(self.intersection_action) self.actionDifference.triggered.connect(self.difference_action) self.actionReverse.triggered.connect(self.reverse_action) self.actionDeterminize.triggered.connect(self.determinize_action) self.actionMinimize.triggered.connect(self.minimize_action) self.actionUnion.triggered.connect(self.union_action) self.actionConcatenation.triggered.connect(self.concatenation_action) self.actionClosure.triggered.connect(self.closure_action) self.actionComplement.triggered.connect(self.complement)
def import_grammar(self): path, _ = QFileDialog.getOpenFileName(self) if path: try: grammar = Grammar() grammar.load(path) if self.validate_regular_grammar(grammar): self._grammar = grammar self.update_grammar_list() else: QMessageBox.critical(self, 'Error', 'Not a regular grammar') except ValueError as error: QMessageBox.critical(self, 'Error', error.args[0])
def import_grammar(self): path, _ = QFileDialog.getOpenFileName(self) if path: try: grammar = Grammar() grammar.load(path) if grammar.validate_grammar(): self._grammar = grammar self.update_production_text() else: QMessageBox.critical(self, 'Error', 'Not a valid grammar') except ValueError as error: QMessageBox.critical(self, 'Error', error.args[0])
from model.finiteAutomata import FiniteAutomata from model.grammar import Grammar if __name__ == '__main__': #read the things from the file print("1.Grammar from the requested file -------------------------------") grammar = Grammar.fromFile('regularGrammar.txt') print(grammar) print("----------------------------------------------------------") print("2.Production for the grammar and no_terminal A ------------------") grammar.production_for_a_non_terminal('S') print("----------------------------------------------------------") print("3.Finite Automata ------------------") finiteAutomata = FiniteAutomata.from_file('finiteAutomata.txt') print(finiteAutomata) print("----------------------------------------------------------") #print("3.Is regular and then compute Fa-----------------------------------------") grammar = Grammar.fromFile('regularGrammar.txt') #grammar = Grammar.fromConsole() if grammar.isRegular(): finiteAutomata = FiniteAutomata.fromRegularGrammar(grammar) print(finiteAutomata) else: print("The grammar is not regular\n") print(
from model.finiteAutomata import FiniteAutomata from model.grammar import Grammar if __name__ == '__main__': # Grammar usage # We read the grammar from file 'rg1.txt' grammar = Grammar.fromFile('rg1.txt') print(grammar) # We print the productions for a given non-terminal, # A in this case try: grammar.showProductionsFor('A') except Exception as e: print(e) # We can also read from the console if we'd like, # just make sure that the format of the input is the same as in this example # grammar2 = Grammar.fromConsole() # print('\n' + str(grammar2)) # Finite Automata usage # We read the Finite Automata from the file 'fa1.txt' finiteAutomata = FiniteAutomata.fromFile('fa1.txt') print(finiteAutomata)
class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self): QMainWindow.__init__(self) self.setupUi(self) self.message = QMessageBox() self.message.setIcon(QMessageBox.Information) self._regex = Regex() self._automata = Automata() self._grammar = Grammar() self._automata_list = list() self._item_data = '' self._table_data = '' #Regex self.importRegexButton.clicked.connect(self.import_regex) self.exportRegexButton.clicked.connect(self.export_regex) self.convertRegexButton.clicked.connect(self.convert_regex) #Automata self.importAutomataButton.clicked.connect(self.import_automata) self.exportAutomataButton.clicked.connect(self.export_automata) self.convertAutomataButton.clicked.connect(self.convert_automata) self.addStateButton.clicked.connect(self.add_state) self.removeStateButton.clicked.connect(self.remove_state) self.addSymbolButton.clicked.connect(self.add_symbol) self.removeSymbolButton.clicked.connect(self.remove_symbol) self.setFinalStatesButton.clicked.connect(self.set_final_states) self.enumerateButton.clicked.connect(self.enumerate_strings) self.checkStringButton.clicked.connect(self.check_string) self.transitionTable.itemClicked.connect(self.table_item_clicked) self.transitionTable.itemDoubleClicked.connect(self.table_item_double_clicked) self.transitionTable.cellChanged.connect(self.update_automata) #Grammar self.importGrammarButton.clicked.connect(self.import_grammar) self.exportGrammarButton.clicked.connect(self.export_grammar) self.convertGrammarButton.clicked.connect(self.convert_grammar) self.addProdButton.clicked.connect(self.add_production) self.removeProdButton.clicked.connect(self.remove_production) self.productionList.itemClicked.connect(self.grammar_item_clicked) self.productionList.itemDoubleClicked.connect(self.grammar_item_double_clicked) self.productionList.itemChanged.connect(self.update_grammar) #Automata List self.automataList.itemDoubleClicked.connect(self.automata_list_double_clicked) #Operations self.actionIntersection.triggered.connect(self.intersection_action) self.actionDifference.triggered.connect(self.difference_action) self.actionReverse.triggered.connect(self.reverse_action) self.actionDeterminize.triggered.connect(self.determinize_action) self.actionMinimize.triggered.connect(self.minimize_action) self.actionUnion.triggered.connect(self.union_action) self.actionConcatenation.triggered.connect(self.concatenation_action) self.actionClosure.triggered.connect(self.closure_action) self.actionComplement.triggered.connect(self.complement) def add_automata_to_list(self): if self.transitionTable.rowCount() != 0 and self.transitionTable.columnCount() != 0: text, ok = QInputDialog.getText(self, 'Replace Automata', 'You are going to '+ 'replace the current automata, give it a name or cancel to '+ 'not add it to the list: ') if ok: new_automata = self._automata.copy() self._automata_list.append(new_automata) self.automataList.addItem(text) def automata_list_double_clicked(self, item): self.add_automata_to_list() index = self.automataList.row(item) self._automata = self._automata_list[index] self.update_transition_table() def import_regex(self): path, _ = QFileDialog.getOpenFileName(self) self._regex = Regex() if path: try: self._regex.load(path) self.regexInput.setText(self._regex.string) except ValueError as error: QMessageBox.critical(self, 'Error', error.args[0]) def export_regex(self): regex_string = self.regexInput.text() self._regex = Regex(regex_string) path, _ = QFileDialog.getSaveFileName(self) if path: self._regex.save(path) def convert_regex(self): regex_string = self.regexInput.text() self._regex = Regex(regex_string) self.add_automata_to_list() self._automata = self._regex.convert_to_automata() self.update_transition_table() def validate_finite_automata(self, automata): if re.fullmatch(STATE_INPUT, automata.initial_state) is None: return False symbols = ','.join(sorted(automata.symbols)) if re.fullmatch(SYMBOL_INPUT, symbols) is None: return False states = ','.join(sorted(automata.states)) if re.fullmatch(STATE_INPUT, states) is None: return False final_states = ','.join(sorted(automata.final_states)) if final_states != '': if re.fullmatch(STATE_INPUT, final_states) is None: return False transitions = [','.join(sorted(v)) for k, v in automata.transitions.items()] for transition in transitions: if transition != '': if re.fullmatch(STATE_INPUT, transition) is None: return False return True def import_automata(self): path, _ = QFileDialog.getOpenFileName(self) if path: try: automata = Automata() automata.load(path) if self.validate_finite_automata(automata): self.add_automata_to_list() self._automata = automata self.update_transition_table() else: QMessageBox.critical(self, 'Error', 'Not a valid automata') except ValueError as error: QMessageBox.critical(self, 'Error', error.args[0]) def export_automata(self): path, _ = QFileDialog.getSaveFileName(self) if path: self._automata.save(path) def convert_automata(self): if self.transitionTable.rowCount() != 0 and self.transitionTable.columnCount() != 0: self._grammar = self._automata.convert_to_grammar() self.update_grammar_list() def add_state(self): text, ok = QInputDialog.getText( self, 'Add State', 'You can input a single state qN or a list of '+ 'states. e.g(q0, q1, ...)') if ok: text = text.strip().replace(' ', '') while re.fullmatch(STATE_INPUT, text) is None: text, ok = QInputDialog.getText(self, 'Add State', 'The states have to be a \'q\' followed by a number') if ok: text = text.strip().replace(' ', '') for state in text.split(','): self._automata.add_state(state) for s in self._automata.symbols: self._automata.transitions[state, s] = set() self.update_transition_table() def remove_state(self): text, ok = QInputDialog.getText( self, 'Remove State', 'You can input a single state qN or a list of '+ 'states. e.g(q0, q1, ...)') if ok: text = text.strip().replace(' ', '') while re.fullmatch(STATE_INPUT, text) is None: text, ok = QInputDialog.getText(self, 'Remove State', 'The states have to be a \'q\' followed by a number') if ok: text = text.strip().replace(' ', '') for state in text.split(','): self._automata.remove_state(state) self.update_transition_table() def add_symbol(self): text, ok = QInputDialog.getText( self, 'Add Symbol', 'You can input a single symbol or a list of '+ 'symbols. e.g(a, b, c, ...)') if ok: text = text.strip().replace(' ', '') while re.fullmatch(SYMBOL_INPUT, text) is None: text, ok = QInputDialog.getText(self, 'Add Symbol', 'Only lower case letters and numbers are accepted as symbols!') if ok: text = text.strip().replace(' ', '') for symbol in text.split(','): self._automata.add_symbol(symbol) for state in self._automata.states: self._automata.transitions[state, symbol] = set() self.update_transition_table() def remove_symbol(self): text, ok = QInputDialog.getText( self, ' Remove Symbol', 'You can input a single symbol or a list of '+ 'symbols. e.g(a, b, c, ...)') if ok: text = text.strip().replace(' ', '') while re.fullmatch(SYMBOL_INPUT, text) is None: text, ok = QInputDialog.getText(self, 'Remove Symbol', 'Only lower case letters and numbers are accepted as symbols!') if ok: text = text.strip().replace(' ', '') for symbol in text.split(','): self._automata.remove_symbol(symbol) self.update_transition_table() def set_final_states(self): text, ok = QInputDialog.getText( self, 'Set Final States', 'You can input a single state qN or a list of '+ 'states. e.g(q0, q1, ...)') if ok: text = text.strip().replace(' ', '') while re.fullmatch(STATE_INPUT, text) is None: text, ok = QInputDialog.getText(self, 'Set Final States', 'The states have to be a \'q\' followed by a number') if ok: text = text.strip().replace(' ', '') for state in text.split(','): self._automata.add_final_state(state) self.update_transition_table() def determinize_action(self): self.add_automata_to_list() self._automata.determinize() self._automata.rename_states() self.update_transition_table() def minimize_action(self): self.add_automata_to_list() self._automata.minimize() self._automata.rename_states() self.update_transition_table() def union_action(self): try: item_text = self.automataList.selectedItems()[0].text() message = ('Union will be made with the current automata and the selected '+ 'automata from the list: ' + item_text + '.') ok = QMessageBox.question(self, 'Select Automata', message, QMessageBox.Yes, QMessageBox.No) if ok == QMessageBox.Yes: self.add_automata_to_list() other_automata = self._automata_list[self.automataList.currentRow()].copy() self._automata.union(other_automata) self.update_transition_table() except IndexError: self.message.setText('To use union operation you need a automata in '+ 'the table and other selected from the automata list!') self.message.show() def concatenation_action(self): try: item_text = self.automataList.selectedItems()[0].text() message = ('Concatenation will be made with the current automata and the selected '+ 'automata from the list: ' + item_text + '.') ok = QMessageBox.question(self, 'Select Automata', message, QMessageBox.Yes, QMessageBox.No) if ok == QMessageBox.Yes: self.add_automata_to_list() other_automata = self._automata_list[self.automataList.currentRow()].copy() self._automata.concatenation(other_automata) self.update_transition_table() except IndexError: self.message.setText('To use union operation you need a automata in '+ 'the table and other selected from the automata list!') self.message.show() def closure_action(self): self.add_automata_to_list() self._automata.closure() self.update_transition_table() def complement(self): self.add_automata_to_list() self._automata.complement() self.update_transition_table() def intersection_action(self): try: item_text = self.automataList.selectedItems()[0].text() message = ('Intersection will be made with the current automata and the selected '+ 'automata from the list: ' + item_text + '.') ok = QMessageBox.question(self, 'Select Automata', message, QMessageBox.Yes, QMessageBox.No) if ok == QMessageBox.Yes: self.add_automata_to_list() other_automata = self._automata_list[self.automataList.currentRow()].copy() (o, s, u) = self._automata.intersection(other_automata) self.automataList.addItem(item_text+'Complement') self.automataList.addItem('oldAutomataComplement') self.automataList.addItem('middleComplementUnion') self._automata_list.append(o) self._automata_list.append(s) self._automata_list.append(u) self.update_transition_table() except IndexError: self.message.setText('To use intersection operation you need a automata in '+ 'the table and other selected from the automata list!') self.message.show() def difference_action(self): try: item_text = self.automataList.selectedItems()[0].text() message = ('Difference will be made with the current automata - selected '+ 'automata from the list: ' + item_text + '.') ok = QMessageBox.question(self, 'Select Automata', message, QMessageBox.Yes, QMessageBox.No) if ok == QMessageBox.Yes: self.add_automata_to_list() other_automata = self._automata_list[self.automataList.currentRow()].copy() o = self._automata.difference(other_automata) self.automataList.addItem(item_text+'Complement') self._automata_list.append(o) self.update_transition_table() except IndexError: self.message.setText('To use intersection operation you need a automata in '+ 'the table and other selected from the automata list!') self.message.show() def reverse_action(self): self.add_automata_to_list() self._automata.reverse() self.update_transition_table() def enumerate_strings(self): n, ok = QInputDialog.getInt( self, 'Enumerate', 'Which size of sentence') if ok: try: accepted = self._automata.enumerate_strings(n) if accepted == set(): accepted = 'There aren\'t sentences with this size!' else: accepted = ','.join(v for v in accepted) self.message.setText('Enumerate sentences with size: '+str(n)+'\n'+accepted) self.message.show() except ValueError as error: QMessageBox.critical(self, 'Error', error.args[0]) def check_string(self): string = self.checkStringInput.text() accepted = self._automata.membership(string) if accepted: self.message.setText('The string is accepted by the automaton!') self.message.show() else: self.message.setText('The string is NOT accepted by the automaton!') self.message.show() def update_automata(self, row, col): table_item = self.transitionTable.item(row, col) text = table_item.text().replace(' ', '') states = sorted(self._automata.states) symbols = sorted(self._automata.symbols) if text != '-': if re.fullmatch(STATE_INPUT, text) is None: table_item.setText(self._table_data) self.message.setText('The states have to be a \'q\' followed by a number or a \'-\'') self.message.show() else: end_states = set(text.split(',')) try: self._automata.add_transition(states[row], symbols[col], end_states) except ValueError as error: self.transitionTable.cellChanged.disconnect(self.update_automata) table_item.setText(self._table_data) self.transitionTable.cellChanged.connect(self.update_automata) QMessageBox.critical(self, 'Error', error.args[0]) else: self._automata.add_transition(states[row], symbols[col], set()) def table_item_clicked(self, item): self.transitionTable.cellChanged.disconnect(self.update_automata) self._table_data = item.text() self.transitionTable.cellChanged.connect(self.update_automata) def table_item_double_clicked(self, item): self.transitionTable.cellChanged.disconnect(self.update_automata) item.setText(self._table_data) self.transitionTable.cellChanged.connect(self.update_automata) def update_transition_table(self): self.transitionTable.cellChanged.disconnect(self.update_automata) states = [] for state in sorted(self._automata.states): preffix = '' if state == self._automata.initial_state: preffix += '->' if state in self._automata.final_states: preffix += '*' states.append(preffix + state) self.transitionTable.setRowCount(len(states)) self.transitionTable.setVerticalHeaderLabels(states) self.transitionTable.setColumnCount(len(self._automata.symbols)) self.transitionTable.setHorizontalHeaderLabels(sorted(self._automata.symbols)) for i, state in enumerate(sorted(self._automata.states)): for j, symbol in enumerate(sorted(self._automata.symbols)): if (state, symbol) in self._automata.transitions: item = ','.join(sorted(self._automata.transitions[state, symbol])) else: item = '-' self.transitionTable.setItem(i, j, QTableWidgetItem(item)) self.transitionTable.cellChanged.connect(self.update_automata) def validate_regular_grammar(self, grammar): first = True for k, v in grammar.productions.items(): text = k + '->' for p in v: text += p + '|' if first: if re.fullmatch(INITIAL_GRAMMAR, text[:-1]) is None: return False else: first = False else: if re.fullmatch(GRAMMAR_INPUT, text[:-1]) is None: return False return True def import_grammar(self): path, _ = QFileDialog.getOpenFileName(self) if path: try: grammar = Grammar() grammar.load(path) if self.validate_regular_grammar(grammar): self._grammar = grammar self.update_grammar_list() else: QMessageBox.critical(self, 'Error', 'Not a regular grammar') except ValueError as error: QMessageBox.critical(self, 'Error', error.args[0]) def export_grammar(self): path, _ = QFileDialog.getSaveFileName(self) if path: self._grammar.save(path) def convert_grammar(self): self.add_automata_to_list() self._automata = self._grammar.convert_to_automata() self._automata.determinize() self._automata.rename_states() self.update_transition_table() def add_production(self): keys = self._grammar.productions.keys() if self.productionList.count() == 0: text, ok = QInputDialog.getText( self, 'Add Initial Production', 'Input a production '+ 'e.g(A -> aA | bB)') if ok: text = text.strip().replace(' ', '') while re.fullmatch(INITIAL_GRAMMAR, text) is None: text, ok = QInputDialog.getText(self, 'Add Initial Production', 'Production not regular!') if ok: text = text.strip().replace(' ', '') self.productionList.addItem(text) key, set_values = text.split('->') self._grammar.add(key, set(set_values.split('|'))) else: text, ok = QInputDialog.getText( self, 'Add Production', 'Input a production '+ 'e.g(A -> aA | bB)') if ok: text = text.strip().replace(' ', '') while re.fullmatch(GRAMMAR_INPUT, text) is None: text, ok = QInputDialog.getText(self, 'Add Production', 'Production not regular!') if ok: text = text.strip().replace(' ', '') key, set_values = text.split('->') if key not in keys: self.productionList.addItem(text) self._grammar.add(key, set(set_values.split('|'))) else: self.message.setText('This non terminal symbol already exists!') self.message.show() def remove_production(self): for item in self.productionList.selectedItems(): key = item.text().split('->')[0] self._grammar.remove(key) self.productionList.takeItem(self.productionList.row(item)) def grammar_item_clicked(self, item): self.productionList.itemChanged.disconnect(self.update_grammar) item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable) self._item_data=item.text() self.productionList.itemChanged.connect(self.update_grammar) def grammar_item_double_clicked(self, item): self.productionList.itemChanged.disconnect(self.update_grammar) item.setText(self._item_data) self.productionList.itemChanged.connect(self.update_grammar) def update_grammar(self, item): self.productionList.itemChanged.disconnect(self.update_grammar) keys = self._grammar.productions.keys() if self.productionList.indexFromItem(item).row() == 0: if re.fullmatch(INITIAL_GRAMMAR, item.text()) is None: item.setText(self._item_data) self.message.setText('Production not Regular!') self.message.show() else: key, set_values = item.text().split('->') old_key = self._item_data.split('->')[0] if key not in keys or key == old_key : self._grammar.edit_key(old_key, key, set(set_values.split('|'))) else: item.setText(self._item_data) self.message.setText('This non terminal symbol already exists!') self.message.show() else: if re.fullmatch(GRAMMAR_INPUT, item.text()) is None: item.setText(self._item_data) self.message.setText('Production not Regular!') self.message.show() else: key, set_values = item.text().split('->') old_key = self._item_data.split('->')[0] if key not in keys or key == old_key : self._grammar.edit_key(old_key, key, set(set_values.split('|'))) else: item.setText(self._item_data) self.message.setText('This non terminal symbol already exists!') self.message.show() self.productionList.itemChanged.connect(self.update_grammar) def update_grammar_list(self): self.productionList.clear() for k, v in self._grammar.productions.items(): if v == set(): continue text = k + '->' for p in v: text += p + '|' self.productionList.addItem(text[:-1])
print("getting corpus from: " + corpus) model = PlaintextCorpusReader( corpus, '.*\.txt', sent_tokenizer=LazyLoader('tokenizers/punkt/spanish.pickle'), encoding="utf8") # Create grammar terminals = set() epsilon = Symbol("ε", True) terminals.add(epsilon) ## epsilon terminal non_terminals = set() s = Symbol("S", False) # Starting non terminal non_terminals.add(s) grammar = Grammar(non_terminals, terminals, s) # This is only to tell me how advanced the process is count = 0.0 len_fileids = len(model.fileids()) # Get the tokenized corpus tokens_location = location + "tokenized" print("getting tokens from: " + tokens_location) f = open(tokens_location, 'rb') tokens = pickle.load(f) f.close() # Train the grammar model with a context of -+1 for fileid in model.fileids(): spanish_sents = model.sents(fileid) print(str((count / len_fileids) * 100) + "%")
def read_file(self, file_src): """ Loads the content from a file and scans for certain words. If one of these words is found the string after the word will be stored into a grammar or settings object. :param file_src: String contains the path to a file :return: list which contains the grammar and settings object """ with open(file_src, "r") as fobj: grammar = Grammar() settings = Settings() for line in fobj: rhs = None #right-hand-side of a rule lhs = None #left-hand-side of a rule state = "lhs" words = line.rstrip().split() for word in words: if (words.index(word) == 0 and word == "axiom:"): words.remove(word) grammar.axiom = ' '.join(words) elif (words.index(word) > 0 and words[0] == "angle_z:"): settings.angle_z_min = int(words[1]) settings.angle_z_max = int(words[3]) elif (words.index(word) > 0 and words[0] == "angle_y:"): settings.angle_y_min = int(words[1]) settings.angle_y_max = int(words[3]) elif (words.index(word) > 0 and words[0] == "angle_x:"): settings.angle_x_min = int(words[1]) settings.angle_x_max = int(words[3]) elif (words.index(word) > 0 and words[0] == "branch-shortening:"): settings.branch_min = float(words[1]) settings.branch_max = float(words[3]) #elif (words.index(word) > 0 and words[0] == "num_sides:"): #grammar.num_sides = int(words[1]) elif (words.index(word) > 0 and words[0] == "base_radius:"): settings.base_radius = float(words[1]) elif (words.index(word) > 0 and words[0] == "rules:"): if (state == "lhs"): lhs = word if (lhs not in grammar.variables): grammar.variables.add(lhs) state = "rhs" continue if (state == "rhs" and word != "->"): rhs = word if ("," in rhs): rhs = rhs.replace(",", "") grammar.rules.add(Rule(lhs, rhs)) state = "lhs" elif (words.index(word) > 0 and words[0] == "generations:"): settings.generations = int(words[1]) elif (words.index(word) > 0 and words[0] == "base_length:"): settings.base_length = float(words[1]) elif (words.index(word) > 0 and words[0] == "bark_texture:"): settings.bark_path = words[1] elif (words.index(word) > 0 and words[0] == "leaf_texture:"): settings.leaf_path = words[1] return [grammar, settings]
class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self): QMainWindow.__init__(self) self.setupUi(self) self.message = QMessageBox() self.message.setIcon(QMessageBox.Information) self._grammar = Grammar() self._grammar_list = list() #Grammar Buttons self.listButton.clicked.connect(self.add_grammar_to_list) self.importGrammarButton.clicked.connect(self.import_grammar) self.exportGrammarButton.clicked.connect(self.export_grammar) self.firstButton.clicked.connect(self.first) self.firstNTButton.clicked.connect(self.firstNT) self.followButton.clicked.connect(self.follow) self.factorableButton.clicked.connect(self.factorable) self.checkEmptyButton.clicked.connect(self.check_empty) self.runproductiveButton.clicked.connect(self.remove_unproductive) self.runreachableButton.clicked.connect(self.remove_unreachable) self.rsimpleProdButton.clicked.connect(self.remove_simple_productions) self.rleftrecursionButton.clicked.connect(self.remove_left_recursion) self.tepsilonButton.clicked.connect(self.t_epsilon) self.tproperButton.clicked.connect(self.t_proper) #Grammar List self.grammarList.itemDoubleClicked.connect( self.grammar_list_double_clicked) def add_grammar_to_list(self): if self.update_grammar(): text, ok = QInputDialog.getText(self, 'Grammar List', 'Give the grammar a name: ') if ok: new_grammar = copy.deepcopy(self._grammar) self._grammar_list.append(new_grammar) self.grammarList.addItem(text) def update_production_text(self): grammar_text = '' for k, v in self._grammar.productions.items(): if v == set(): continue text = k + ' -> ' for p in v: text += p + ' | ' grammar_text += text[:-2] + '\n' self.prodTextEdit.setPlainText(grammar_text) def update_grammar(self): try: self._grammar = Grammar(self.prodTextEdit.toPlainText()) return True except ValueError as error: QMessageBox.critical(self, 'Error', error.args[0]) return False def grammar_list_double_clicked(self, item): index = self.grammarList.row(item) self._grammar = self._grammar_list[index] self.update_production_text() def import_grammar(self): path, _ = QFileDialog.getOpenFileName(self) if path: try: grammar = Grammar() grammar.load(path) if grammar.validate_grammar(): self._grammar = grammar self.update_production_text() else: QMessageBox.critical(self, 'Error', 'Not a valid grammar') except ValueError as error: QMessageBox.critical(self, 'Error', error.args[0]) def export_grammar(self): path, _ = QFileDialog.getSaveFileName(self) if path: self.update_grammar() self._grammar.save(path) #PROGRAM LOGIC FUNCTIONS def first(self): if not self.update_grammar(): return self._grammar.first() nt = set() text = '' for k, v in self._grammar._first.items(): if k not in nt: text += '\nFirst({}): '.format(k) text += '{}'.format(v) nt.add(k) else: text += ', {}'.format(v) QMessageBox.information(self, 'First', text) def firstNT(self): if not self.update_grammar(): return self._grammar.firstNT() nt = set() text = '' for k, v in self._grammar._first_nt.items(): if k not in nt: text += '\nFirst-NT({}): '.format(k) if v != set(): text += '{}'.format(v) else: text += 'Empty' nt.add(k) else: text += ', {}'.format(v) QMessageBox.information(self, 'First-NT', text) def follow(self): if not self.update_grammar(): return follow = self._grammar.follow() nt = set() text = '' for k, v in follow.items(): if k not in nt: text += '\nFollow({}): '.format(k) text += '{}'.format(v) nt.add(k) else: text += ', {}'.format(v) QMessageBox.information(self, 'Follow', text) def factorable(self): pass def remove_left_recursion(self): pass def check_empty(self): if not self.update_grammar(): return text = '' grammar = copy.deepcopy(self._grammar) try: grammar.remove_unproductive() text += 'Not Empty\n' if grammar.is_finite(): text += 'Is finite' else: text += 'Is infinite' QMessageBox.information(self, 'Not Empty', text) except ValueError as error: QMessageBox.information(self, 'Empty', error.args[0]) return # NEED TO CHECK FINITE OR INFINITE def remove_unproductive(self): if not self.update_grammar(): return try: grammar = copy.deepcopy(self._grammar) grammar.remove_unproductive() self._grammar = grammar self.update_production_text() except ValueError as error: QMessageBox.critical(self, 'Error', error.args[0]) def remove_unreachable(self): if not self.update_grammar(): return try: grammar = copy.deepcopy(self._grammar) grammar.remove_unreachable() self._grammar = grammar self.update_production_text() except ValueError as error: QMessageBox.critical(self, 'Error', error.args[0]) def t_epsilon(self): if not self.update_grammar(): return self._grammar.t_epsilon() self.update_production_text() def remove_simple_productions(self): if not self.update_grammar(): return self._grammar.remove_simple_productions() self.update_production_text() def t_proper(self): grammars = self._grammar.t_proper() self._grammar_list.append(grammars[0]) self.grammarList.addItem('intermediate epsilon free') self._grammar_list.append(grammars[1]) self.grammarList.addItem('intermediate removing simple productions') self._grammar_list.append(copy.deepcopy(self._grammar)) self.grammarList.addItem('final proper grammar') self.update_production_text() text = ('NF: ' + str(grammars[2]) + '\nVI: ' + str(grammars[3]) + '\nNE: ' + str(grammars[4]) + '\nNA: ' + str(grammars[5])) QMessageBox.information(self, 'Sets', text)