コード例 #1
0
ファイル: test_TuringMachineParser.py プロジェクト: jponf/UTM
    def test_parse_utf8(self):
        parser = TuringMachineParser()
        parser.parse_string(TEST_UTF8)
        tm = parser.create()

        self.assertTrue(tm.is_word_accepted('0000'))
        self.assertFalse(tm.is_word_accepted('1011'))
コード例 #2
0
ファイル: utm.py プロジェクト: jponf/UTM
    def __init__(self):
        super().__init__()

        self.parser = TuringMachineParser()
        self.turing_machine = None
        self.main_vbox = QtGui.QVBoxLayout(self)
コード例 #3
0
ファイル: utm.py プロジェクト: jponf/UTM
class GUI(QtGui.QWidget):
    
    TAPE_SIZE = 31
    TAPE_HEAD = TAPE_SIZE // 2
    TAPE_HEAD_LEFT = TAPE_HEAD - 1
    TAPE_HEAD_RIGHT = TAPE_HEAD + 1
    DEF_WIDTH = 800
    DEF_HEIGHT = 600
    H_SPACING = 10
    V_SPACING = 5

    # Tape style(s)
    TAPE_HEAD_STYLE = 'QLineEdit { border: 2px solid red; background: white;}'

    def __init__(self):
        super().__init__()

        self.parser = TuringMachineParser()
        self.turing_machine = None
        self.main_vbox = QtGui.QVBoxLayout(self)

    def init_gui(self):
        # Configure window
        self.setMinimumSize(GUI.DEF_WIDTH, GUI.DEF_HEIGHT)   
        self.setWindowTitle(__program__)

        # Set GUI icon
        self._init_icon()
        # Add Tape widgets
        self._init_tape()
        # Add log text box
        self._init_log_area()
        # Add controls
        self._init_control_area()
        # Install handlers
        self._install_handlers()
        
        self.resize(GUI.DEF_WIDTH, GUI.DEF_HEIGHT)

    def redraw_tape(self, head_pos):
        blank = self.turing_machine.get_blank_symbol()

        # sym = self.turing_machine.getSymbolAt(head_pos)
        # self.tape_textboxes[GUI.TAPE_HEAD].setText(
        #    '' if sym == blank else str(sym))

        for i in range(GUI.TAPE_HEAD + 1):
            txt_box_index = GUI.TAPE_HEAD - i
            tape_index = head_pos - i
            sym = self.turing_machine.get_symbol_at(tape_index)
            self.tape_textboxes[txt_box_index].setText(
                '' if sym == blank else str(sym))

        for inc, i in enumerate(range(GUI.TAPE_HEAD + 1, GUI.TAPE_SIZE)):
            tape_index = head_pos + inc + 1
            sym = self.turing_machine.get_symbol_at(tape_index)
            self.tape_textboxes[i].setText('' if sym == blank else str(sym))

    def print_error_log(self, error):
        """Prints a message on the log_textbox
        Text Color: RED
        """
        self.log_textbox.setTextColor(Qt.red)
        self.log_textbox.setFontWeight(QtGui.QFont.Normal)
        self.log_textbox.append(error)

    def print_info_log(self, msg):
        """Prints a message on the log_textbox
        Text Color: BLACK
        """
        self.log_textbox.setTextColor(Qt.black)
        self.log_textbox.setFontWeight(QtGui.QFont.Normal)
        self.log_textbox.append(msg)

    def print_striking_info_log(self, msg):
        """Prints a message on the log_textbox making it more visible than a
        normal log
        """
        self.log_textbox.setTextColor(Qt.darkBlue)
        self.log_textbox.setFontWeight(QtGui.QFont.Bold)
        self.log_textbox.append(msg)

    #
    # QtGui event handlers
    #

    def on_set_turing_machine_clicked(self):
        tm_str = str(self.src_textbox.toPlainText())
        try:
            self.parser.clean()
            self.parser.parse_string(tm_str)
            self.turing_machine = self.parser.create()
            self.turing_machine.attach_observer(TuringMachineObserver(self))
            
            self.print_info_log('Turing machine created')
            self.print_info_log('Current state: ' +
                                str(self.turing_machine.get_current_state()))
                                
        except Exception as e:
            self.print_error_log('Error: %s' % str(e))

    def on_set_tape_clicked(self):
        tape_str = str(self.tape_textbox.toPlainText())
        if self.turing_machine is not None:
            self.turing_machine.set_tape(tape_str)
            self.turing_machine.set_at_initial_state()
            self.print_info_log('Tape value established')
        else:
            self.print_error_log("Error: The Turing machine must be set"
                                 " before setting the tape")

    def on_run_step_clicked(self):
        try:
            self.turing_machine.run_step()
        except HaltStateException as e:
            self.print_error_log(str(e))
        except TapeNotSetException as e:
            self.print_error_log(str(e))
        except UnknownTransitionException as e:
            self.print_error_log(str(e))
        except AttributeError:
            self.print_error_log('Error: Turing machine is unset')
        except Exception as e:
            self.print_error_log(str(type(e)))

    def on_run_until_halt_clicked(self):
        try:
            if self.turing_machine.is_at_halt_state():
                self.print_error_log('Error: The Turing Machine is on halt state')
            else:
                self.print_info_log('---------- Run Until Halt ----------')
                
                try:
                    while not self.turing_machine.is_at_halt_state():
                        self.turing_machine.run_step()
                except TapeNotSetException as e:
                    self.print_error_log(str(e))
                except UnknownTransitionException as e:
                    self.print_error_log(str(e))
        except AttributeError:
            self.print_error_log('Error: Turing machine is unset')

    def on_load_clicked(self):
        fname = QtGui.QFileDialog.getOpenFileName(self, 'Load file',
                                                  os.path.expanduser('~'))
        if fname:
            f = open(fname, 'r')
            fstr = f.read()
            self.src_textbox.setPlainText(fstr)
            f.close()
            
            self.print_info_log('Loaded file: %s' % fname)

    def on_save_clicked(self):
        fname = QtGui.QFileDialog.getSaveFileName(self, 'Save file',
                                                  os.path.expanduser('~'))
        if fname:
            f = open(fname, 'w')
            fstr = str(self.src_textbox.toPlainText())
            f.write(fstr)
            f.close()
            self.print_info_log('Saved file: %s' % fname)

    def on_clear_log_clicked(self):
    
        self.log_textbox.clear()

    def on_print_all_tape(self):
        if self.turing_machine:
            try:
                tape_value = ' '.join(self.turing_machine.get_tape_iterator())
                self.print_info_log('***************************************')
                self.print_info_log('Tape Values:')
                self.print_striking_info_log(tape_value)
                self.print_info_log('***************************************')
            except Exception as e:
                self.print_error_log(str(e))
        else:
            self.print_error_log("Error: The Turing Machine must be set"
                                 " before printing the tape")

    #
    # 'Private'
    #

    def _init_icon(self):
        data = pkgutil.get_data('resources', 'icon.png')
        pix_map = QtGui.QPixmap()
        pix_map.loadFromData(data)
        self.setWindowIcon(QtGui.QIcon(pix_map))

    def _init_tape(self):
        self.tape_label = QtGui.QLabel('Tape', self)
        self.tape_hbox = QtGui.QHBoxLayout()
                
        # self.tape_lbutton = QtGui.QPushButton('<', self)
        # self.tape_rbutton = QtGui.QPushButton('>', self)
        self.tape_textboxes = self._create_tape()

        # self.tape_hbox.addWidget(self.tape_lbutton)
        for txt_box in self.tape_textboxes:
            self.tape_hbox.addWidget(txt_box)
        # self.tape_hbox.addWidget(self.tape_rbutton)

        self.main_vbox.addWidget(self.tape_label, 0, Qt.AlignCenter)        
        self.main_vbox.addLayout(self.tape_hbox, 1)
        self.main_vbox.addSpacing(GUI.V_SPACING)

    def _create_tape(self):
        tape_txt_boxes = [QtGui.QLineEdit(self) for _ in range(GUI.TAPE_SIZE)]
        for txt_box in tape_txt_boxes:
            txt_box.setReadOnly(True)
            txt_box.setFocusPolicy(Qt.NoFocus)
            txt_box.setAlignment(Qt.AlignHCenter)
            
        tape_txt_boxes[GUI.TAPE_HEAD].setStyleSheet(GUI.TAPE_HEAD_STYLE)
        return tape_txt_boxes

    def _init_log_area(self):
        
        log_vbox = QtGui.QVBoxLayout()
                
        # Add log text box
        log_label = QtGui.QLabel('Activity Log', self)
        self.log_textbox = QtGui.QTextEdit(self)
        self.log_textbox.setReadOnly(True)
        log_vbox.addWidget(log_label, 0, Qt.AlignCenter)
        log_vbox.addWidget(self.log_textbox)
        
        # Add some control buttons
        log_hbox = QtGui.QHBoxLayout() 
        self.clear_log_btn = QtGui.QPushButton('Clear Log', self)
        self.print_all_tape_btn = QtGui.QPushButton('Print All Tape', self)

        log_hbox.addWidget(self.print_all_tape_btn)        
        log_hbox.addWidget(self.clear_log_btn)
        
        log_vbox.addLayout(log_hbox)        
        
        # Add all the previous stuff to the window layout
        self.main_vbox.addLayout(log_vbox, 1)
        self.main_vbox.addSpacing(GUI.V_SPACING)

    def _init_control_area(self):
        self.ctrl_hbox = QtGui.QHBoxLayout()
        
        # Add source text box and load/save buttons
        ctrl_llabel = QtGui.QLabel("TM Source Code", self)
        self.src_textbox = QtGui.QTextEdit(self)
        highlighters.TMSourceHighlighter(self.src_textbox)
        self.src_load_btn = QtGui.QPushButton('Load', self)
        self.src_save_btn = QtGui.QPushButton('Save', self)
        
        self.ctrl_lvbox = QtGui.QVBoxLayout()
        self.ctrl_lvbox.addWidget(ctrl_llabel, 0, Qt.AlignCenter)
        self.ctrl_lvbox.addWidget(self.src_textbox)
        ctrl_btn_hbox = QtGui.QHBoxLayout()
        ctrl_btn_hbox.addWidget(self.src_load_btn)
        ctrl_btn_hbox.addWidget(self.src_save_btn)
        self.ctrl_lvbox.addLayout(ctrl_btn_hbox)
        
        # Add control buttons
        ctrl_rlabel = QtGui.QLabel("Tape's Initial Value", self)
        self.tape_textbox = QtGui.QPlainTextEdit(self)
        self.set_tm_btn = QtGui.QPushButton('Set TM', self)
        self.set_tape_btn = QtGui.QPushButton('Set Tape', self)
        self.run_step_btn = QtGui.QPushButton('Run Step', self)
        self.run_all_btn = QtGui.QPushButton('Run Until Halt', self)
        
        self.ctrl_rvbox = QtGui.QVBoxLayout()
        self.ctrl_rvbox.addWidget(ctrl_rlabel, 0, Qt.AlignCenter)
        self.ctrl_rvbox.addWidget(self.tape_textbox)
        self.ctrl_rvbox.addWidget(self.set_tm_btn)
        self.ctrl_rvbox.addWidget(self.set_tape_btn)
        self.ctrl_rvbox.addWidget(self.run_step_btn)
        self.ctrl_rvbox.addWidget(self.run_all_btn)
        
        # Add some tooltips
        self.set_tape_btn.setToolTip('Sets the tape values and forces the TM '
                                     'to be at the initial state')
       
        # Add the control area to the main layout
        self.ctrl_hbox.addLayout(self.ctrl_lvbox, 2)
        self.ctrl_hbox.addSpacing(GUI.H_SPACING)
        self.ctrl_hbox.addLayout(self.ctrl_rvbox, 1)
        self.main_vbox.addLayout(self.ctrl_hbox, 2)

    def _install_handlers(self):
        self.set_tm_btn.clicked.connect(self.on_set_turing_machine_clicked)
        self.set_tape_btn.clicked.connect(self.on_set_tape_clicked)
        self.run_step_btn.clicked.connect(self.on_run_step_clicked)
        self.run_all_btn.clicked.connect(self.on_run_until_halt_clicked)
        self.src_load_btn.clicked.connect(self.on_load_clicked)
        self.src_save_btn.clicked.connect(self.on_save_clicked)
        self.clear_log_btn.clicked.connect(self.on_clear_log_clicked)
        self.print_all_tape_btn.clicked.connect(self.on_print_all_tape)
コード例 #4
0
ファイル: test_TuringMachineParser.py プロジェクト: jponf/UTM
 def test_create(self):
     parser = TuringMachineParser()
     parser.parse_string(TEST_STR)
     self.assertIsInstance(parser.create(), TuringMachine)