#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); }