MODULE the_tape
INTEGER, ALLOCATABLE :: tape(:), transitions(:, :)
INTEGER :: left_edge, right_edge, tape_head_position, tape_size
END MODULE
MODULE states_and_transitions
INTEGER :: accept_state, current_state, current_transition, cardinality_alphabet
END MODULE
program turing_machine_simulator
USE the_tape
USE states_and_transitions
INTEGER :: next_, write_, read_
CHARACTER :: move_
CHARACTER(100) :: tape_prototype, arg
INTEGER :: cardinality_Q
external handle_sigint ! Must declare as external
call get_command_argument(1, arg)
OPEN(UNIT = 12, FILE=arg)
READ(12,*) cardinality_Q
READ(12,*) cardinality_alphabet
cardinality_alphabet = cardinality_alphabet + 1
allocate(transitions(3, cardinality_alphabet * cardinality_Q))
do 1 i=1, cardinality_alphabet * cardinality_Q
READ(12,*) next_, write_, move_
transitions(1:3, i) = (/ next_ + 1, write_, merge(1, -1, move_=='R') /)
1 continue
READ(12, *) tape_prototype
WRITE(*,*) tape_prototype
CLOSE(12)
allocate(tape(len(tape_prototype)))
do 2 i=1, len(tape_prototype)
tape(i) = IACHAR(tape_prototype(i:i)) - IACHAR('0')
2 continue
call SIGNAL(2, handle_sigint)
current_state = 1
accept_state = cardinality_Q + 1
tape_head_position = 1
left_edge = 1
right_edge = len(trim(tape_prototype))
tape_size = right_edge
call run
call print_tape
deallocate(tape)
deallocate(transitions)
end program
SUBROUTINE run
USE the_tape
USE states_and_transitions
INTEGER :: read_
read_ = 0
current_transition = 1
do while(current_state .NE. accept_state)
if (tape_head_position .LT. left_edge) then
left_edge = left_edge - 1
elseif (tape_head_position .GT. right_edge) then
right_edge = right_edge + 1
endif
if (left_edge .LT. 1 .OR. right_edge .GT. tape_size) call grow_tape
read_ = tape(tape_head_position)
current_transition = ((current_state - 1) * cardinality_alphabet) + 1 + read_
tape(tape_head_position) = transitions(2, current_transition)
tape_head_position = tape_head_position + transitions(3, current_transition)
current_state = transitions(1, current_transition)
end do
end SUBROUTINE
SUBROUTINE print_tape
USE the_tape
do 10 i=left_edge, right_edge - 1 !Index by one, and this is inclusive
WRITE(*,*) tape(i)
10 continue
print *, ''
return
end SUBROUTINE
SUBROUTINE handle_sigint
USE the_tape
print *, 'Received sigint--bailing.'
call print_tape
deallocate(tape)
deallocate(transitions)
stop
end SUBROUTINE
SUBROUTINE grow_tape
USE the_tape
INTEGER :: offset
INTEGER, ALLOCATABLE :: temp(:)
print *, 'Growing every time', tape_size
offset = tape_size / 2
allocate(temp(tape_size * 2))
temp = 0 !sets everything to zero in the array
left_edge = left_edge + offset
right_edge = right_edge + offset
tape_head_position = tape_head_position + offset
temp(left_edge:right_edge) = tape(1:tape_size)
tape = temp
tape_size = tape_size * 2
deallocate(temp)
return
end SUBROUTINE
Comments
0 B
|👍
/👎
0 B
|👍
/👎