#include "DFA.h"
#include "ListFuns.h"

const int DEBUG = 1;

//************  DFAState   **************************
DFAState::DFAState(Boolean isFinal, unsigned int serNum):_neighbors()
{ 	_isFinal = isFinal;	
	_serialNumber = serNum;
}

void DFAState::addNeighbor(char on, DFAState * to)
{	_neighbors.atPut(on,to);
}

/*
DFAState::DFAState(DFAState &d)
{	_isFinal = d._isFinal;
	_neighbors = d._neighbors;
	_serialNumber = d._serialNumber;
}

DFAState::~DFAState()
{	// nothing;
}

DFAState & DFAState::operator =(DFAState &d)
{	if(this != &d)
	{	_isFinal = d._isFinal;
		_neighbors = d._neighbors;
		_serialNumber = d._serialNumber;
	}
	return *this;
}
*/
void DFAState::run(String tape)
{	if(DEBUG) cout << "node " <<_serialNumber << " tape "<< tape <<endl;
	if(tape.length() == 0)
	{	if(_isFinal)
			cout <<"Accepted.\n";
		else
			cout << "Rejected.\n";
	}
	else 
	{	DFAState * nbr;
		if(_neighbors.at(tape[0], nbr))
		{	nbr->run(tape.sub(1,tape.length()-1));
		}
		else
			cout << "No transition. Error. \n";
	}
}


//************  DFA   **************************
DFA::DFA()
:	_initial(NULL),
	_nodes(0),
	_nodeList()
{	
}

DFA::DFA(const DFA &d) { copy(d); }

DFA::~DFA(){ free(); }

DFA & DFA::operator =(const DFA &d)
{	if(this != &d)
	{	free();
		copy(d);
	}
	return *this;
}


DFAState * DFA::newNode(Boolean isFinal)
{	DFAState *result = new DFAState(isFinal,_nodes++);
	if(_initial == NULL) _initial = result;
	_nodeList = _nodeList.consElement(result);
	return result;
}

void DFA::run(String tape)
{	_initial->run(tape);
}


ostream& operator <<(ostream& out, DFAState * )
{	out << "a DFAState";
	return out;
}

void DFA::free() // Delete all of the nodes. 
{	while(!_nodeList.empty())
	{	DFAState * n = _nodeList.head();
		_nodeList = _nodeList.tail();
		delete n;
	}
	_initial = NULL;
}

void DFA::copy(const DFA & D)
{	if(! D._nodeList.empty())
	{	_initial = insertAll(_nodeList, D._nodeList);
	}
}

