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]
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')
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'})
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)
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'))
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'} )
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'})
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'})
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
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')