Top/TuringMachineSimulator.Cc

Top | Top | recent changes | Preferences

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


Top | Top | recent changes | Preferences
This page is read-only | View other revisions
Last edited October 6, 2004 10:26 pm by Neal Young (diff)
Search: