Cleaned up some debug messages, parseInput(string) now returns a parse tree of NodeTree*. This is done by having each non-terminal Symbol have it's own subtree and calling a method to combine subtrees and terminals on each reduce. The output is now the DOT version of the parse tree.

This commit is contained in:
Nathan Braswell
2013-05-30 19:49:19 -04:00
parent dd7b255520
commit 0c4af245bf
5 changed files with 85 additions and 28 deletions

View File

@@ -10,9 +10,11 @@
#include "Symbol.h" #include "Symbol.h"
#include "State.h" #include "State.h"
#include "StringReader.h" #include "StringReader.h"
#include "NodeTree.h"
#include <map> #include <map>
#include <vector> #include <vector>
#include <algorithm>
#include <stack> #include <stack>
#include <string> #include <string>
#include <iostream> #include <iostream>
@@ -29,7 +31,7 @@ class Parser {
std::string stateSetToString(); std::string stateSetToString();
int gotoTable(int state, Symbol* token); int gotoTable(int state, Symbol* token);
ParseAction* actionTable(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 grammerToString();
std::string grammerToDOT(); std::string grammerToDOT();
@@ -46,6 +48,7 @@ class Parser {
std::stack<Symbol*> symbolStack; std::stack<Symbol*> symbolStack;
Symbol* getOrAddSymbol(std::string symbolString, bool isTerminal); Symbol* getOrAddSymbol(std::string symbolString, bool isTerminal);
NodeTree* reduceTreeCombine(Symbol* newSymbol, std::vector<Symbol*> &symbols);
}; };
#endif #endif

View File

@@ -5,18 +5,26 @@
#define NULL 0 #define NULL 0
#endif #endif
#include "NodeTree.h"
#include <vector> #include <vector>
#include <string> #include <string>
class Symbol { class Symbol {
public: public:
Symbol(std::string name, bool isTerminal); Symbol(std::string name, bool isTerminal);
Symbol(std::string name, bool isTerminal, NodeTree* tree);
~Symbol(); ~Symbol();
bool const operator==(const Symbol &other); bool const operator==(const Symbol &other);
std::string toString(); std::string toString();
Symbol* clone();
void setSubTree(NodeTree* tree);
NodeTree* getSubTree();
bool isTerminal();
private: private:
std::string name; std::string name;
bool isTerminal; bool terminal;
NodeTree* subTree;
}; };

View File

@@ -52,21 +52,26 @@ int main(int argc, char* argv[]) {
Parser parser; Parser parser;
parser.loadGrammer(grammerInputFileString); parser.loadGrammer(grammerInputFileString);
std::cout << "Creating State Set from Main" << std::endl; //std::cout << "Creating State Set from Main" << std::endl;
parser.createStateSet(); parser.createStateSet();
std::cout << "finished State Set from Main" << std::endl; //std::cout << "finished State Set from Main" << std::endl;
std::cout << "Doing stateSetToString from Main" << std::endl; //std::cout << "Doing stateSetToString from Main" << std::endl;
std::cout << parser.stateSetToString() << 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 << grammerInputFileString << std::endl;
std::cout << parser.grammerToString() << 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; 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(); programInFile.close();
grammerInFile.close(); grammerInFile.close();

View File

@@ -54,15 +54,15 @@ void Parser::loadGrammer(std::string grammerInputString) {
void Parser::createStateSet() { void Parser::createStateSet() {
std::cout << "Begining creation of stateSet" << std::endl; std::cout << "Begining creation of stateSet" << std::endl;
stateSets.push_back( new State(0, loadedGrammer[0]) ); 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++) { 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]); closure(stateSets[i]);
std::cout << "finished closure" << std::endl; //std::cout << "finished closure" << std::endl;
std::cout << "Starting inner for loop that adds states" << std::endl; //std::cout << "Starting inner for loop that adds states" << std::endl;
std::vector<ParseRule*>* allRules = stateSets[i]->getTotal(); std::vector<ParseRule*>* allRules = stateSets[i]->getTotal();
for (std::vector<ParseRule*>::size_type j = 0; j < allRules->size(); j++) { for (std::vector<ParseRule*>::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()); addState(&stateSets, stateSets[i], (*allRules)[j]->getAtNextIndex());
//Closure will be called in the outer loop //Closure will be called in the outer loop
} }
@@ -71,12 +71,12 @@ void Parser::createStateSet() {
void Parser::closure(State* state) { void Parser::closure(State* state) {
//Add all the applicable rules. //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<ParseRule*>::size_type i = 0; i < state->getTotal()->size(); i++) { for (std::vector<ParseRule*>::size_type i = 0; i < state->getTotal()->size(); i++) {
for (std::vector<ParseRule*>::size_type j = 0; j < loadedGrammer.size(); j++) { for (std::vector<ParseRule*>::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 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())) { 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 //Check to make sure not already in
bool isAlreadyInState = false; bool isAlreadyInState = false;
for (std::vector<ParseRule*>::size_type k = 0; k < state->getTotal()->size(); k++) { for (std::vector<ParseRule*>::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. //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 //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 ( *(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 //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 //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); return new ParseAction(ParseAction::REJECT);
} }
void Parser::parseInput(std::string inputString) { NodeTree* Parser::parseInput(std::string inputString) {
StringReader inputReader; StringReader inputReader;
inputReader.setString(inputString); inputReader.setString(inputString);
Symbol* token = new Symbol(inputReader.word(), true); Symbol* token = new Symbol("\""+inputReader.word()+"\"", true);
ParseAction* action; ParseAction* action;
stateStack.push(0); stateStack.push(0);
@@ -222,33 +222,51 @@ void Parser::parseInput(std::string inputString) {
case ParseAction::REDUCE: case ParseAction::REDUCE:
{ {
int rightSideLength = action->reduceRule->getRightSide().size(); int rightSideLength = action->reduceRule->getRightSide().size();
//Keep track of symbols popped for parse tree
std::vector<Symbol*> poppedSymbols;
for (int i = 0; i < rightSideLength; i++) { for (int i = 0; i < rightSideLength; i++) {
poppedSymbols.push_back(symbolStack.top());
stateStack.pop(); stateStack.pop();
symbolStack.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())); stateStack.push(gotoTable(stateStack.top(), symbolStack.top()));
std::cout << "Reduce by " << action->reduceRule->toString() << std::endl; std::cout << "Reduce by " << action->reduceRule->toString() << std::endl;
break; break;
} }
case ParseAction::SHIFT: case ParseAction::SHIFT:
symbolStack.push(token); symbolStack.push(token);
token = new Symbol(inputReader.word(), true); token = new Symbol("\""+inputReader.word()+"\"", true);
stateStack.push(action->shiftState); stateStack.push(action->shiftState);
std::cout << "Shift " << symbolStack.top()->toString() << std::endl; std::cout << "Shift " << symbolStack.top()->toString() << std::endl;
break; break;
case ParseAction::ACCEPT: case ParseAction::ACCEPT:
std::cout << "ACCEPTED!" << std::endl; std::cout << "ACCEPTED!" << std::endl;
return; return(symbolStack.top()->getSubTree());
break; break;
case ParseAction::REJECT: case ParseAction::REJECT:
std::cout << "REJECTED!" << std::endl; std::cout << "REJECTED!" << std::endl;
return; return(NULL);
break; break;
} }
} }
} }
NodeTree* Parser::reduceTreeCombine(Symbol* newSymbol, std::vector<Symbol*> &symbols) {
NodeTree* newTree = new NodeTree(newSymbol->toString());
for (std::vector<Symbol*>::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() { std::string Parser::grammerToString() {
//Iterate through the vector, adding string representation of each grammer rule //Iterate through the vector, adding string representation of each grammer rule
std::cout << "About to toString\n"; std::cout << "About to toString\n";
@@ -261,7 +279,7 @@ std::string Parser::grammerToString() {
std::string Parser::grammerToDOT() { std::string Parser::grammerToDOT() {
//Iterate through the vector, adding DOT representation of each grammer rule //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 = ""; std::string concat = "";
for (int i = 0; i < loadedGrammer.size(); i++) { for (int i = 0; i < loadedGrammer.size(); i++) {
concat += loadedGrammer[i]->toDOT(); concat += loadedGrammer[i]->toDOT();

View File

@@ -2,7 +2,14 @@
Symbol::Symbol(std::string name, bool isTerminal) { Symbol::Symbol(std::string name, bool isTerminal) {
this->name = name; 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() { Symbol::~Symbol() {
@@ -10,10 +17,26 @@ Symbol::~Symbol() {
} }
const bool Symbol::operator==(const Symbol &other) { 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() { 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;
} }