#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define MAXWORDSIZE 100
#define BLANK ' '
void die(char *msg);
char *copy_string(char *s) {
char *t = new char[strlen(s)+1];
strcpy(t,s);
return t;
}
// store transition function in linked list of transitions
struct Transition {
char *from_state, *to_state;
char from_symbol, to_symbol;
char tape_head_move;
Transition *next_transition;
};
struct TuringMachine {
char *tape;
int tape_head_location;
int tape_size;
char *state;
Transition *transition_fn;
TuringMachine(char *filename) {
tape_size = 100;
tape_head_location = 0;
tape = new char[tape_size];
for (int i = 0; i < tape_size; ++i) {
tape[i] = BLANK;
}
state = "start";
transition_fn = NULL;
FILE * tm_file = fopen(filename, "r");
if (! tm_file) die("unable to open file");
while (1) {
char from_state[MAXWORDSIZE], to_state[MAXWORDSIZE];
char from_symbol, to_symbol, tape_head_move;
int n =
fscanf(tm_file, "%s %c %s %c %c\n",
from_state,
&from_symbol,
to_state,
&to_symbol,
&tape_head_move);
if (n == -1) break;
if (n != 5) die("syntax error");
add_transition(from_state, from_symbol, to_state, to_symbol, tape_head_move);
}
}
~TuringMachine() {
Transition *t = transition_fn, *next;
for (t = transition_fn; t; t = next) {
next = t->next_transition;
delete[] t->from_state;
delete[] t->to_state;
delete t;
}
}
void grow_tape() {
tape_size *= 2;
char *new_tape = new char[tape_size];
for (int i = 0; i < tape_size; ++i)
if (i < tape_size/2)
new_tape[i] = tape[i];
else
new_tape[i] = BLANK;
delete[] tape;
tape = new_tape;
}
void
add_transition(char *from_state, char from_symbol, char *to_state, char to_symbol, char tape_head_move) {
Transition * t = new Transition;
t->from_state = copy_string(from_state);
t->to_state = copy_string(to_state);
t->from_symbol = from_symbol;
t->to_symbol = to_symbol;
t->tape_head_move = tape_head_move;
t->next_transition = transition_fn;
if (0)
cout << "added ("
<< from_state << ", " << from_symbol
<< ") -> ("
<< to_state << ", " << to_symbol << ", " << tape_head_move
<< ")" << endl;
transition_fn = t;
}
void
do_transition() {
char from_symbol = tape[tape_head_location];
char *from_state = state;
Transition *t = transition_fn;
char to_symbol, *to_state, tape_head_move;
if (0)
cout << "looking for (" << from_state << ", " << from_symbol << ")" << endl;
while (1) {
if (!t) {
to_state = "reject";
to_symbol = BLANK;
tape_head_move = 'L';
break;
}
if (0)
cout << "comparing (" << t->from_state << ", " << t->from_symbol << ")" << endl;
if (strcmp(t->from_state, from_state) == 0 && from_symbol == t->from_symbol) {
to_state = t->to_state;
to_symbol = t->to_symbol;
tape_head_move = t->tape_head_move;
break;
}
t = t->next_transition;
}
state = to_state;
tape[tape_head_location] = to_symbol;
if (tape_head_move == 'L') {
if (tape_head_location > 0)
--tape_head_location;
} else if (tape_head_move == 'R') {
++tape_head_location;
if (tape_head_location >= tape_size)
grow_tape();
} else
die("bad tape_head_move");
}
void print_configuration() {
for (int i = 0; i < tape_size; ++i) cout << tape[i];
cout << "..." << endl;
for (int i = 0; i < tape_head_location; ++i) cout << " ";
cout << "^ " << state << endl;
}
bool run(char *input) {
int n = strlen(input);
while (n >= tape_size) grow_tape();
for (int i = 0; i < n; ++i) tape[i] = input[i];
print_configuration();
while (1) {
if (strcmp(state, "reject") == 0) {
return 0;
}
if (strcmp(state, "accept") == 0) {
return 1;
}
do_transition();
print_configuration();
}
}
};
main(int argc, char *argv[]) {
if (argc != 3) die("arg count");
char *tm_filename = argv[1];
char *input_string = argv[2];
// build turing machine
TuringMachine tm(tm_filename);
if (tm.run(input_string))
cout << "ACCEPT" << endl;
else
cout << "REJECT" << endl;
}
void die(char *msg) {
cerr << msg << endl;
exit(-1);
}