Transfer computer

This commit is contained in:
Nathan Braswell
2013-06-21 14:16:16 -04:00
parent 66b88cb5d7
commit 20b059ca45
3 changed files with 37 additions and 14 deletions

View File

@@ -25,7 +25,9 @@ class Parser {
void loadGrammer(std::string grammerInputString);
std::vector<Symbol*>* firstSet(Symbol* token);
void printFirstSets();
std::vector<Symbol*>* followSet(Symbol* token);
//std::vector<Symbol*>* followSet(int stateNum, Symbol* token);
std::vector<Symbol*>* gramFollowSet(Symbol* token);
std::vector<Symbol*>* gramFollowSetAvoid(Symbol* token, std::vector<Symbol*>* avoidList);
void printFollowSets();
void createStateSet();
void closure(State* state);

View File

@@ -89,14 +89,31 @@ void Parser::printFirstSets() {
}
}
std::vector<Symbol*>* Parser::followSet(Symbol* token) {
//follow set created from grammer instead of an individual state
//May not be totally correct, but works for now. Should be simialr to LALR(1)
//To avoid infinite recursion, we call a function with an avoid list, adding ourselves to it as we go.
std::vector<Symbol*>* Parser::gramFollowSet(Symbol* token) {
std::vector<Symbol*>* avoidList = new std::vector<Symbol*>();
return gramFollowSetAvoid(token, avoidList);
}
std::vector<Symbol*>* Parser::gramFollowSetAvoid(Symbol* token, std::vector<Symbol*>* avoidList) {
std::vector<Symbol*>* follow = new std::vector<Symbol*>();
//First, if the symbol is a terminal, than it's follow set is the empty set.
if (token->isTerminal()) {
return(follow);
}
//If the token is in the avoid list, just return
for (std::vector<Symbol*>::size_type i = 0; i < avoidList->size(); i++) {
if (*token == *((*avoidList)[i]))
return(follow);
}
//If not, we're about to process it, so add it to the avoid list
avoidList->push_back(token);
//Otherwise....
//Ok, to make a follow set, go through the grammer looking for the terminal in the right side. If it exists
//Ok, to make a follow set, go through the state (indicated by stateNum) looking for the terminal in the right side. If it exists
//Then add to it's follow set the first set of the next token, or if it is at the end, the follow set of the left side.
//Theoretically, if that one includes mull, do the next one too. However, null productions have not yet been implemented.
Symbol* rightToken = NULL;
@@ -119,7 +136,7 @@ std::vector<Symbol*>* Parser::followSet(Symbol* token) {
follow->insert(follow->begin(), recursiveFollowSet->begin(), recursiveFollowSet->end());
}
} else {
recursiveFollowSet = followSet(loadedGrammer[i]->getLeftSide());
recursiveFollowSet = gramFollowSetAvoid(loadedGrammer[i]->getLeftSide(), avoidList);
follow->insert(follow->begin(), recursiveFollowSet->begin(), recursiveFollowSet->end());
}
}
@@ -131,7 +148,7 @@ std::vector<Symbol*>* Parser::followSet(Symbol* token) {
void Parser::printFollowSets() {
std::vector<Symbol*>* follow = NULL;
for (std::vector<Symbol*>::size_type i = 0; i < symbolIndexVec.size(); i++) {
follow = followSet(symbolIndexVec[i]);
follow = gramFollowSet(symbolIndexVec[i]);
std::cout << "Follow set of " << symbolIndexVec[i]->toString() << " is: ";
for (std::vector<Symbol*>::size_type j = 0; j < follow->size(); j++)
std::cout << (*follow)[j]->toString() << " ";
@@ -210,32 +227,36 @@ void Parser::addStates(std::vector< State* >* stateSets, State* state) {
//See if reduce
//Also, this really only needs to be done for the state's basis, but we're already iterating through, so...
if ((*currStateTotal)[i]->isAtEnd()) {
std::cout << (*currStateTotal)[i]->toString() << " is at end, adding reduce to table" << std::endl;
//This should iterate through the follow set, but right now is LR(0), so all symbols
for (std::vector<Symbol*>::size_type j = 0; j < symbolIndexVec.size(); j++)
addToTable(state, symbolIndexVec[j], new ParseAction(ParseAction::REDUCE, (*currStateTotal)[i]));
//std::cout << (*currStateTotal)[i]->toString() << " is at end, adding reduce to table" << std::endl;
//Iterates through follow set (not quite the correct follow set though. I believe it to be close to LALR(1))
std::vector<Symbol*>* followSet = gramFollowSet((*currStateTotal)[i]->getLeftSide());
for (std::vector<Symbol*>::size_type j = 0; j < followSet->size(); j++)
addToTable(state, (*followSet)[j], new ParseAction(ParseAction::REDUCE, (*currStateTotal)[i]));
} else {
std::cout << (*currStateTotal)[i]->toString() << " is NOT at end" << std::endl;
//std::cout << (*currStateTotal)[i]->toString() << " is NOT at end" << std::endl;
}
}
//Put all our new states in the set of states only if they're not already there.
bool stateAlreadyInAllStates = false;
Symbol* currStateSymbol;
for (std::vector< State * >::size_type i = 0; i < newStates.size(); i++) {
stateAlreadyInAllStates = false;
currStateSymbol = (*(newStates[i]->getBasis()))[0]->getAtIndex();
for (std::vector< State * >::size_type j = 0; j < stateSets->size(); j++) {
if (*(newStates[i]) == *((*stateSets)[j])) {
stateAlreadyInAllStates = true;
//If it does exist, we should add it as the shift/goto in the action table
addToTable(state, currStateSymbol, new ParseAction(ParseAction::SHIFT, j));
std::cout << "State exists, is " << j << std::endl;
break;
}
}
if (!stateAlreadyInAllStates) {
stateSets->push_back(newStates[i]);
stateAlreadyInAllStates = false;
//If the state does not already exist, add it and add it as the shift/goto in the action table
addToTable(state, currStateSymbol, new ParseAction(ParseAction::SHIFT, stateSets->size()-1));
std::cout << "State does not exist" << std::endl;
std::cout << "State is " << newStates[i]->toString() << std::endl;
}
}
}
@@ -302,12 +323,12 @@ void Parser::addToTable(State* fromState, Symbol* tranSymbol, ParseAction* actio
//std::cout << "blank is " << (*(table[stateNum]))[symbolIndex] << std::endl;
if ( (*(table[stateNum]))[symbolIndex] == NULL ) {
std::cout << "Null, adding " << action->toString() << std::endl;
//std::cout << "Null, adding " << action->toString() << std::endl;
(*(table[stateNum]))[symbolIndex] = action;
}
//If the slot is not empty and does not contain ourself, then it is a conflict
else if ( *((*(table[stateNum]))[symbolIndex]) != *action) {
std::cout << "not Null!" << std::endl;
//std::cout << "not Null!" << std::endl;
std::cout << "Conflict between old: " << (*(table[stateNum]))[symbolIndex]->toString() << " and new: " << action->toString() << std::endl;
//Don't overwrite
//(*(table[stateNum]))[symbolIndex] = action;

View File

@@ -22,7 +22,7 @@ const bool State::operator==(const State &other) {
if (remaining.size() != other.remaining.size())
return false;
for (std::vector< ParseRule* >::size_type i = 0; i < remaining.size(); i++) {
if (remaining[i] != other.remaining[i])
if ( *(remaining[i]) != *(other.remaining[i]) )
return false;
}
return true;