Example #1
0
def test_convert_scribble(datum):
    pushdown_automata = PDA()
    print(list(tokenize(datum[0])))
    ast = pushdown_automata.run(tokenize(datum[0]))
    print('Got:\n', repr(ast))
    print('Expecting:\n', datum[1])
    assert repr(ast) == datum[1]
Example #2
0
    def open_pda(self):
        file_name, _ = QtWidgets.QFileDialog.getOpenFileName(
            self.central_widget, 'Open PDA file...', '.', 'XML Files (*.xml)')

        if file_name:
            self.set_menu_state(True)

            self.pda = PDA(file_name)

            f = Digraph('pda_machine', filename='pda_tmp.gv', format='svg')
            f.attr(rankdir='LR', size='8,5')

            # Setup initial state
            f.attr('node', shape='plaintext')
            f.node(' ')
            f.attr('node', shape='circle')
            f.node(self.pda.initial_state)
            f.edge(' ', self.pda.initial_state, ' ')

            # Setup final states
            f.attr('node', shape='doublecircle')
            for fs in self.pda.final_states:
                f.node(fs)

            # Setup other states and transitions
            f.attr('node', shape='circle')
            for tr in self.pda.transitions:
                f.edge(
                    tr['source'], tr['destination'],
                    '{},{},{}'.format(PDA.lamb(tr['input']),
                                      PDA.lamb(tr['stack_read']),
                                      PDA.lamb(tr['stack_write'])))

            self.graph = f

            f.render()
            self.center_image.load('pda_tmp.gv.svg')
Example #3
0
pda = PDA(states={'q0', 'q1', 'q2'},
          input_symbols={'a', 'b', 'c'},
          stack_symbols={'$', '0', '1'},
          transitions={
              'q0': {
                  '0': {
                      'a': ('q0', (None, '0')),
                      'b': ('q0', (None, '1')),
                      'c': ('q1', (None, None))
                  },
                  '1': {
                      'a': ('q0', (None, '0')),
                      'b': ('q0', (None, '1')),
                      'c': ('q1', (None, None))
                  },
                  '$': {
                      'a': ('q0', (None, '0')),
                      'b': ('q0', (None, '1')),
                      'c': ('q1', (None, None))
                  }
              },
              'q1': {
                  '$': {
                      '': ('q2', (None, None))
                  },
                  '0': {
                      'a': ('q1', ('0', None))
                  },
                  '1': {
                      'b': ('q1', ('1', None))
                  }
              }
          },
          init_state='q0',
          final_states={'q2'})
Example #4
0
    def _mkpda(self,
               nonterms,
               productions,
               productions_struct,
               terminals,
               splitstring=1):
        """
        This function generates a PDA from a CNF grammar as described in:
          -  http://www.oit.edu/faculty/sherry.yang/CST229/Lectures/7_pda.pdf
          -  http://www.eng.utah.edu/~cs3100/lectures/l18/pda-notes.pdf

        If all of the grammar productions are in the Chomsky Normal Form,
        then follow the template for constructing a pushdown symautomata:

        1. Start
        2. Push S
        3. Pop
        4. Case:
            Nonterminal A: For every production rule of this form: A: BC, Push C and then Push B

        Args:
             nonterms (list): Non terminals list
             productions (dict): productions in the CNF form:
                                    A -> a or A -> b0b1, or S -> e
             productions_struct (dict):  productions in the CNF form in structure form
                                    object.a for A -> a,
                                    object.b0 and object.b1 for A -> b0b1
                                    and object.type where type is
                                        1 for A-->a and 2 for A-->b0b1
             terminals (list): All terminals
             splitstring (bool): If enabled an extra space is added after each symbol.
        Returns:
            PDA: The generated PDA
        """
        pda = PDA(self.alphabet)
        pda.nonterminals = nonterms
        pda.terminals = terminals

        pda.s[pda.n] = PDAState()
        pda.s[pda.n].id = pda.n
        pda.s[pda.n].sym = '@closing'
        pda.s[pda.n].type = 1
        pda.s[pda.n].trans[1] = [0]

        pda.n = pda.n + 1
        pda.s[pda.n] = PDAState()
        pda.s[pda.n].id = pda.n
        pda.s[pda.n].type = 1
        pda.s[pda.n].sym = nonterms[0]
        pda.s[pda.n].trans[2] = [0]

        pda.n = pda.n + 1
        pda.s[pda.n] = PDAState()
        pda.s[pda.n].id = pda.n
        pda.s[pda.n].type = 2
        pda.s[pda.n].trans[0] = ['@closing']

        counter = 0
        i = 0
        while i < len(nonterms):
            j = 0
            while j < len(productions[nonterms[i]]):
                if productions_struct[counter].type == 1:
                    # ADD AND CONNECT STATE
                    pda.n = pda.n + 1
                    pda.s[pda.n] = PDAState()
                    pda.s[pda.n].id = pda.n
                    if pda.n not in pda.s[2].trans:
                        pda.s[2].trans[pda.n] = []
                    pda.s[2].trans[pda.n].append(nonterms[i])

                    if splitstring == 0:

                        # FILL NEW STATE  READ
                        pda.s[pda.n].type = 3
                        pda.s[pda.n].trans[2] = [productions_struct[counter].a]

                    else:
                        # THE FOLLOWIN SWITCH IS DUE TO THE REQUIREMENT OF
                        # HAVING STRINGS SPLITTED TO SYMBOLS AND CAN INTERSECT
                        # WITH DFA

                        if productions_struct[counter].a not in terminals or \
                                        len(productions_struct[counter].a) == 1:
                            # FILL NEW STATE  READ
                            pda.s[pda.n].type = 3
                            pda.s[pda.n].trans[pda.n + 1] = [
                                productions_struct[counter].a.lower()
                            ]
                            pda.n = pda.n + 1
                            pda.s[pda.n] = PDAState()
                            pda.s[pda.n].id = pda.n
                            pda.s[pda.n].type = 3
                            pda.s[pda.n].trans[2] = [' ']

                        else:
                            pda.s[pda.n].type = 3
                            pda.s[pda.n].trans[pda.n + 1] = \
                                [productions_struct[counter].a[0].lower()]
                            k = 1
                            while k < len(productions_struct[counter].a) - 1:
                                pda.n = pda.n + 1
                                pda.s[pda.n] = PDAState()
                                pda.s[pda.n].id = pda.n
                                pda.s[pda.n].type = 3
                                pda.s[pda.n].trans[pda.n +1] = \
                                    [productions_struct[counter].a[k].lower()]
                                k = k + 1
                            pda.n = pda.n + 1
                            pda.s[pda.n] = PDAState()
                            pda.s[pda.n].id = pda.n
                            pda.s[pda.n].type = 3

                            pda.s[pda.n].trans[pda.n + 1] = \
                                [productions_struct[counter].a[-1].lower()]
                            pda.n = pda.n + 1
                            pda.s[pda.n] = PDAState()
                            pda.s[pda.n].id = pda.n
                            pda.s[pda.n].type = 3
                            pda.s[pda.n].trans[2] = [' ']

                else:
                    # ADD AND CONNECT PUSH STATE
                    pda.n = pda.n + 1
                    pda.s[pda.n] = PDAState()
                    pda.s[pda.n].id = pda.n
                    if pda.n not in pda.s[2].trans:
                        pda.s[2].trans[pda.n] = []
                    pda.s[2].trans[pda.n].append(nonterms[i])

                    # FILL NEW STATE
                    pda.s[pda.n].type = 1
                    pda.s[pda.n].sym = productions_struct[counter].b1
                    pda.s[pda.n].trans[(pda.n) + 1] = [0]

                    # ADD AND CONNECT PUSH STATE (ALREADY CONNECTED)
                    pda.n = pda.n + 1
                    pda.s[pda.n] = PDAState()
                    pda.s[pda.n].id = pda.n

                    # FILL NEW STATE
                    pda.s[pda.n].type = 1
                    pda.s[pda.n].sym = productions_struct[counter].b0
                    pda.s[pda.n].trans[2] = [0]

                j = j + 1
                counter = counter + 1

            i = i + 1
        return pda
#!/usr/bin/env python2
import sys
sys.path.insert(0, '../pda/')

from pda import PDA

# This pda loop infinitely.

pda = PDA(states={'q0', 'q1'},
          input_symbols={'a', 'b'},
          stack_symbols={'0'},
          transitions={
              'q0': {
                  '': [{
                      '0': ('q0', ['0'])
                  }]
              },
          },
          initial_state='q0',
          initial_stack_symbol='0',
          final_states={'q1'})

print(pda.validate_input('ab'))
def read_input(input_path):
    input_file = open(input_path, "r")
    regex = input_file.readline()
    input_file.close()
    return regex


if __name__ == '__main__':
    input_path = sys.argv[1]
    output_path_nfa = sys.argv[2]
    output_path_dfa = sys.argv[3]

    # add concatenation symbol into the regex
    regex = precompute_regex(read_input(input_path))

    pda = PDA()
    nfa = NFA()

    # Construieste arborele de parsare
    parse_tree = pda.parseExpression(regex)

    # Adauga root-ul arboerlui de parsare in NFA
    nfa.transitions[0, parse_tree] = 1
    # Creeaza NFA
    nfa.create_NFA(0)

    # Scrie in fisier NFA-ul
    nfa.write_output(output_path_nfa)

    # Foloseste codul din tema2 pentru a transforma NFA-ul obtinut din regex in DFA
    #convert_to_dfa(output_path_nfa, output_path_dfa)
Example #7
0
import sys
import io
from pda import PDA

if __name__ == "__main__":
    input_stream = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8')
    lines = input_stream.readlines()
    pda = PDA.parse(lines)
    grammar = pda.to_cfg()
    sys.stdout.buffer.write((str(grammar) + "\n").encode('utf-8'))
Example #8
0
pda = PDA(
    states={'q0', 'q1', 'q2'},
    input_symbols={'a', 'b', 'c'},
    stack_symbols={'a', 'b', 'c', 'x'},
    transitions={
        'q0': {
            'a': [{
                    # Add 'a' to stack.
                    'x': ('q0', ['a', 'x']),
                    'a': ('q0', ['a', 'a']),
                    'b': ('q0', ['a', 'b']),
                    'c': ('q0', ['a', 'c']),
                  }],
            'b': [{
                    # Add 'b' to stack.
                    'x': ('q0', ['b', 'x']),
                    'a': ('q0', ['b', 'a']),
                    'b': ('q0', ['b', 'b']),
                    'c': ('q0', ['b', 'c']),
                  }],
            'c': [{
                    # Add 'c' to stack.
                    'x': ('q0', ['c', 'x']),
                    'a': ('q0', ['c', 'a']),
                    'b': ('q0', ['c', 'b']),
                    'c': ('q0', ['c', 'c']),
                  }],
            '' : [{
                    # Guess the middle of the word, keep the stack.
                    'x': ('q1', ['x']),
                    'a': ('q1', ['a']),
                    'b': ('q1', ['b']),
                    'c': ('q1', ['c']),
                  },
                  {
                    # Guess the middle of the word, remove last letter from stack
                    #  (to match palindromes of odd length).
                    'x': ('q1', []),
                    'a': ('q1', []),
                    'b': ('q1', []),
                    'c': ('q1', []),
                  }],
        },

        'q1': {
            # Unwind the stack and check for matching letters.
            'a': [{ 'a': ('q1', []) }],
            'b': [{ 'b': ('q1', []) }],
            'c': [{ 'c': ('q1', []) }],

            # Stack empty -> go to final state.
            # Final state has to transitions -> it fails if some letters are left.
            '' : [{'x': ('q2', ['x'])}]
        },
    },
    initial_state='q0',
    initial_stack_symbol='x',
    final_states={'q2'}
)
Example #9
0
pda = PDA(states={'q0', 'q1', 'q2', 'q3'},
          input_symbols={'0', '1'},
          stack_symbols={'1', '0'},
          transitions={
              'q0': {
                  '0': [{
                      '1': ('q1', ['1', '0'])
                  }],
                  '': [{
                      '1': ('q1', ['1', '0'])
                  }]
              },
              'q1': {
                  '0': [{
                      '1': ('q1', ['1', '1'])
                  }],
                  '1': [{
                      '1': ('q2', [])
                  }]
              },
              'q2': {
                  '0': [{
                      '1': ('q2', [])
                  }],
                  '': [{
                      '0': ('q3', ['0'])
                  }]
              }
          },
          initial_state='q0',
          initial_stack_symbol='0',
          final_states={'q3'})
Example #10
0
pda = PDA(
    states={'q0', 'q1', 'q2', 'q3'},
    input_symbols={'a', 'b'},
    stack_symbols={'0', '1'},
    transitions={
        'q0': {
            'a': [{
                '0': ('q1', ['1', '0'])
            }],  # transition pushes '1' to stack
            '': [{
                '0': ('q3', ['0'])
            }]
        },
        'q1': {
            'a': [{
                '1': ('q1', ['1', '1'])
            }],
            'b': [{
                '1': ('q2', [])
            }]  # transition pops from stack
        },
        'q2': {
            'b': [{
                '1': ('q2', [])
            }],
            '': [{
                '0': ('q3', ['0'])
            }]  # transition does not change stack
        }
    },
    initial_state='q0',
    initial_stack_symbol='0',
    final_states={'q3'})
Example #11
0
    def _intesect(self):
        """The intesection of a PDA and a DFA"""
        p1automaton = self.mma
        p2automaton = self.mmb
        p3automaton = PDA(self.alphabet)
        self._break_terms()
        p1counter = 0
        p3counter = 0
        p2states = list(p2automaton.states)
        print 'PDA States: ' + repr(p1automaton.n)
        print 'DFA States: ' + repr(len(list(p2states)))
        ignorechars = p1automaton.nonterminals + [0] + ['@closing']
        del (ignorechars[ignorechars.index('S')])
        while p1counter < p1automaton.n + 1:
            p1state = p1automaton.s[p1counter]
            p2counter = 0
            while p2counter < len(list(p2states)):
                p2state = p2states[p2counter]
                tempstate = PDAState()
                tempstate.id = (p1state.id, p2state.stateid)
                tempstate.sym = p1state.sym
                tempstate.type = p1state.type
                tempstate.trans = {}
                found = 0
                for char in self.alphabet:
                    if char in ignorechars:
                        continue
                    # DFA has single destination from a state
                    p2dest = self._delta(p2automaton, p2state, char)
                    # PDA may have multiple destinations from a state
                    # print p1state.trans
                    if p2dest is not None:
                        for potential in p1state.trans:
                            if char in p1state.trans[potential]:
                                found = 1
                                p1dest = potential
                                if (p1dest,
                                        p2dest.stateid) not in tempstate.trans:
                                    tempstate.trans[(p1dest,
                                                     p2dest.stateid)] = []
                                    # print 'Appending A Transition to
                                    # ('+`p1dest`+','+`p2dest.stateid`+') for
                                    # input '+`char`
                                tempstate.trans[(p1dest,
                                                 p2dest.stateid)].append(char)

                                # THEN THE NONTERMINALS + 0 3 transitions
                                # print p1state.trans
                                #               print p1automaton.nonterminals
                if found == 0 and p1state.type == 3 and len(p1state.trans) > 0:
                    assert 1==1,'Check Failed: A READ state with transitions' \
                                ' did not participate in the cross product'
                if p2dest is not None:
                    for nonterm in p1automaton.nonterminals + \
                            [0] + ['@closing']:
                        for potential in p1state.trans:
                            if nonterm in p1state.trans[potential]:
                                p1dest = potential
                                if (p1dest, p2state.stateid
                                    ) not in tempstate.trans:
                                    tempstate.trans[(p1dest,
                                                     p2state.stateid)] = []
                                # print 'Appending B Transition to
                                # ('+`p1dest`+','+`p2state.stateid`+') for
                                # input '+`nonterm`
                                tempstate.trans[(
                                    p1dest, p2state.stateid)].append(nonterm)
                p3automaton.s[p3counter] = tempstate
                p3counter = p3counter + 1
                p2counter = p2counter + 1
            p1counter = p1counter + 1
        # print 'Total States Appended '+`len(p3automaton.input_string)`
        p3automaton.n = p3counter - 1

        p3automaton.accepted = []
        for state in p2automaton.states:
            if state.final != TropicalWeight(float('inf')):
                p3automaton.accepted.append(state.stateid)
        return p3automaton
Example #12
0
class MainWindow(object):
    def setupUi(self, main_window):
        main_window.setObjectName("main_window")
        main_window.resize(800, 600)
        self.central_widget = QtWidgets.QWidget(main_window)
        self.central_widget.setObjectName("central_widget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.central_widget)
        self.horizontalLayout.setContentsMargins(11, 11, 11, 11)
        self.horizontalLayout.setSpacing(6)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.center_image = QtSvg.QSvgWidget(self.central_widget)
        self.center_image.setObjectName("center_image")
        self.horizontalLayout.addWidget(self.center_image)
        main_window.setCentralWidget(self.central_widget)
        self.menu_bar = QtWidgets.QMenuBar(main_window)
        self.menu_bar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menu_bar.setObjectName("menu_bar")
        self.menu_file = QtWidgets.QMenu(self.menu_bar)
        self.menu_file.setObjectName("menu_file")
        self.menu_export_as = QtWidgets.QMenu(self.menu_file)
        self.menu_export_as.setObjectName("menu_export_as")
        self.menu_help = QtWidgets.QMenu(self.menu_bar)
        self.menu_help.setObjectName("menu_help")
        self.menu_pda = QtWidgets.QMenu(self.menu_bar)
        self.menu_pda.setObjectName("menu_pda")
        main_window.setMenuBar(self.menu_bar)
        self.action_open_pda = QtWidgets.QAction(main_window)
        self.action_open_pda.setIconVisibleInMenu(False)
        self.action_open_pda.setObjectName("action_open_pda")
        self.action_open_pda.triggered.connect(self.open_pda)
        self.action_exit = QtWidgets.QAction(main_window)
        self.action_exit.setObjectName("action_exit")
        self.action_exit.triggered.connect(self.app_exit)
        self.action_about = QtWidgets.QAction(main_window)
        self.action_about.setObjectName("action_about")
        self.action_about.triggered.connect(self.show_about_dialog)
        self.action_gv = QtWidgets.QAction(main_window)
        self.action_gv.setObjectName("action_gv")
        self.action_gv.triggered.connect(lambda: self.export_as('gv'))
        self.action_pdf = QtWidgets.QAction(main_window)
        self.action_pdf.setObjectName("action_pdf")
        self.action_pdf.triggered.connect(lambda: self.export_as('pdf'))
        self.action_png = QtWidgets.QAction(main_window)
        self.action_png.setObjectName("action_png")
        self.action_png.triggered.connect(lambda: self.export_as('png'))
        self.action_svg = QtWidgets.QAction(main_window)
        self.action_svg.setObjectName("action_svg")
        self.action_svg.triggered.connect(lambda: self.export_as('svg'))
        self.action_convert = QtWidgets.QAction(main_window)
        self.action_convert.setObjectName("action_convert")
        self.action_convert.triggered.connect(self.convert_to_cfg)
        self.menu_export_as.addAction(self.action_gv)
        self.menu_export_as.addAction(self.action_pdf)
        self.menu_export_as.addAction(self.action_png)
        self.menu_export_as.addAction(self.action_svg)
        self.menu_file.addAction(self.action_open_pda)
        self.menu_file.addAction(self.menu_export_as.menuAction())
        self.menu_file.addSeparator()
        self.menu_file.addAction(self.action_exit)
        self.menu_help.addAction(self.action_about)
        self.menu_pda.addAction(self.action_convert)
        self.menu_bar.addAction(self.menu_file.menuAction())
        self.menu_bar.addAction(self.menu_pda.menuAction())
        self.menu_bar.addAction(self.menu_help.menuAction())

        self.retranslateUi(main_window)
        QtCore.QMetaObject.connectSlotsByName(main_window)

    def retranslateUi(self, main_window):
        _translate = QtCore.QCoreApplication.translate
        main_window.setWindowTitle(_translate("main_window", "PDA to CFG"))
        self.menu_file.setTitle(_translate("main_window", "File"))
        self.menu_export_as.setTitle(_translate("main_window", "Export as..."))
        self.menu_help.setTitle(_translate("main_window", "Help"))
        self.menu_pda.setTitle(_translate("main_window", "PDA"))
        self.action_open_pda.setText(_translate("main_window", "Open PDA"))
        self.action_open_pda.setShortcut(_translate("main_window", "Ctrl+O"))
        self.action_exit.setText(_translate("main_window", "Exit"))
        self.action_exit.setShortcut(_translate("main_window", "Ctrl+Q"))
        self.action_about.setText(_translate("main_window", "About"))
        self.action_about.setShortcut(_translate("main_window", "Ctrl+H"))
        self.action_gv.setText(_translate("main_window", ".gv"))
        self.action_pdf.setText(_translate("main_window", ".pdf"))
        self.action_png.setText(_translate("main_window", ".png"))
        self.action_svg.setText(_translate("main_window", ".svg"))
        self.action_convert.setText(_translate("main_window",
                                               "Convert to CFG"))

        self.set_menu_state(False)

    def set_menu_state(self, state):
        self.action_gv.setEnabled(state)
        self.action_pdf.setEnabled(state)
        self.action_png.setEnabled(state)
        self.action_svg.setEnabled(state)
        self.action_convert.setEnabled(state)

    def app_exit(self):
        sys.exit(0)

    def open_pda(self):
        file_name, _ = QtWidgets.QFileDialog.getOpenFileName(
            self.central_widget, 'Open PDA file...', '.', 'XML Files (*.xml)')

        if file_name:
            self.set_menu_state(True)

            self.pda = PDA(file_name)

            f = Digraph('pda_machine', filename='pda_tmp.gv', format='svg')
            f.attr(rankdir='LR', size='8,5')

            # Setup initial state
            f.attr('node', shape='plaintext')
            f.node(' ')
            f.attr('node', shape='circle')
            f.node(self.pda.initial_state)
            f.edge(' ', self.pda.initial_state, ' ')

            # Setup final states
            f.attr('node', shape='doublecircle')
            for fs in self.pda.final_states:
                f.node(fs)

            # Setup other states and transitions
            f.attr('node', shape='circle')
            for tr in self.pda.transitions:
                f.edge(
                    tr['source'], tr['destination'],
                    '{},{},{}'.format(PDA.lamb(tr['input']),
                                      PDA.lamb(tr['stack_read']),
                                      PDA.lamb(tr['stack_write'])))

            self.graph = f

            f.render()
            self.center_image.load('pda_tmp.gv.svg')

    def export_as(self, file_type):
        file_name, _ = QtWidgets.QFileDialog.getSaveFileName(
            self.central_widget, 'Export as' + file_type, '',
            file_type.upper() + ' Files (*.' + file_type + ')')

        if file_name:
            self.graph.format = file_type
            self.graph.render(file_name)

    def convert_to_cfg(self):
        self.cfg = self.pda.convert_to_cfg()

        messageBox = QtWidgets.QMessageBox()
        messageBox.setText('<font size=16>' + '<br>'.join(self.cfg) +
                           '</font>')
        messageBox.setWindowTitle('Result CFG')
        messageBox.exec_()

    def show_about_dialog(self):
        QtWidgets.QMessageBox.information(self.central_widget, 'About me',
                                          'Programmer: AliReza Beitari')