diff --git a/include/Parser.h b/include/Parser.h index 84785ea..ce3f6ff 100644 --- a/include/Parser.h +++ b/include/Parser.h @@ -10,9 +10,11 @@ #include "Symbol.h" #include "State.h" #include "StringReader.h" +#include "NodeTree.h" #include #include +#include #include #include #include @@ -29,7 +31,7 @@ class Parser { std::string stateSetToString(); int gotoTable(int state, Symbol* token); ParseAction* actionTable(int state, Symbol* token); - void parseInput(std::string inputString); + NodeTree* parseInput(std::string inputString); std::string grammerToString(); std::string grammerToDOT(); @@ -46,6 +48,7 @@ class Parser { std::stack symbolStack; Symbol* getOrAddSymbol(std::string symbolString, bool isTerminal); + NodeTree* reduceTreeCombine(Symbol* newSymbol, std::vector &symbols); }; #endif \ No newline at end of file diff --git a/include/Symbol.h b/include/Symbol.h index 9a5b49d..0971e71 100644 --- a/include/Symbol.h +++ b/include/Symbol.h @@ -5,18 +5,26 @@ #define NULL 0 #endif +#include "NodeTree.h" + #include #include class Symbol { public: Symbol(std::string name, bool isTerminal); + Symbol(std::string name, bool isTerminal, NodeTree* tree); ~Symbol(); bool const operator==(const Symbol &other); std::string toString(); + Symbol* clone(); + void setSubTree(NodeTree* tree); + NodeTree* getSubTree(); + bool isTerminal(); private: std::string name; - bool isTerminal; + bool terminal; + NodeTree* subTree; }; diff --git a/main.cpp b/main.cpp index 8c3120a..f49afab 100644 --- a/main.cpp +++ b/main.cpp @@ -52,21 +52,26 @@ int main(int argc, char* argv[]) { Parser parser; parser.loadGrammer(grammerInputFileString); - std::cout << "Creating State Set from Main" << std::endl; + //std::cout << "Creating State Set from Main" << std::endl; parser.createStateSet(); - std::cout << "finished State Set from Main" << std::endl; - std::cout << "Doing stateSetToString from Main" << std::endl; + //std::cout << "finished State Set from Main" << std::endl; + //std::cout << "Doing stateSetToString from Main" << std::endl; std::cout << parser.stateSetToString() << std::endl; - std::cout << "finished stateSetToString from Main" << std::endl; + //std::cout << "finished stateSetToString from Main" << std::endl; std::cout << grammerInputFileString << std::endl; std::cout << parser.grammerToString() << std::endl; - std::cout << parser.grammerToDOT() << std::endl; + //std::cout << parser.grammerToDOT() << std::endl; - outFile << parser.grammerToDOT() << std::endl; + //outFile << parser.grammerToDOT() << std::endl; std::cout << programInputFileString << std::endl; - parser.parseInput(programInputFileString); + NodeTree* parseTree = parser.parseInput(programInputFileString); + + if (parseTree) { + std::cout << parseTree->DOTGraphString() << std::endl; + outFile << parseTree->DOTGraphString() << std::endl; + } programInFile.close(); grammerInFile.close(); diff --git a/src/Parser.cpp b/src/Parser.cpp index ea55248..caa506b 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -54,15 +54,15 @@ void Parser::loadGrammer(std::string grammerInputString) { void Parser::createStateSet() { std::cout << "Begining creation of stateSet" << std::endl; stateSets.push_back( new State(0, loadedGrammer[0]) ); - std::cout << "Begining for main set for loop" << std::endl; + //std::cout << "Begining for main set for loop" << std::endl; for (std::vector< State* >::size_type i = 0; i < stateSets.size(); i++) { - std::cout << "calling closure on " << stateSets[i]->toString() << std::endl; + //std::cout << "calling closure on " << stateSets[i]->toString() << std::endl; closure(stateSets[i]); - std::cout << "finished closure" << std::endl; - std::cout << "Starting inner for loop that adds states" << std::endl; + //std::cout << "finished closure" << std::endl; + //std::cout << "Starting inner for loop that adds states" << std::endl; std::vector* allRules = stateSets[i]->getTotal(); for (std::vector::size_type j = 0; j < allRules->size(); j++) { - std::cout << "about to call addState" << std::endl; + //std::cout << "about to call addState" << std::endl; addState(&stateSets, stateSets[i], (*allRules)[j]->getAtNextIndex()); //Closure will be called in the outer loop } @@ -71,12 +71,12 @@ void Parser::createStateSet() { void Parser::closure(State* state) { //Add all the applicable rules. - std::cout << "Closure on " << state->toString() << " is" << std::endl; + //std::cout << "Closure on " << state->toString() << " is" << std::endl; for (std::vector::size_type i = 0; i < state->getTotal()->size(); i++) { for (std::vector::size_type j = 0; j < loadedGrammer.size(); j++) { //If the current symbol in the rule is not null (rule completed) and it equals a grammer's left side if ((*state->getTotal())[i]->getAtNextIndex() != NULL && *((*state->getTotal())[i]->getAtNextIndex()) == *(loadedGrammer[j]->getLeftSide())) { - std::cout << (*state->getTotal())[i]->getAtNextIndex()->toString() << " has an applicable production " << loadedGrammer[j]->toString() << std::endl; + //std::cout << (*state->getTotal())[i]->getAtNextIndex()->toString() << " has an applicable production " << loadedGrammer[j]->toString() << std::endl; //Check to make sure not already in bool isAlreadyInState = false; for (std::vector::size_type k = 0; k < state->getTotal()->size(); k++) { @@ -90,7 +90,7 @@ void Parser::closure(State* state) { } } } - std::cout << state->toString() << std::endl; + //std::cout << state->toString() << std::endl; } //Adds state if it doesn't already exist. @@ -188,7 +188,7 @@ ParseAction* Parser::actionTable(int state, Symbol* token) { } //If the current rule in the state is not completed, see if it has the next correct token - std::cout << currentRule->getAtNextIndex()->toString() << " comp to " << token->toString() << std::endl; + //std::cout << currentRule->getAtNextIndex()->toString() << " comp to " << token->toString() << std::endl; if ( *(currentRule->getAtNextIndex()) == *token){ //If it does have the correct next token, then find the state that has this rule advanced as basis, that is the state we shift to //Goes to n^2 here, really need that table @@ -207,10 +207,10 @@ ParseAction* Parser::actionTable(int state, Symbol* token) { return new ParseAction(ParseAction::REJECT); } -void Parser::parseInput(std::string inputString) { +NodeTree* Parser::parseInput(std::string inputString) { StringReader inputReader; inputReader.setString(inputString); - Symbol* token = new Symbol(inputReader.word(), true); + Symbol* token = new Symbol("\""+inputReader.word()+"\"", true); ParseAction* action; stateStack.push(0); @@ -222,33 +222,51 @@ void Parser::parseInput(std::string inputString) { case ParseAction::REDUCE: { int rightSideLength = action->reduceRule->getRightSide().size(); + //Keep track of symbols popped for parse tree + std::vector poppedSymbols; for (int i = 0; i < rightSideLength; i++) { + poppedSymbols.push_back(symbolStack.top()); stateStack.pop(); symbolStack.pop(); } - symbolStack.push(action->reduceRule->getLeftSide()); + std::reverse(poppedSymbols.begin(), poppedSymbols.end()); //To put in order + //Assign the new tree to the new Symbol + Symbol* newSymbol = action->reduceRule->getLeftSide()->clone(); + newSymbol->setSubTree(reduceTreeCombine(newSymbol, poppedSymbols)); + symbolStack.push(newSymbol); stateStack.push(gotoTable(stateStack.top(), symbolStack.top())); std::cout << "Reduce by " << action->reduceRule->toString() << std::endl; break; } case ParseAction::SHIFT: symbolStack.push(token); - token = new Symbol(inputReader.word(), true); + token = new Symbol("\""+inputReader.word()+"\"", true); stateStack.push(action->shiftState); std::cout << "Shift " << symbolStack.top()->toString() << std::endl; break; case ParseAction::ACCEPT: std::cout << "ACCEPTED!" << std::endl; - return; + return(symbolStack.top()->getSubTree()); break; case ParseAction::REJECT: std::cout << "REJECTED!" << std::endl; - return; + return(NULL); break; } } } +NodeTree* Parser::reduceTreeCombine(Symbol* newSymbol, std::vector &symbols) { + NodeTree* newTree = new NodeTree(newSymbol->toString()); + for (std::vector::size_type i = 0; i < symbols.size(); i++) { + if (symbols[i]->isTerminal()) + newTree->addChild(new NodeTree(symbols[i]->toString())); + else + newTree->addChild(symbols[i]->getSubTree()); + } + return(newTree); +} + std::string Parser::grammerToString() { //Iterate through the vector, adding string representation of each grammer rule std::cout << "About to toString\n"; @@ -261,7 +279,7 @@ std::string Parser::grammerToString() { std::string Parser::grammerToDOT() { //Iterate through the vector, adding DOT representation of each grammer rule - std::cout << "About to DOT export\n"; + //std::cout << "About to DOT export\n"; std::string concat = ""; for (int i = 0; i < loadedGrammer.size(); i++) { concat += loadedGrammer[i]->toDOT(); diff --git a/src/Symbol.cpp b/src/Symbol.cpp index 8230462..35350c0 100644 --- a/src/Symbol.cpp +++ b/src/Symbol.cpp @@ -2,7 +2,14 @@ Symbol::Symbol(std::string name, bool isTerminal) { this->name = name; - this->isTerminal = isTerminal; + this->terminal = isTerminal; + this->subTree = NULL; +} + +Symbol::Symbol(std::string name, bool isTerminal, NodeTree* tree) { + this->name = name; + this->terminal = isTerminal; + this->subTree = tree; } Symbol::~Symbol() { @@ -10,10 +17,26 @@ Symbol::~Symbol() { } const bool Symbol::operator==(const Symbol &other) { - return( name == other.name && isTerminal == other.isTerminal); + return( name == other.name && terminal == other.terminal); } std::string Symbol::toString() { - return(name + "(" + (isTerminal ? "T" : "NT") + ")"); + return(name); //+ "(" + (terminal ? "T" : "NT") + ")"); +} + +Symbol* Symbol::clone() { + return new Symbol(name, terminal, subTree); +} + +void Symbol::setSubTree(NodeTree* tree) { + subTree = tree; +} + +NodeTree* Symbol::getSubTree() { + return subTree; +} + +bool Symbol::isTerminal() { + return terminal; }