diff --git a/include/Parser.h b/include/Parser.h index 370095c..d76eb4a 100644 --- a/include/Parser.h +++ b/include/Parser.h @@ -25,7 +25,9 @@ class Parser { void loadGrammer(std::string grammerInputString); std::vector* firstSet(Symbol* token); void printFirstSets(); - std::vector* followSet(Symbol* token); + //std::vector* followSet(int stateNum, Symbol* token); + std::vector* gramFollowSet(Symbol* token); + std::vector* gramFollowSetAvoid(Symbol* token, std::vector* avoidList); void printFollowSets(); void createStateSet(); void closure(State* state); diff --git a/src/Parser.cpp b/src/Parser.cpp index d2d8c9f..22c0275 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -89,14 +89,31 @@ void Parser::printFirstSets() { } } -std::vector* 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* Parser::gramFollowSet(Symbol* token) { + std::vector* avoidList = new std::vector(); + return gramFollowSetAvoid(token, avoidList); +} +std::vector* Parser::gramFollowSetAvoid(Symbol* token, std::vector* avoidList) { std::vector* follow = new std::vector(); //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::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* 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* Parser::followSet(Symbol* token) { void Parser::printFollowSets() { std::vector* follow = NULL; for (std::vector::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::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::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* followSet = gramFollowSet((*currStateTotal)[i]->getLeftSide()); + for (std::vector::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; diff --git a/src/State.cpp b/src/State.cpp index b9e82f5..640a68a 100644 --- a/src/State.cpp +++ b/src/State.cpp @@ -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;