#!/usr/bin/python
from string import split, join
from sys import argv
class TM:
blank = "_"
accept = "accept"
reject = "reject"
start = "start"
left = "L"
right = "R"
#### Tape
class Tape:
def __init__(self, input):
self.head = 0
self.contents = [x for x in input]
def move_left(self):
if(self.head > 0): self.head -= 1
def move_right(self):
self.head += 1
if (self.head >= len(self.contents)):
self.contents.append(TM.blank)
def read_symbol(self):
return self.contents[self.head]
def write_symbol(self, symbol):
self.contents[self.head] = symbol
def str(self):
return join(self.contents, "") + "\n" + (" " * self.head) + "^"
#### Transition Function
class TransitionFunction:
def __init__(self, file):
self.table = {}
try: file = open(file, 'r')
except IOError:
print "Can't open TM defn file", file
raise SystemExit
line_number = 0
def check(cond, *msg):
if (not cond):
print transition_file, ":", line_number, ":", msg
raise SystemExit
for line in file.readlines():
++line_number
parts = split(line, None, 5)
if len(parts) == 0: continue
check(len(parts) >= 5,
"only", len(parts), "words on line")
if len(parts) == 5: parts.append("")
(state1, symbol1, state2, symbol2, move, comment) = parts
check(move == TM.right or move == TM.left,
"unknown move:", move)
check(not self.table.has_key((state1, symbol1)),
"redundant transition:", line)
self.table[state1, symbol1] = (state2, symbol2, move, comment)
def lookup(self, state, symbol):
if (self.table.has_key((state, symbol))):
return self.table[state, symbol]
return (TM.reject, TM.blank, TM.left, "")
#### Turing Machine
def __init__(self, transition_file, initial_tape_str):
self.tape = TM.Tape(initial_tape_str)
self.fn = TM.TransitionFunction(transition_file)
self.state = TM.start
def step(self):
print self.tape.str(), self.state
symbol = self.tape.read_symbol()
(self.state, symbol, move, comment) = self.fn.lookup(self.state, symbol)
self.tape.write_symbol(symbol)
if (move == TM.left): self.tape.move_left()
else: self.tape.move_right()
def run(self):
while (1):
if (self.state == TM.reject): return 0
if (self.state == TM.accept): return 1
self.step()
if __name__ == "__main__":
usage = "usage: " + argv[0] + " tmfilename initialtapestring"
if len(argv) != 3:
print usage
raise SystemExit
tm = TM(argv[1], argv[2])
if (tm.run()): print "accept"
else: print "reject"