// © Copyright1995, Joseph Bergin.  All rights reserved. 

#ifndef __TuringMachine__
#define __TuringMachine__

#include "Dictionary.h"
#include "Strngs.h"
#include "Boolean.h"
#include "List.h"

#include <iostream.h>

class TuringMachineState;
enum tapeMove {leftMove, rightMove, noMove};

struct transition
{	TuringMachineState *to;
	tapeMove which;
	char symbol;
};

class TuringMachineState  // The only way to get one is via a TM.
{	public:
		void addNeighbor
		(	char on, 
			TuringMachineState * to, 
			tapeMove d = rightMove, 
			char symbol = ' '
		); // Danger. Do not addNeighbor after its TM has been deleted.
	private:
		TuringMachineState(Boolean isFinal = false, unsigned int serNum = 0); 
			// NOT final by default;
//		TuringMachineState(const TuringMachineState &d);
//		~TuringMachineState();
//		TuringMachineState & operator =(TuringMachineState &d);
		void run(String tape, unsigned int head);
		
		Dictionary<char, transition> _neighbors;
		Boolean _isFinal;
		unsigned int _serialNumber;
	friend class TuringMachine;
};

	ostream& operator <<(ostream& out, TuringMachineState * );
	ostream& operator <<(ostream& out, transition *);

class TuringMachine
{	public:
		TuringMachine();
		TuringMachine(const TuringMachine &d);
		~TuringMachine(); // Deletes all of its nodes. 
		TuringMachine & operator =(const TuringMachine &d);
		
		TuringMachineState * newNode(Boolean isFinal = false);
			// The first node generated for a new TuringMachine is its
			// initial node.  
		void run(String tape);
	private:
		TuringMachineState * _initial;
		unsigned int _nodes;
		List<TuringMachineState *> _nodeList;
		void free();
		void copy(const TuringMachine &);
};

#endif

