#include "Table.h" Table::Table() { // } Table::~Table() { // } void Table::exportTable(std::ofstream &file) { //Save symbolIndexVec int size = symbolIndexVec.size(); file.write((char*)&size, sizeof(int)); for (int i = 0; i < symbolIndexVec.size(); i++) { //Save the name std::string symbolName = symbolIndexVec[i].getName(); //Get the string size = symbolName.size()+1; file.write((char*)&size, sizeof(int)); //Save size of string file.write((char*)(symbolName.c_str()), size); //Save the string //Save the value std::string symbolValue = symbolIndexVec[i].getValue(); //Get the string size = symbolValue.size()+1; file.write((char*)&size, sizeof(int)); //Save size of string file.write((char*)(symbolValue.c_str()), size); //Save the string bool isTerminal = symbolIndexVec[i].isTerminal(); file.write((char*)&isTerminal, sizeof(bool)); //Save the true false } //Save the actual table size = table.size(); file.write((char*)&size, sizeof(int)); for (int i = 0; i < table.size(); i++) { //each item is a middle vector //std::vector< std::vector< std::vector* >* > table; std::vector< std::vector* >* middleVector = table[i]; int middleVectorSize = middleVector->size(); file.write((char*)&middleVectorSize, sizeof(int)); for (int j = 0; j < middleVectorSize; j++) { //each item is an inner vector std::vector* innerVector = (*middleVector)[j]; int innerVectorSize = 0; if (innerVector) innerVectorSize = innerVector->size(); else innerVectorSize = 0; file.write((char*)&innerVectorSize, sizeof(int)); for (int k = 0; k < innerVectorSize; k++) { //Save the type ParseAction* toSave = (*innerVector)[k]; ParseAction::ActionType actionType = toSave->action; file.write((char*)&actionType, sizeof(ParseAction::ActionType)); //Save the reduce rule if necessary if (actionType == ParseAction::REDUCE) { //Save the reduce rule ParseRule* rule = toSave->reduceRule; //int pointer index int ptrIndx = rule->getIndex(); file.write((char*)&ptrIndx, sizeof(int)); //Symbol leftHandle Symbol leftHandle = rule->getLeftSide(); //Save the name std::string symbolName = leftHandle.getName(); //Get the string size = symbolName.size()+1; file.write((char*)&size, sizeof(int)); //Save size of string file.write((char*)(symbolName.c_str()), size); //Save the string //Save the value std::string symbolValue = leftHandle.getValue(); //Get the string size = symbolValue.size()+1; file.write((char*)&size, sizeof(int)); //Save size of string file.write((char*)(symbolValue.c_str()), size); //Save the string bool isTerminal = leftHandle.isTerminal(); file.write((char*)&isTerminal, sizeof(bool)); //Save the true false //std::vector* lookahead; //Should not need //std::vector rightSide; std::vector rightSide = rule->getRightSide(); size = rightSide.size(); //std::cout << leftHandle.toString() << std::endl; file.write((char*)&size, sizeof(int)); for (int l = 0; l < rightSide.size(); l++) { //Save the name symbolName = rightSide[l].getName(); //Get the string size = symbolName.size()+1; file.write((char*)&size, sizeof(int)); //Save size of string file.write((char*)(symbolName.c_str()), size); //Save the string // //Save the value symbolValue = rightSide[l].getValue(); //Get the string size = symbolValue.size()+1; file.write((char*)&size, sizeof(int)); //Save size of string file.write((char*)(symbolValue.c_str()), size); //Save the string // isTerminal = rightSide[l].isTerminal(); file.write((char*)&isTerminal, sizeof(bool)); //Save the true false } } int shiftState = toSave->shiftState; file.write((char*)&shiftState, sizeof(int)); } } } } void Table::importTable(char* tableData) { //Load symbolIndexVec int size = *((int*)tableData); tableData += sizeof(int); for (int i = 0; i < size; i++) { int stringLen = *((int*)tableData); tableData += sizeof(int); std::string symbolName = std::string(tableData); tableData += stringLen*sizeof(char); stringLen = *((int*)tableData); tableData += sizeof(int); std::string symbolValue = std::string(tableData); tableData += stringLen*sizeof(char); bool isTerminal = *((bool*)tableData); tableData += sizeof(bool); symbolIndexVec.push_back(Symbol(symbolName, isTerminal, symbolValue)); } //Now for the actual table int tableSize = *((int*)tableData); tableData += sizeof(int); for (int i = 0; i < tableSize; i++) { //each item is a middle vector std::vector< std::vector* >* middleVector = new std::vector< std::vector* >(); table.push_back(middleVector); int middleVectorSize = *((int*)tableData); tableData += sizeof(int); for (int j = 0; j < middleVectorSize; j++) { //each item is an inner vector std::vector* innerVector = new std::vector(); middleVector->push_back(innerVector); int innerVectorSize = *((int*)tableData); tableData += sizeof(int); for (int k = 0; k < innerVectorSize; k++) { //each item is a ParseRule ParseAction::ActionType action = *((ParseAction::ActionType*)tableData); tableData += sizeof(ParseAction::ActionType); //If reduce, import the reduce rule ParseRule* reduceRule = NULL; if (action == ParseAction::REDUCE) { int ptrIndx = *((int*)tableData); tableData += sizeof(int); size = *((int*)tableData); tableData += sizeof(int); std::string leftHandleName = std::string(tableData); tableData += size*sizeof(char); size = *((int*)tableData); tableData += sizeof(int); std::string leftHandleValue = std::string(tableData); tableData += size*sizeof(char); bool isTerminal = *((bool*)tableData); tableData += sizeof(bool); //right side std::vector rightSide; size = *((int*)tableData); tableData += sizeof(int); for (int l = 0; l < size; l++) { int inStringLen = *((int*)tableData); tableData += sizeof(int); std::string inSymbolName = std::string(tableData); tableData += inStringLen*sizeof(char); inStringLen = *((int*)tableData); tableData += sizeof(int); std::string inSymbolValue = std::string(tableData); tableData += inStringLen*sizeof(char); bool inIsTerminal = *((bool*)tableData); tableData += sizeof(bool); rightSide.push_back(Symbol(inSymbolName, inIsTerminal, inSymbolValue)); } reduceRule = new ParseRule(Symbol(leftHandleName, isTerminal, leftHandleValue), ptrIndx, rightSide, NULL); } int shiftState = *((int*)tableData); tableData += sizeof(int); //And push the new action back if (reduceRule) innerVector->push_back(new ParseAction(action, reduceRule)); else innerVector->push_back(new ParseAction(action, shiftState)); } } } } void Table::setSymbols(Symbol EOFSymbol, Symbol nullSymbol) { this->EOFSymbol = EOFSymbol; this->nullSymbol = nullSymbol; } void Table::add(int stateNum, Symbol tranSymbol, ParseAction* action) { //If this is the first time we're adding to the table, add the EOF character if (symbolIndexVec.size() == 0) symbolIndexVec.push_back(EOFSymbol); //If state not in table, add up to and it. //std::cout << "table size is " << table.size() <= table.size()) { //std::cout << "Pushing back table" << std::endl; table.push_back(new std::vector* >()); } //find out what index this symbol is on int symbolIndex = -1; for (std::vector::size_type i = 0; i < symbolIndexVec.size(); i++) { if ( symbolIndexVec[i] == tranSymbol ) { //Has been found symbolIndex = i; break; } } //std::cout << "symbolIndex is " << symbolIndex << std::endl; //If we've never done this symbol, add it if (symbolIndex < 0) { // std::cout << "pushing back symbolIndexVec" <toString() << std::endl; //std::cout << table[stateNum] << " "; while (symbolIndex >= table[stateNum]->size()) { table[stateNum]->push_back(NULL); } //If this table slot is empty //std::cout << "table[stateNum] is " << table[stateNum] << std::endl; //std::cout << "blank is " << (*(table[stateNum]))[symbolIndex] << std::endl; if ( (*(table[stateNum]))[symbolIndex] == NULL ) { //std::cout << "Null, adding " << action->toString() << std::endl; std::vector* actionList = new std::vector(); actionList->push_back(action); (*(table[stateNum]))[symbolIndex] = actionList; } //If the slot is not empty and does not contain ourself, then it is a conflict //else if ( !(*(table[stateNum]))[symbolIndex]->equalsExceptLookahead(*action)) { else { //std::cout << "not Null!" << std::endl; //std::cout << "State: " << stateNum << " Conflict between old: " << (*(table[stateNum]))[symbolIndex]->toString() << " and new: " << action->toString() << " on " << tranSymbol->toString() << std::endl; //Check to see if this action is already in the list //(*(table[stateNum]))[symbolIndex]->push_back(action); bool alreadyIn = false; for (std::vector::size_type i = 0; i < (*(table[stateNum]))[symbolIndex]->size(); i++) if (*((*((*(table[stateNum]))[symbolIndex]))[i]) == *action) alreadyIn = true; if (!alreadyIn) (*(table[stateNum]))[symbolIndex]->push_back(action); } } void Table::remove(int stateNum, Symbol tranSymbol) { //find out what index this symbol is on int symbolIndex = -1; for (std::vector::size_type i = 0; i < symbolIndexVec.size(); i++) { if ( symbolIndexVec[i] == tranSymbol ) { //Has been found symbolIndex = i; break; } } (*(table[stateNum]))[symbolIndex] = NULL; } std::vector* Table::get(int state, Symbol token) { int symbolIndex = -1; for (std::vector::size_type i = 0; i < symbolIndexVec.size(); i++) { if ( symbolIndexVec[i] == token) { symbolIndex = i; break; } } if (symbolIndex == -1) { std::cout << "Unrecognized symbol: " << token.toString() << ", cannot get from table!" << std::endl; return NULL; } //std::cout << "Get for state: " << state << ", and Symbol: " << token.toString() << std::endl; if (state < 0 || state >= table.size()) { std::cout << "State bad: " << state << std::endl; return NULL; } std::vector* action = NULL; if (symbolIndex < 0 || symbolIndex >= table[state]->size()) { //std::cout << "Symbol bad for this state: " << token.toString() << ". This is a reject." << std::endl; } else { action = (*(table[state]))[symbolIndex]; } //This is the accepting state, as it is the 1th's state's reduction on EOF, which is 0 in the symbolIndexVec //(This assumes singular goal assignment, a simplification for now) if (state == 1 && symbolIndex == 0) { if (action == NULL) action = new std::vector(); action->push_back(new ParseAction(ParseAction::ACCEPT)); } //If outside the symbol range of this state (same as NULL), reject if ( symbolIndex >= table[state]->size() ) { action = new std::vector(); action->push_back(new ParseAction(ParseAction::REJECT)); } //If null, reject. (this is a space with no other action) if (action == NULL) { action = new std::vector(); action->push_back(new ParseAction(ParseAction::REJECT)); } //Otherwise, we have something, so return it return action; } ParseAction* Table::getShift(int state, Symbol token) { std::vector* actions = get(state, token); ParseAction* shift = NULL; for (int i = 0; i < actions->size(); i++) { if ((*actions)[i]->action == ParseAction::SHIFT) { shift = (*actions)[i]; break; } } return shift; } std::vector> Table::stateAsParseActionVector(int state) { std::vector> reconstructedState; std::vector*>* stateVec = table[state]; for (int i = 0; i < stateVec->size(); i++) if (std::vector* forStateAndSymbol = (*stateVec)[i]) for (int j = 0; j < forStateAndSymbol->size(); j++) reconstructedState.push_back(std::make_pair(symbolIndexVec[i].toString(),*((*forStateAndSymbol)[j]))); return reconstructedState; } std::string Table::toString() { std::string concat = ""; for (std::vector::size_type i = 0; i < symbolIndexVec.size(); i++) concat += "\t" + symbolIndexVec[i].toString(); concat += "\n"; for (std::vector< std::vector< std::vector< ParseRule* >* >* >::size_type i = 0; i < table.size(); i++) { concat += intToString(i) + " is the state\t"; for (std::vector< std::vector< ParseRule* >* >::size_type j = 0; j < table[i]->size(); j++) { concat += "for " + symbolIndexVec[j].toString() + " do "; if ( (*(table[i]))[j] != NULL) { for (std::vector< ParseRule* >::size_type k = 0; k < (*(table[i]))[j]->size(); k++) { concat += (*((*(table[i]))[j]))[k]->toString() + "\t"; } } else { concat += "NULL\t"; } } concat += "\n"; } return(concat); }