Python2实现简易图灵机(附源码)

好久没更新了,最近有人委托我做了一个单纸带 图灵机的模型,我就用python写了一个简易的。写完之后想了一想,其实这东西本质上就是一个仿汇编指令语法的程序编译器。虽然是一个比较精简的实现,但我个人认为还是比较有参考价值的,因此我把代码开源给大家。
完整代码在我的github上:https://github.com/Eathoublu/EathouTuringMachine

我设计的是一个单纸带图灵机,拥有1024的个可分配内存地址。采取的是一个仿汇编语言的指令集。
废话不多说,下面放图灵机的源码:

# coding:utf8
# author: Yixiao Lan
class Memory(object):
    def __init__(self, length):
        self.space = [None for _ in range(length)]
        self.length = length

    def malloc(self):
        for idx in range(self.length):
            if self.space[idx] is None:
                return idx
        raise Exception('MemoryError', 'Out if space.')

    def set_memory(self, addr, value):
        if addr >= self.length:
            raise Exception('MemoryError', 'Address > Memory max address.')
        self.space[addr] = value
        return

    def clear_memory(self, addr):
        if addr >= self.length:
            raise Exception('MemoryError', 'Address > Memory max address.')
        self.space[addr] = None
        return

    def read_memory(self, addr):
        if addr >= self.length:
            raise Exception('MemoryError', 'Address > Memory max address.')
        return self.space[addr]


class Controller(object):
    def __init__(self):
        self.cursor = 0
        self.input_sequence = None
        self.memory = Memory(length=1000)
        self.arithmetic_logic_unit = ArithmeticLogicUnit(self.memory)

    def set_operates(self, operation_sequence_input):
        self.input_sequence = operation_sequence_input
        return

    @staticmethod
    def turn_operation_into_tuple(operation):
        opt_arg = operation.split(' ')
        if len(opt_arg) == 1:
            return opt_arg
        args = opt_arg[1].split(',')
        return opt_arg[0], args

    def run(self):
        while True:
            operation = self.input_sequence[self.cursor]
            operation_tuple = self.turn_operation_into_tuple(operation)
            self.cursor = self.arithmetic_logic_unit.operate(operation_tuple, self.cursor)
            if self.cursor == -1:
                break
        # self.watch_memory()

    def watch_memory(self):
        print('Memory state is as follow:\n{}'.format(self.memory.space))


class ArithmeticLogicUnit(object):
    def __init__(self, bond_memory):
        self.bond_memory = bond_memory

    def detect(self, value):
        if str(value)[0] == '@':
            return self.bond_memory.read_memory(int(str(value)[1:])) if self.bond_memory.read_memory(int(str(value)[1:])) else 0
        return int(value)

    @staticmethod
    def get_cursor(value):
        if str(value)[0] != '@':
            return int(value)
        return int(str(value)[1:])

    def watch_memory(self):
        print('Memory state is as follow:\n{}'.format(self.bond_memory.space))

    def operate(self, operation_tuple, pc):
        opt = operation_tuple[0]
        if len(operation_tuple) != 1:
            args = operation_tuple[1]
        if opt == 'MOV':
            self.bond_memory.set_memory(addr=self.get_cursor(args[0]), value=self.detect(args[1]))
            return pc + 1
        if opt == 'ADD':
            register = self.detect(args[0])
            if not register:
                register = 0
            register += self.detect(args[1])
            self.bond_memory.set_memory(addr=self.get_cursor(args[0]), value=register)
            return pc + 1
        if opt == 'DEC':
            register = self.detect(args[0])
            if not register:
                register = 0
            register -= self.detect(args[1])
            self.bond_memory.set_memory(addr=self.get_cursor(args[0]), value=register)
            return pc + 1
        if opt == 'MUL':
            register = self.detect(args[0])
            if not register:
                register = 0
            register *= self.detect(args[1])
            self.bond_memory.set_memory(addr=self.get_cursor(args[0]), value=register)
            return pc + 1
        if opt == 'DIV':
            register = self.detect(args[0])
            if not register:
                register = 0
            register /= self.detect(args[1])
            self.bond_memory.set_memory(addr=args[0], value=register)
            return pc + 1
        if opt == 'EQU':
            if self.detect(args[0]) == self.detect(args[1]):
                return self.get_cursor(args[3])
            return pc + 1
        if opt == 'NEQ':
            if self.detect(args[0]) != self.detect(args[1]):
                return self.get_cursor(args[3])
            return pc + 1
        if opt == 'BGT':
            if self.detect(args[0]) >= self.detect(args[1]):
                return int(args[3])
            return pc + 1
        if opt == 'SMT':
            if self.detect(args[0]) <= self.detect(args[1]):
                return int(args[3])
            return pc + 1
        if opt == 'ANB':
            if self.detect(args[0]) and self.detect(args[1]):
                return int(args[3])
            return pc + 1
        if opt == 'ORB':
            if self.detect(args[0]) or self.detect(args[1]):
                return int(args[3])
            return pc + 1
        if opt == 'JMP':
            return int(args[0])
        if opt == 'END':
            return -1
        if opt == 'DEL':
            self.bond_memory.clear_memory(addr=self.get_cursor(args[0]))
            return pc + 1
        if opt == 'MLC':
            pass
            return pc + 1
        if opt == 'VAR':
            pass
            return pc + 1
        if opt == 'PRT':
            print(self.detect(args[0]))
            return pc + 1
        if opt == 'PRTM':
            self.watch_memory()
            return pc + 1
        raise Exception('Syntax Error', 'No such opt code : {}'.format(opt))


def parser(seq, spl=';'):
    seq = seq.replace('\n', '')
    return seq.split(spl)


if __name__ == '__main__':
    with open('tape.trl', 'r') as f:
        content = f.read()
    parsed_content = parser(content)
    controller = Controller()
    controller.set_operates(parsed_content)
    controller.run()

测试程序放在tape.trl中,(trl是一个我自己定义的语言名称,其实只是个文件名而已啦)。

MOV @1,2;
MUL @1,2;
PRT @1;
DEL @1;
PRT @1;
END;

输出结果:

0
4

附上语法说明(完整readme可以去我的github看):

1. MOV @1,2    @1<-2
2. ADD @1,2    @1<-@1+2
3. DEC @1,2    @1<-@1-2
4. MUL @1,2    @1<-@1*2
5. DIV @1,2    @1<-@1/2
6. EQU 1,2,4    1=2?pc<-4:pc<-pc+1
7. NEQ 1,1,4    1!=2?pc<-4:pc<-pc+1
8. BGT 1,2,4    1>2?pc<-4:pc<-pc+1
9. SMT 1,2,4    1<2?pc<-4:pc<-pc+1
10. ANB 1,2,4    1&2?pc<-4:pc<-pc+1
11. ORB 1,2,4    1|2?pc<-4:pc<-pc+1
12. DEL @1    @1<-NULL
13. PRT @1    PRINT TO TERMINAL<-@1
14. PRTM    PRINT COMPLETE MEMORY TO TERMINAL
15. END    QUIT PROCESS

其中,@XX指的是内存地址

正如大家所见,这个图灵机模型尚为一个极其简易的模型,如果大家有兴趣,我们可以共同完善这个项目,欢迎大家到我的github:
https://github.com/Eathoublu/EathouTuringMachine 上fork这个项目,嘻嘻。
本人联系邮箱:yixiaolan@foxmail.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值