예제 #1
0
 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
예제 #2
0
    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)
예제 #3
0
    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)
예제 #4
0
    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])
예제 #5
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])
예제 #6
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)
예제 #8
0
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])
예제 #9
0
    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) + "%")
예제 #10
0
 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]
예제 #11
0
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)