Have a nullableParts generator now. It works for simple cases and may work for advanced cases, but more testing is required to ensure full usability.
This commit is contained in:
@@ -45,7 +45,7 @@ class NodeTree {
|
|||||||
std::string DOTGraphString();
|
std::string DOTGraphString();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string DOTGraphStringHelper();
|
std::string DOTGraphStringHelper(std::vector<NodeTree<T>*> avoidList);
|
||||||
std::string getDOTName();
|
std::string getDOTName();
|
||||||
std::string name;
|
std::string name;
|
||||||
T data;
|
T data;
|
||||||
@@ -124,6 +124,8 @@ std::vector<NodeTree<T>*> NodeTree<T>::getParents() {
|
|||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void NodeTree<T>::addChild(NodeTree<T>* child) {
|
void NodeTree<T>::addChild(NodeTree<T>* child) {
|
||||||
|
if (!child)
|
||||||
|
throw "Help, NULL child";
|
||||||
if (findChild(child) == -1)
|
if (findChild(child) == -1)
|
||||||
children.push_back(child);
|
children.push_back(child);
|
||||||
}
|
}
|
||||||
@@ -206,15 +208,20 @@ void NodeTree<T>::setData(T data) {
|
|||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
std::string NodeTree<T>::DOTGraphString() {
|
std::string NodeTree<T>::DOTGraphString() {
|
||||||
return( "digraph Kraken { \n" + DOTGraphStringHelper() + "}");
|
return( "digraph Kraken { \n" + DOTGraphStringHelper(std::vector<NodeTree<T>*>()) + "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
std::string NodeTree<T>::DOTGraphStringHelper() {
|
std::string NodeTree<T>::DOTGraphStringHelper(std::vector<NodeTree<T>*> avoidList) {
|
||||||
|
for (typename std::vector<NodeTree<T>*>::size_type i = 0; i < avoidList.size(); i++)
|
||||||
|
if (this == avoidList[i])
|
||||||
|
return "";
|
||||||
|
avoidList.push_back(this);
|
||||||
|
|
||||||
std::string ourDOTRelation = "";
|
std::string ourDOTRelation = "";
|
||||||
for (int i = 0; i < children.size(); i++) {
|
for (int i = 0; i < children.size(); i++) {
|
||||||
if (children[i] != NULL)
|
if (children[i] != NULL)
|
||||||
ourDOTRelation += getDOTName() + " -> " + children[i]->getDOTName() + ";\n" + children[i]->DOTGraphStringHelper();
|
ourDOTRelation += getDOTName() + " -> " + children[i]->getDOTName() + ";\n" + children[i]->DOTGraphStringHelper(avoidList);
|
||||||
else
|
else
|
||||||
ourDOTRelation += getDOTName() + " -> BAD_NULL_" + getDOTName() + "\n";
|
ourDOTRelation += getDOTName() + " -> BAD_NULL_" + getDOTName() + "\n";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class RNGLRParser: public Parser {
|
|||||||
void addChildren(NodeTree<Symbol*>* parent, std::vector<NodeTree<Symbol*>*>* children, NodeTree<Symbol*>* nullableParts);
|
void addChildren(NodeTree<Symbol*>* parent, std::vector<NodeTree<Symbol*>*>* children, NodeTree<Symbol*>* nullableParts);
|
||||||
|
|
||||||
void addStates(std::vector< State* >* stateSets, State* state);
|
void addStates(std::vector< State* >* stateSets, State* state);
|
||||||
|
bool fullyReducesToNull(ParseRule* rule);
|
||||||
bool reducesToNull(ParseRule* rule);
|
bool reducesToNull(ParseRule* rule);
|
||||||
bool reducesToNull(ParseRule* rule, std::vector<Symbol*> avoidList);
|
bool reducesToNull(ParseRule* rule, std::vector<Symbol*> avoidList);
|
||||||
|
|
||||||
@@ -32,6 +33,7 @@ class RNGLRParser: public Parser {
|
|||||||
void setPacked(NodeTree<Symbol*>* node, bool isPacked);
|
void setPacked(NodeTree<Symbol*>* node, bool isPacked);
|
||||||
|
|
||||||
NodeTree<Symbol*>* getNullableParts(ParseRule* rule);
|
NodeTree<Symbol*>* getNullableParts(ParseRule* rule);
|
||||||
|
NodeTree<Symbol*>* getNullableParts(ParseRule* rule, std::vector<NodeTree<Symbol*>*> avoidList);
|
||||||
NodeTree<Symbol*>* getNullableParts(Symbol* symbol);
|
NodeTree<Symbol*>* getNullableParts(Symbol* symbol);
|
||||||
|
|
||||||
std::vector<NodeTree<Symbol*>*> getPathEdges(std::vector<NodeTree<int>*> path);
|
std::vector<NodeTree<Symbol*>*> getPathEdges(std::vector<NodeTree<int>*> path);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ NodeTree<Symbol*>* RNGLRParser::parseInput(std::string inputString) {
|
|||||||
for (std::vector<ParseAction*>::size_type i = 0; i < firstActions.size(); i++) {
|
for (std::vector<ParseAction*>::size_type i = 0; i < firstActions.size(); i++) {
|
||||||
if (firstActions[i]->action == ParseAction::SHIFT)
|
if (firstActions[i]->action == ParseAction::SHIFT)
|
||||||
toShift.push(std::make_pair(v0,firstActions[i]->shiftState));
|
toShift.push(std::make_pair(v0,firstActions[i]->shiftState));
|
||||||
else if (firstActions[i]->action == ParseAction::REDUCE && firstActions[i]->reduceRule->getRightSide().size() == 0) {
|
else if (firstActions[i]->action == ParseAction::REDUCE && fullyReducesToNull(firstActions[i]->reduceRule)) {
|
||||||
Reduction newReduction = {v0, firstActions[i]->reduceRule->getLeftSide(), 0, getNullableParts(firstActions[i]->reduceRule), NULL};
|
Reduction newReduction = {v0, firstActions[i]->reduceRule->getLeftSide(), 0, getNullableParts(firstActions[i]->reduceRule), NULL};
|
||||||
toReduce.push(newReduction);
|
toReduce.push(newReduction);
|
||||||
//toReduce.push(std::make_pair(std::make_pair(v0, firstActions[i]->reduceRule->getLeftSide()), 0));
|
//toReduce.push(std::make_pair(std::make_pair(v0, firstActions[i]->reduceRule->getLeftSide()), 0));
|
||||||
@@ -158,8 +158,8 @@ void RNGLRParser::reducer(int i) {
|
|||||||
std::cout << "Checking for non-null reductions in states that already existed" << std::endl;
|
std::cout << "Checking for non-null reductions in states that already existed" << std::endl;
|
||||||
std::vector<ParseAction*> actions = *(table.get(toState, input[i]));
|
std::vector<ParseAction*> actions = *(table.get(toState, input[i]));
|
||||||
for (std::vector<ParseAction*>::size_type k = 0; k < actions.size(); k++) {
|
for (std::vector<ParseAction*>::size_type k = 0; k < actions.size(); k++) {
|
||||||
if (actions[k]->action == ParseAction::REDUCE && actions[k]->reduceRule->getRightSize() != 0) {
|
if (actions[k]->action == ParseAction::REDUCE && !fullyReducesToNull(actions[k]->reduceRule)) {
|
||||||
Reduction newReduction = {currentReached, actions[k]->reduceRule->getLeftSide(), actions[k]->reduceRule->getRightSize(), getNullableParts(actions[k]->reduceRule), newLabel};
|
Reduction newReduction = {currentReached, actions[k]->reduceRule->getLeftSide(), actions[k]->reduceRule->getIndex(), getNullableParts(actions[k]->reduceRule), newLabel};
|
||||||
toReduce.push(newReduction);
|
toReduce.push(newReduction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,11 +176,11 @@ void RNGLRParser::reducer(int i) {
|
|||||||
std::cout << "Action is " << actions[k]->toString() << std::endl;
|
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));
|
toShift.push(std::make_pair(toStateNode, actions[k]->shiftState));
|
||||||
} else if (actions[k]->action == ParseAction::REDUCE && actions[k]->reduceRule->getRightSize() == 0) {
|
} else if (actions[k]->action == ParseAction::REDUCE && fullyReducesToNull(actions[k]->reduceRule)) {
|
||||||
Reduction newReduction = {toStateNode, actions[k]->reduceRule->getLeftSide(), 0, getNullableParts(actions[k]->reduceRule), NULL};
|
Reduction newReduction = {toStateNode, actions[k]->reduceRule->getLeftSide(), 0, getNullableParts(actions[k]->reduceRule), NULL};
|
||||||
toReduce.push(newReduction);
|
toReduce.push(newReduction);
|
||||||
} else if (reduction.length != 0 && actions[k]->action == ParseAction::REDUCE && actions[k]->reduceRule->getRightSize() != 0) {
|
} else if (reduction.length != 0 && actions[k]->action == ParseAction::REDUCE && !fullyReducesToNull(actions[k]->reduceRule)) {
|
||||||
Reduction newReduction = {currentReached, actions[k]->reduceRule->getLeftSide(), actions[k]->reduceRule->getRightSize(), getNullableParts(actions[k]->reduceRule), newLabel};
|
Reduction newReduction = {currentReached, actions[k]->reduceRule->getLeftSide(), actions[k]->reduceRule->getIndex(), getNullableParts(actions[k]->reduceRule), newLabel};
|
||||||
toReduce.push(newReduction);
|
toReduce.push(newReduction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,8 +204,8 @@ void RNGLRParser::shifter(int i) {
|
|||||||
gss.addEdge(shiftTo, shift.first, newLabel);
|
gss.addEdge(shiftTo, shift.first, newLabel);
|
||||||
std::vector<ParseAction*> actions = *(table.get(shift.second, input[i+1]));
|
std::vector<ParseAction*> actions = *(table.get(shift.second, input[i+1]));
|
||||||
for (std::vector<ParseAction*>::size_type j = 0; j < actions.size(); j++) {
|
for (std::vector<ParseAction*>::size_type j = 0; j < actions.size(); j++) {
|
||||||
if (actions[j]->action == ParseAction::REDUCE && actions[j]->reduceRule->getRightSize() != 0) {
|
if (actions[j]->action == ParseAction::REDUCE && !fullyReducesToNull(actions[j]->reduceRule)) {
|
||||||
Reduction newReduction = {shift.first, actions[j]->reduceRule->getLeftSide(), actions[j]->reduceRule->getRightSize(), getNullableParts(actions[j]->reduceRule), newLabel};
|
Reduction newReduction = {shift.first, actions[j]->reduceRule->getLeftSide(), actions[j]->reduceRule->getIndex(), getNullableParts(actions[j]->reduceRule), newLabel};
|
||||||
toReduce.push(newReduction);
|
toReduce.push(newReduction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,10 +220,10 @@ void RNGLRParser::shifter(int i) {
|
|||||||
//Shift
|
//Shift
|
||||||
if (actions[j]->action == ParseAction::SHIFT) {
|
if (actions[j]->action == ParseAction::SHIFT) {
|
||||||
nextShifts.push(std::make_pair(shiftTo, actions[j]->shiftState));
|
nextShifts.push(std::make_pair(shiftTo, actions[j]->shiftState));
|
||||||
} else if (actions[j]->action == ParseAction::REDUCE && actions[j]->reduceRule->getRightSize() != 0) {
|
} else if (actions[j]->action == ParseAction::REDUCE && !fullyReducesToNull(actions[j]->reduceRule)) {
|
||||||
Reduction newReduction = {shift.first, actions[j]->reduceRule->getLeftSide(), actions[j]->reduceRule->getRightSize(), getNullableParts(actions[j]->reduceRule), newLabel};
|
Reduction newReduction = {shift.first, actions[j]->reduceRule->getLeftSide(), actions[j]->reduceRule->getIndex(), getNullableParts(actions[j]->reduceRule), newLabel};
|
||||||
toReduce.push(newReduction);
|
toReduce.push(newReduction);
|
||||||
} else if (actions[j]->action == ParseAction::REDUCE && actions[j]->reduceRule->getRightSize() == 0) {
|
} else if (actions[j]->action == ParseAction::REDUCE && fullyReducesToNull(actions[j]->reduceRule)) {
|
||||||
Reduction newReduction = {shiftTo, actions[j]->reduceRule->getLeftSide(), 0, getNullableParts(actions[j]->reduceRule), NULL};
|
Reduction newReduction = {shiftTo, actions[j]->reduceRule->getLeftSide(), 0, getNullableParts(actions[j]->reduceRule), NULL};
|
||||||
toReduce.push(newReduction);
|
toReduce.push(newReduction);
|
||||||
}
|
}
|
||||||
@@ -237,6 +237,7 @@ void RNGLRParser::shifter(int i) {
|
|||||||
void RNGLRParser::addChildren(NodeTree<Symbol*>* parent, std::vector<NodeTree<Symbol*>*>* children, NodeTree<Symbol*>* nullableParts) {
|
void RNGLRParser::addChildren(NodeTree<Symbol*>* parent, std::vector<NodeTree<Symbol*>*>* children, NodeTree<Symbol*>* nullableParts) {
|
||||||
if (nullableParts)
|
if (nullableParts)
|
||||||
children->push_back(nullableParts);
|
children->push_back(nullableParts);
|
||||||
|
|
||||||
if (!belongsToFamily(parent, children)) {
|
if (!belongsToFamily(parent, children)) {
|
||||||
if (parent->getChildren().size() == 0) {
|
if (parent->getChildren().size() == 0) {
|
||||||
parent->addChildren(children);
|
parent->addChildren(children);
|
||||||
@@ -330,18 +331,19 @@ void RNGLRParser::addStates(std::vector< State* >* stateSets, State* state) {
|
|||||||
if ((*currStateTotal)[i]->isAtEnd()) {
|
if ((*currStateTotal)[i]->isAtEnd()) {
|
||||||
for (std::vector<Symbol*>::size_type j = 0; j < lookahead->size(); j++)
|
for (std::vector<Symbol*>::size_type j = 0; j < lookahead->size(); j++)
|
||||||
table.add(stateNum(state), (*lookahead)[j], new ParseAction(ParseAction::REDUCE, (*currStateTotal)[i]));
|
table.add(stateNum(state), (*lookahead)[j], new ParseAction(ParseAction::REDUCE, (*currStateTotal)[i]));
|
||||||
// } else if (*((*currStateTotal)[i]->getAtNextIndex()) == *nullSymbol) {
|
|
||||||
//If this has an appropriate ruduction to null, get the reduce trees out
|
//If this has an appropriate ruduction to null, get the reduce trees out
|
||||||
} else if (reducesToNull((*currStateTotal)[i])) {
|
} else if (reducesToNull((*currStateTotal)[i])) {
|
||||||
std::cout << (*currStateTotal)[i]->toString() << " REDUCES TO NULL" << std::endl;
|
std::cout << (*currStateTotal)[i]->toString() << " REDUCES TO NULL" << std::endl;
|
||||||
//If is a rule that produces only NULL, add in the approprite reduction, but use a new rule with a right side that is equal to
|
//If is a rule that produces only NULL, add in the approprite reduction, but use a new rule with a right side that is equal to
|
||||||
//the part that we've already gone through in the rule. (so we don't pop extra off stack)
|
//the part that we've already gone through in the rule. (so we don't pop extra off stack)
|
||||||
ParseRule* nullRule = (*currStateTotal)[i]->clone();
|
//Now we use the same rule and make sure that the index location is used
|
||||||
std::vector<Symbol*> oldRightSide = nullRule->getRightSide();
|
//ParseRule* nullRule = (*currStateTotal)[i]->clone();
|
||||||
oldRightSide.erase(oldRightSide.begin()+nullRule->getIndex(), oldRightSide.end());
|
// std::vector<Symbol*> oldRightSide = nullRule->getRightSide();
|
||||||
nullRule->setRightSide(oldRightSide);
|
// oldRightSide.erase(oldRightSide.begin()+nullRule->getIndex(), oldRightSide.end());
|
||||||
|
// nullRule->setRightSide(oldRightSide);
|
||||||
for (std::vector<Symbol*>::size_type j = 0; j < lookahead->size(); j++)
|
for (std::vector<Symbol*>::size_type j = 0; j < lookahead->size(); j++)
|
||||||
table.add(stateNum(state), (*lookahead)[j], new ParseAction(ParseAction::REDUCE, nullRule));
|
table.add(stateNum(state), (*lookahead)[j], new ParseAction(ParseAction::REDUCE, (*currStateTotal)[i]));
|
||||||
|
//table.add(stateNum(state), (*lookahead)[j], new ParseAction(ParseAction::REDUCE, nullRule));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Put all our new states in the set of states only if they're not already there.
|
//Put all our new states in the set of states only if they're not already there.
|
||||||
@@ -367,6 +369,10 @@ void RNGLRParser::addStates(std::vector< State* >* stateSets, State* state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RNGLRParser::fullyReducesToNull(ParseRule* rule) {
|
||||||
|
return rule->getIndex() == 0 && reducesToNull(rule);
|
||||||
|
}
|
||||||
|
|
||||||
bool RNGLRParser::reducesToNull(ParseRule* rule) {
|
bool RNGLRParser::reducesToNull(ParseRule* rule) {
|
||||||
std::vector<Symbol*> avoidList;
|
std::vector<Symbol*> avoidList;
|
||||||
return reducesToNull(rule, avoidList);
|
return reducesToNull(rule, avoidList);
|
||||||
@@ -410,23 +416,37 @@ bool RNGLRParser::reducesToNull(ParseRule* rule, std::vector<Symbol*> avoidList)
|
|||||||
}
|
}
|
||||||
|
|
||||||
NodeTree<Symbol*>* RNGLRParser::getNullableParts(ParseRule* rule) {
|
NodeTree<Symbol*>* RNGLRParser::getNullableParts(ParseRule* rule) {
|
||||||
//return new NodeTree<Symbol*>("FAKE_PARTS_FOR_NO_CRASH", nullSymbol);
|
return getNullableParts(rule, std::vector<NodeTree<Symbol*>*>());
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeTree<Symbol*>* RNGLRParser::getNullableParts(ParseRule* rule, std::vector<NodeTree<Symbol*>*> avoidList) {
|
||||||
if (reducesToNull(rule)) {
|
if (reducesToNull(rule)) {
|
||||||
std::cout << "Reduces to null so adding parts " << rule->toString() << std::endl;
|
std::cout << "Reduces to null so adding parts " << rule->toString() << std::endl;
|
||||||
//return new NodeTree<Symbol*>("FAKE_PARTS_FOR_NO_CRASH", nullSymbol);
|
//return new NodeTree<Symbol*>("FAKE_PARTS_FOR_NO_CRASH", nullSymbol);
|
||||||
Symbol* symbol = rule->getLeftSide();
|
Symbol* symbol = rule->getLeftSide();
|
||||||
NodeTree<Symbol*>* symbolNode = new NodeTree<Symbol*>(symbol->getName(), symbol);
|
NodeTree<Symbol*>* symbolNode = new NodeTree<Symbol*>(symbol->getName(), symbol);
|
||||||
if (rule->getRightSize() == 0) {
|
if (*(rule->getAtNextIndex()) == *nullSymbol) {
|
||||||
symbolNode->addChild(new NodeTree<Symbol*>(nullSymbol->getName(), nullSymbol));
|
symbolNode->addChild(new NodeTree<Symbol*>(nullSymbol->getName(), nullSymbol));
|
||||||
} else {
|
} else {
|
||||||
//Do something recursive
|
//Find recursively
|
||||||
//Be careful of cycles
|
|
||||||
ParseRule* iterate = rule->clone();
|
ParseRule* iterate = rule->clone();
|
||||||
while (!iterate->isAtEnd()) {
|
while (!iterate->isAtEnd()) {
|
||||||
for (std::vector<ParseRule*>::size_type i = 0; i < loadedGrammer.size(); i++)
|
//Check to see if we've done this symbol already, if so use it
|
||||||
if (*(iterate->getAtNextIndex()) == *(loadedGrammer[i]->getLeftSide()))
|
for (std::vector<NodeTree<Symbol*>*>::size_type i = 0; i < avoidList.size(); i++) {
|
||||||
symbolNode->addChild(getNullableParts(loadedGrammer[i]));
|
if (*(iterate->getAtNextIndex()) == *(avoidList[i]->getData())) {
|
||||||
rule->advancePointer();
|
symbolNode->addChild(avoidList[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//We haven't so do it recursively
|
||||||
|
for (std::vector<ParseRule*>::size_type i = 0; i < loadedGrammer.size(); i++) {
|
||||||
|
if (fullyReducesToNull(loadedGrammer[i]) && *(iterate->getAtNextIndex()) == *(loadedGrammer[i]->getLeftSide())) {
|
||||||
|
NodeTree<Symbol*>* symbolTree = getNullableParts(loadedGrammer[i], avoidList);
|
||||||
|
avoidList.push_back(symbolTree);
|
||||||
|
symbolNode->addChild(symbolTree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iterate->advancePointer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return symbolNode;
|
return symbolNode;
|
||||||
|
|||||||
Reference in New Issue
Block a user