#!/usr/bin/perl -w

use strict;
our(@ARGV);

my $tape_pos = 0;
my $state = undef;
my %state_trans;
my %tape_contents;

sub read_state_file{
    my $fname = shift;
    open(FILE,"<$fname") or die "Unable to open $fname";
    while(<FILE>){
        if(/^\s*(\S+)\s+(\w+)\s+(\S+)\s+(\w+)\s+([r|l|R|L])\s*(\#.*)?$/){
            if(defined $state_trans{$1}{$2}){
                #already defined state/value
                die "state $1 value $2 already defined\n";
            }else{
                $state = $1 if(!defined $state);
                $state_trans{$1}{$2} = [$3,$4,$5];
            }
        }elsif(/^$/){
            #blank line, ignore
        }else{
            print STDERR "Illigal instruction : $_\n";
        }
    }
    close(FILE);
}

sub parse{
    my $n_tape_pos = 0;
    my $n_state = undef;
    STEP:for(;;){
        $tape_contents{$tape_pos} = '_' if !defined $tape_contents{$tape_pos};
        last STEP if (!exists $state_trans{$state}{$tape_contents{$tape_pos}});
        #save new tape_pos and state for after we modify tape_contents
        $n_tape_pos = $state_trans{$state}{$tape_contents{$tape_pos}}[2] eq 'L' ? -1 : 1;
        $n_state = $state_trans{$state}{$tape_contents{$tape_pos}}[0];
        #modify tape contents
        $tape_contents{$tape_pos}= $state_trans{$state}{$tape_contents{$tape_pos}}[1];
        #set new state and tape position
        $state = $n_state;
        $tape_pos += $n_tape_pos;
    }
}

sub by_number {
  # a sort subroutine, expect $a and $b
  if ($a < $b) { -1 } elsif ($a > $b) { 1 } else { 0 }
}

sub main{
    die "nope .. not a file" if (!defined $ARGV[0]) or (! -f $ARGV[0]);
    read_state_file($ARGV[0]);
    $tape_contents{$tape_pos} = '_'; #initialize tape
    if(defined ($ARGV[1])){
        my $ctr = 0;
        foreach my $c (split('',$ARGV[1])){
            $tape_contents{$ctr++} = $c;
        }
    }
    parse();
    foreach my $c (sort by_number keys(%tape_contents)){
        print "$tape_contents{$c}";
    }
    print "\n";
}

main()
