From 31d7c02ef91cc2a6cbceb9e2a8c542cefab007ec Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Thu, 8 Aug 2013 02:44:17 -0400 Subject: [PATCH] Finished writing first code for turning the RNGLR recognizer into a parser. Doesn't compile yet, needs lots of bugfixing, but I'm calling it a night. --- include/GraphStructuredStack.h | 9 +- include/RNGLRParser.h | 21 +++- src/GraphStructuredStack.cpp | 40 +++++++- src/RNGLRParser.cpp | 172 ++++++++++++++++++++++++++------- 4 files changed, 200 insertions(+), 42 deletions(-) diff --git a/include/GraphStructuredStack.h b/include/GraphStructuredStack.h index f24cdfd..e5bac15 100644 --- a/include/GraphStructuredStack.h +++ b/include/GraphStructuredStack.h @@ -14,15 +14,20 @@ class GraphStructuredStack { NodeTree* newNode(int stateNum); void addToFrontier(int frontier, NodeTree* node); NodeTree* inFrontier(int frontier, int state); + int getContainingFrontier(NodeTree* node); bool frontierIsEmpty(int frontier); - bool frontierHasAccState(int frontier); + NodeTree* frontierGetAccState(int frontier); std::vector*>* getReachable(NodeTree* start, int lenght); + std::vector*> >* getReachablePaths(NodeTree* start, int lenght); + void recursivePathFind(NodeTree* start, int length, std::vector*> currentPath, std::vector*> >* paths); bool hasEdge(NodeTree* start, NodeTree* end); - void addEdge(NodeTree* start, NodeTree* end); + NodeTree* getEdge(NodeTree* start, NodeTree* end); + void addEdge(NodeTree* start, NodeTree* end, NodeTree* edge); std::string toString(); private: std::vector*>*> gss; + std::map*, NodeTree*>, NodeTree edges; }; #endif diff --git a/include/RNGLRParser.h b/include/RNGLRParser.h index dc21036..2bf0b1e 100644 --- a/include/RNGLRParser.h +++ b/include/RNGLRParser.h @@ -3,6 +3,8 @@ #include #include +#include +#include #include "Parser.h" #include "GraphStructuredStack.h" @@ -24,14 +26,29 @@ class RNGLRParser: public Parser { bool belongsToFamily(NodeTree* node, std::vector*>* nodes); bool arePacked(std::vector*>* nodes); bool isPacked(NodeTree* node); - void setPacked(NodeTree* node, bool isPacked) + void setPacked(NodeTree* node, bool isPacked); + + int getNullableIndex(ParseRule* rule); + NodeTree getNullableParts(ParseRule* rule); + NodeTree getNullableParts(Symbol* symbol); + NodeTree getNullableParts(int index); + + std::vector*> getPathEdges(std::vector*> path); std::vector input; GraphStructuredStack gss; //start node, lefthand side of the reduction, reduction length - std::queue*, Symbol*>, int > > toReduce; + struct Reduction { + NodeTree* from; + Symbol* symbol; + int length; + int nullablePartsIndex; + NodeTree* label; + } ; + std::queue toReduce; //Node coming from, state going to std::queue< std::pair*, int> > toShift; + std::vector*, int> > SPPFStepNodes; std::vector*> nullableParts; std::map*, bool> packedMap; diff --git a/src/GraphStructuredStack.cpp b/src/GraphStructuredStack.cpp index 66ecf9b..4cbd42d 100644 --- a/src/GraphStructuredStack.cpp +++ b/src/GraphStructuredStack.cpp @@ -32,11 +32,23 @@ NodeTree* GraphStructuredStack::inFrontier(int frontier, int state) { return NULL; } +int GraphStructuredStack::getContainingFrontier(NodeTree* node) { + for (std::vector*>*>::size_type i = 0; i < gss.size(); i++) { + if (frontierIsEmpty(frontier)) + continue; + for (std::vector*>::size_type j = 0; j < gss[i]->size(); j++) { + if (*((*(gss[i]))[j]) == *node) + return i; + } + } + return -1; +} + bool GraphStructuredStack::frontierIsEmpty(int frontier) { return frontier >= gss.size() || gss[frontier]->size() == 0; } -bool GraphStructuredStack::frontierHasAccState(int frontier) { +NodeTree* GraphStructuredStack::frontierGetAccState(int frontier) { //The acc state is always state 1, for now return inFrontier(frontier, 1); } @@ -71,14 +83,38 @@ std::vector*>* GraphStructuredStack::getReachable(NodeTree* s return reachableList; } +std::vector*> >* GraphStructuredStack::getReachablePaths(NodeTree* start, int length) { + std::vector*> >* paths = new std::vector*> >(); + std::vector*> currentPath; + recursivePathFind(start, length, currentPath, paths); + return paths; +} + +void GraphStructuredStack::recursivePathFind(NodeTree* start, int length, std::vector*> currentPath, std::vector*> >* paths) { + currentPath.push_back(start); + if (length == 0) { + paths->push_back(currentPath); + return; + } + std::vector*>* children = start->getChildren(); + for (std::vector*>::size_type i = 0; i < children->size(); i++) { + recursivePathFind((*children)[i], length-1, currentPath, paths); + } +} + bool GraphStructuredStack::hasEdge(NodeTree* start, NodeTree* end) { //Really, either testing for parent or child should work. return start->findChild(end) != -1; } -void GraphStructuredStack::addEdge(NodeTree* start, NodeTree* end) { +NodeTree* GraphStructuredStack::getEdge(NodeTree* start, NodeTree* end) { + return edges.get(std::make_pair(start, end), NULL); +} + +void GraphStructuredStack::addEdge(NodeTree* start, NodeTree* end, NodeTree edge) { start->addChild(end); end->addParent(start); + edges[std::make_pair(start, end)] = edge; } std::string GraphStructuredStack::toString() { diff --git a/src/RNGLRParser.cpp b/src/RNGLRParser.cpp index 37ef9e6..cf71d15 100644 --- a/src/RNGLRParser.cpp +++ b/src/RNGLRParser.cpp @@ -18,10 +18,12 @@ NodeTree* RNGLRParser::parseInput(std::string inputString) { if ((*zeroStateActions)[i]->action == ParseAction::REDUCE) accepting = true; } - if (accepting) + if (accepting) { std::cout << "Accepted!" << std::endl; - else + return getNullableParts(stateSets[0]->getBasis()->operator[0]->getLeftSide()); + } else { std::cout << "Rejected, no input (with no accepting state)" << std::endl; + } return new NodeTree(); } @@ -62,7 +64,9 @@ NodeTree* RNGLRParser::parseInput(std::string inputString) { if (firstActions[i]->action == ParseAction::SHIFT) toShift.push(std::make_pair(v0,firstActions[i]->shiftState)); else if (firstActions[i]->action == ParseAction::REDUCE && firstActions[i]->reduceRule->getRightSide().size() == 0) { - toReduce.push(std::make_pair(std::make_pair(v0, firstActions[i]->reduceRule->getLeftSide()), 0)); + Reduction newReduction = {v0, firstActions[i]->reduceRule->getLeftSide(), 0, getNullableIndex(firstActions[i]->reduceRule), new NodeTree("null", nullSymbol)} + toReduce.push(newReduction); + //toReduce.push(std::make_pair(std::make_pair(v0, firstActions[i]->reduceRule->getLeftSide()), 0)); } } @@ -77,6 +81,12 @@ NodeTree* RNGLRParser::parseInput(std::string inputString) { std::cout << "Failed on " << input[i]->toString() << " next: " << input[i+1]->toString() << std::endl; break; } + + //Clear the vector of SPPF nodes created every step + for (std::vector*>::size_type j = 0; j < SPPFStepNodes.size(); j++) + SPPFStepNodes[j] = NULL; + SPPFStepNodes.clear(); + while (toReduce.size() != 0) { std::cout << "Reducing for " << i << std::endl; //std::cout << "GSS:\n" << gss.toString() << std::endl; @@ -87,61 +97,108 @@ NodeTree* RNGLRParser::parseInput(std::string inputString) { std::cout << "GSS:\n" << gss.toString() << std::endl; } std::cout << "Done with parsing loop, checking for acceptance" << std::endl; - if (gss.frontierHasAccState(input.size()-1)) + NodeTree* accState = gss.frontierHasAccState(input.size()-1); + if (accState) { std::cout << "Accepted!" << std::endl; - else + return gss.getEdge(accState, v0); + } else { std::cout << "Rejected!" << std::endl; + } std::cout << "GSS:\n" << gss.toString() << std::endl; - return new NodeTree(); + return NULL; } void RNGLRParser::reducer(int i) { - std::pair< std::pair*, Symbol*>, int > reduction = toReduce.front(); + Reduction reduction = toReduce.front(); toReduce.pop(); - std::cout << "Doing reduction of length " << reduction.second << " from state " << reduction.first.first->getData() << " to symbol " << reduction.first.second->toString() << std::endl; - int pathLength = reduction.second > 0 ? reduction.second -1 : 0; - std::vector*>* reachable = gss.getReachable(reduction.first.first, pathLength); - for (std::vector*>::size_type j = 0; j < reachable->size(); j++) { - NodeTree* currentReached = (*reachable)[j]; - std::cout << "Getting the shfit state for state " << currentReached->getData() << " and symbol " << reduction.first.second->toString() << std::endl; - int toState = table.getShift(currentReached->getData(), reduction.first.second)->shiftState; + std::cout << "Doing reduction of length " << reduction.length << " from state " << reduction.from->getData() << " to symbol " << reduction.first.second->toString() << std::endl; + int pathLength = reduction.length > 0 ? reduction.length -1 : 0; + //Get every reachable path + std::vector*> >* paths = gss.getReachablePaths(reduction.from, pathLength); + + for (std::vector*> >::size_type j = 0; j < paths->size(); j++) { + + //Algorithm expects path in reverse order + std::vector*> currentPath = (*paths)[j]; + std::reverse(currentPath.begin(), currentPath.end()); + //Add label of first edge to the end, (since reversed, this is the correct place) + + //Get the edges for the current path + std::vector*> pathEdges = getPathEdges(currentPath); + //If the reduction length is 0, label as passed in is null + if (reduction.length != 0) + pathEdges.push_back(reduction.label); + //The end of the current path (remember reversed) + NodeTree* currentReached = currentPath[0]; + + std::cout << "Getting the shfit state for state " << currentReached->getData() << " and symbol " << reduction.symbol->toString() << std::endl; + int toState = table.getShift(currentReached->getData(), reduction.symbol)->shiftState; + + //If reduction length is 0, then we make the new label the appropriate nullable parts + NodeTree* newLabel = NULL; + if (reduction.length == 0) { + newLabel = getNullableParts(reduction.nullablePartsIndex); + } else { + //Otherwise, we create the new label if we haven't already + int reachedFrontier = gss.getContainingFrontier(currentReached); + for (std::vector*, int> >::size_type k = 0; k < SPPFStepNodes.size(); k++) { + if ( SPPFStepNodes[k].second == reachedFrontier && *(SPPFStepNodes[k].first->data) == *(reduction.symbol)) { + newLabel = SPPFStepNodes[k].first; + break; + } + } + if (!newLabel) { + newLabel = new NodeTree("frontier: " + intToString(reachedFrontier), reduction.symbol); + SPPFStepNodes.push_back(std::make_pair(newLabel, reachedFrontier)); + } + } + NodeTree* toStateNode = gss.inFrontier(i, toState); if (toStateNode) { if (!gss.hasEdge(toStateNode, currentReached)) { - gss.addEdge(toStateNode, currentReached); - if (reduction.second != 0) { + gss.addEdge(toStateNode, currentReached, newLabel); + if (reduction.length != 0) { //Do all non null reduction std::cout << "Checking for non-null reductions in states that already existed" << std::endl; std::vector actions = *(table.get(toState, input[i])); - for (std::vector::size_type k = 0; k < actions.size(); k++) - if (actions[k]->action == ParseAction::REDUCE && actions[k]->reduceRule->getRightSize() != 0) - toReduce.push(std::make_pair(std::make_pair(currentReached, actions[k]->reduceRule->getLeftSide()), actions[k]->reduceRule->getRightSize())); + for (std::vector::size_type k = 0; k < actions.size(); k++) { + if (actions[k]->action == ParseAction::REDUCE && actions[k]->reduceRule->getRightSize() != 0) { + Reduction newReduction = {currentReached, actions[k]->reduceRule->getLeftSide(), actions[k]->reduceRule->getRightSize(), getNullableIndex(actions[k]->reduceRule), newLabel} + toReduce.push(newReduction); + } + } } } } else { toStateNode = gss.newNode(toState); gss.addToFrontier(i, toStateNode); - gss.addEdge(toStateNode, currentReached); + gss.addEdge(toStateNode, currentReached, newLabel); std::cout << "Adding shifts and reductions for a state that did not exist" << std::endl; std::vector actions = *(table.get(toState, input[i])); for (std::vector::size_type k = 0; k < actions.size(); k++) { std::cout << "Action is " << actions[k]->toString() << std::endl; - if (actions[k]->action == ParseAction::SHIFT) + if (actions[k]->action == ParseAction::SHIFT) { toShift.push(std::make_pair(toStateNode, actions[k]->shiftState)); - else if (actions[k]->action == ParseAction::REDUCE && actions[k]->reduceRule->getRightSize() != 0) - toReduce.push(std::make_pair(std::make_pair(currentReached, actions[k]->reduceRule->getLeftSide()), actions[k]->reduceRule->getRightSize())); - else if (actions[k]->action == ParseAction::REDUCE && actions[k]->reduceRule->getRightSize() == 0) - toReduce.push(std::make_pair(std::make_pair(toStateNode, actions[k]->reduceRule->getLeftSide()), actions[k]->reduceRule->getRightSize())); + } else if (actions[k]->action == ParseAction::REDUCE && actions[k]->reduceRule->getRightSize() == 0) { + Reduction newReduction = {toStateNode, actions[k]->reduceRule->getLeftSide(), 0, getNullableIndex(actions[k]->reduceRule), new NodeTree("null", nullSymbol)} + toReduce.push(newReduction); + } else if (reduction.length != 0 && actions[k]->action == ParseAction::REDUCE && actions[k]->reduceRule->getRightSize() != 0) { + Reduction newReduction = {currentReached, actions[k]->reduceRule->getLeftSide(), actions[k]->reduceRule->getRightSize(), getNullableIndex(actions[k]->reduceRule), newLabel} + toReduce.push(newReduction); + } } } + if (reduction.length != 0) + addChildren(newLabel, &pathEdges, reduction.nullablePartsIndex); } } void RNGLRParser::shifter(int i) { if (i != input.size()-1) { std::queue< std::pair*, int> > nextShifts; + NodeTree nextLabel = new NodeTree("frontier: " + intToString(i), input[i]); while (!toShift.empty()) { std::pair*, int> shift = toShift.front(); toShift.pop(); @@ -149,27 +206,32 @@ void RNGLRParser::shifter(int i) { NodeTree* shiftTo = gss.inFrontier(i+1, shift.second); if (shiftTo) { std::cout << "State already existed, just adding edge" << std::endl; - gss.addEdge(shiftTo, shift.first); + gss.addEdge(shiftTo, shift.first, nextLabel); std::vector actions = *(table.get(shift.second, input[i+1])); for (std::vector::size_type j = 0; j < actions.size(); j++) { - if (actions[j]->action == ParseAction::REDUCE && actions[j]->reduceRule->getRightSize() != 0) - toReduce.push(std::make_pair(std::make_pair(shift.first, actions[j]->reduceRule->getLeftSide()), actions[j]->reduceRule->getRightSize())); + if (actions[j]->action == ParseAction::REDUCE && actions[j]->reduceRule->getRightSize() != 0) { + Reduction newReduction = {shift.first, actions[j]->reduceRule->getLeftSide(), actions[j]->reduceRule->getRightSize(), getNullableIndex(actions[j]->reduceRule), newLabel} + toReduce.push(newReduction); + } } } else { std::cout << "State did not already exist, adding" << std::endl; shiftTo = gss.newNode(shift.second); gss.addToFrontier(i+1, shiftTo); - gss.addEdge(shiftTo, shift.first); + gss.addEdge(shiftTo, shift.first, newLabel); std::vector actions = *(table.get(shift.second, input[i+1])); for (std::vector::size_type j = 0; j < actions.size(); j++) { std::cout << "Adding action " << actions[j]->toString() << " to either nextShifts or toReduce" << std::endl; //Shift - if (actions[j]->action == ParseAction::SHIFT) + if (actions[j]->action == ParseAction::SHIFT) { nextShifts.push(std::make_pair(shiftTo, actions[j]->shiftState)); - else if (actions[j]->action == ParseAction::REDUCE && actions[j]->reduceRule->getRightSize() != 0) - toReduce.push(std::make_pair(std::make_pair(shift.first, actions[j]->reduceRule->getLeftSide()), actions[j]->reduceRule->getRightSize())); - else if (actions[j]->action == ParseAction::REDUCE && actions[j]->reduceRule->getRightSize() == 0) - toReduce.push(std::make_pair(std::make_pair(shiftTo, actions[j]->reduceRule->getLeftSide()), actions[j]->reduceRule->getRightSize())); + } else if (actions[j]->action == ParseAction::REDUCE && actions[j]->reduceRule->getRightSize() != 0) { + Reduction newReduction = {shift.first, actions[j]->reduceRule->getLeftSide(), actions[j]->reduceRule->getRightSize(), getNullableIndex(actions[j]->reduceRule), newLabel} + toReduce.push(newReduction); + } else if (actions[j]->action == ParseAction::REDUCE && actions[j]->reduceRule->getRightSize() == 0) { + Reduction newReduction = {shiftTo, actions[j]->reduceRule->getLeftSide(), 0, getNullableIndex(actions[j]->reduceRule), new NodeTree("null", nullSymbol)} + toReduce.push(newReduction); + } } } } @@ -179,7 +241,7 @@ void RNGLRParser::shifter(int i) { void RNGLRParser::addChildren(NodeTree* parent, std::vector*>* children, int nullablePartsIndex) { if (nullablePartsIndex != 0) - children->push_back(nullableParts[nullablePartsIndex]); + children->push_back(getNullableParts(nullablePartsIndex); if (!belongsToFamily(parent, children)) { if (parent->getChildren().size() == 0) { parent->addChildren(children); @@ -200,7 +262,20 @@ void RNGLRParser::addChildren(NodeTree* parent, std::vector* node, std::vector*>* nodes) { - // + std::vector*> children = node->getChildren(); + for (std::vector*>::size_type i = 0; i < nodes->size(); i++) { + bool containsOne = false; + for (std::vector*>::size_type j = 0; j < children.size(); j++) { + if ((*(*nodes)[i]) == *(children[j])) { + containsOne = true; + break; + } + } + if (!containsOne) { + return false; + } + } + return true; } bool RNGLRParser::arePacked(std::vector*>* nodes) { @@ -329,3 +404,28 @@ bool RNGLRParser::reducesToNull(ParseRule* rule, std::vector avoidList) return reduces; } +int RNGLRParser::getNullableIndex(ParseRule* rule) { + return 1; +} + +NodeTree RNGLRParser::getNullableParts(ParseRule* rule) { + return new NodeTree("null", nullSymbol); +} + +NodeTree RNGLRParser::getNullableParts(Symbol* symbol) { + return new NodeTree("null", nullSymbol); +} + +NodeTree RNGLRParser::getNullableParts(int index) { + if (index == 0) + return new NodeTree("not_null", nullSymbol); + return new NodeTree("null", nullSymbol); +} + +std::vector*> RNGLRParser::getPathEdges(std::vector*> path) { + std::vector*> pathEdges; + for (std::vector*>::size_type i < path.size()-1; i++) + pathEdges.push_back(gss.getEdge(path[i], path[i+1])); + return pathEdges; +} +