diff --git a/include/Parser.h b/include/Parser.h index f1ce373..370095c 100644 --- a/include/Parser.h +++ b/include/Parser.h @@ -25,6 +25,8 @@ class Parser { void loadGrammer(std::string grammerInputString); std::vector* firstSet(Symbol* token); void printFirstSets(); + std::vector* followSet(Symbol* token); + void printFollowSets(); void createStateSet(); void closure(State* state); void addStates(std::vector< State* >* stateSets, State* state); diff --git a/main.cpp b/main.cpp index 1a140b1..36117fb 100644 --- a/main.cpp +++ b/main.cpp @@ -70,6 +70,7 @@ int main(int argc, char* argv[]) { std::cout << programInputFileString << std::endl; NodeTree* parseTree = parser.parseInput(new Lexer(programInputFileString)); parser.printFirstSets(); + parser.printFollowSets(); if (parseTree) { std::cout << parseTree->DOTGraphString() << std::endl; diff --git a/src/Parser.cpp b/src/Parser.cpp index 65c9833..d2d8c9f 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -89,6 +89,56 @@ void Parser::printFirstSets() { } } +std::vector* Parser::followSet(Symbol* token) { + 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); + } + //Otherwise.... + //Ok, to make a follow set, go through the grammer 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; + std::vector* recursiveFollowSet = NULL; + std::vector rightSide; + for (std::vector::size_type i = 0; i < loadedGrammer.size(); i++) { + rightSide = loadedGrammer[i]->getRightSide(); + for (std::vector::size_type j = 0; j < rightSide.size(); j++) { + if (*token == *(rightSide[j])) { + //If this is the first grammer rule, that is the goal rule, add $EOF$ and move on + if (i == 0) { + follow->push_back(new Symbol("$EOF$", false)); + break; + } + if (j < rightSide.size()-1) { + if (rightSide[j+1]->isTerminal()) + follow->push_back(rightSide[j+1]); + else { + recursiveFollowSet = firstSet(rightSide[j+1]); + follow->insert(follow->begin(), recursiveFollowSet->begin(), recursiveFollowSet->end()); + } + } else { + recursiveFollowSet = followSet(loadedGrammer[i]->getLeftSide()); + follow->insert(follow->begin(), recursiveFollowSet->begin(), recursiveFollowSet->end()); + } + } + } + } + return(follow); +} + +void Parser::printFollowSets() { + std::vector* follow = NULL; + for (std::vector::size_type i = 0; i < symbolIndexVec.size(); i++) { + follow = followSet(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() << " "; + std::cout << std::endl; + } +} + void Parser::createStateSet() { std::cout << "Begining creation of stateSet" << std::endl; stateSets.push_back( new State(0, loadedGrammer[0]) );