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();
|
||||
|
||||
private:
|
||||
std::string DOTGraphStringHelper();
|
||||
std::string DOTGraphStringHelper(std::vector<NodeTree<T>*> avoidList);
|
||||
std::string getDOTName();
|
||||
std::string name;
|
||||
T data;
|
||||
@@ -124,6 +124,8 @@ std::vector<NodeTree<T>*> NodeTree<T>::getParents() {
|
||||
|
||||
template<class T>
|
||||
void NodeTree<T>::addChild(NodeTree<T>* child) {
|
||||
if (!child)
|
||||
throw "Help, NULL child";
|
||||
if (findChild(child) == -1)
|
||||
children.push_back(child);
|
||||
}
|
||||
@@ -206,15 +208,20 @@ void NodeTree<T>::setData(T data) {
|
||||
|
||||
template<class T>
|
||||
std::string NodeTree<T>::DOTGraphString() {
|
||||
return( "digraph Kraken { \n" + DOTGraphStringHelper() + "}");
|
||||
return( "digraph Kraken { \n" + DOTGraphStringHelper(std::vector<NodeTree<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 = "";
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
if (children[i] != NULL)
|
||||
ourDOTRelation += getDOTName() + " -> " + children[i]->getDOTName() + ";\n" + children[i]->DOTGraphStringHelper();
|
||||
ourDOTRelation += getDOTName() + " -> " + children[i]->getDOTName() + ";\n" + children[i]->DOTGraphStringHelper(avoidList);
|
||||
else
|
||||
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 addStates(std::vector< State* >* stateSets, State* state);
|
||||
bool fullyReducesToNull(ParseRule* rule);
|
||||
bool reducesToNull(ParseRule* rule);
|
||||
bool reducesToNull(ParseRule* rule, std::vector<Symbol*> avoidList);
|
||||
|
||||
@@ -32,6 +33,7 @@ class RNGLRParser: public Parser {
|
||||
void setPacked(NodeTree<Symbol*>* node, bool isPacked);
|
||||
|
||||
NodeTree<Symbol*>* getNullableParts(ParseRule* rule);
|
||||
NodeTree<Symbol*>* getNullableParts(ParseRule* rule, std::vector<NodeTree<Symbol*>*> avoidList);
|
||||
NodeTree<Symbol*>* getNullableParts(Symbol* symbol);
|
||||
|
||||
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++) {
|
||||
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) {
|
||||
else if (firstActions[i]->action == ParseAction::REDUCE && fullyReducesToNull(firstActions[i]->reduceRule)) {
|
||||
Reduction newReduction = {v0, firstActions[i]->reduceRule->getLeftSide(), 0, getNullableParts(firstActions[i]->reduceRule), NULL};
|
||||
toReduce.push(newReduction);
|
||||
//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::vector<ParseAction*> actions = *(table.get(toState, input[i]));
|
||||
for (std::vector<ParseAction*>::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(), getNullableParts(actions[k]->reduceRule), newLabel};
|
||||
if (actions[k]->action == ParseAction::REDUCE && !fullyReducesToNull(actions[k]->reduceRule)) {
|
||||
Reduction newReduction = {currentReached, actions[k]->reduceRule->getLeftSide(), actions[k]->reduceRule->getIndex(), getNullableParts(actions[k]->reduceRule), newLabel};
|
||||
toReduce.push(newReduction);
|
||||
}
|
||||
}
|
||||
@@ -176,11 +176,11 @@ void RNGLRParser::reducer(int i) {
|
||||
std::cout << "Action is " << actions[k]->toString() << std::endl;
|
||||
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) {
|
||||
} else if (actions[k]->action == ParseAction::REDUCE && fullyReducesToNull(actions[k]->reduceRule)) {
|
||||
Reduction newReduction = {toStateNode, actions[k]->reduceRule->getLeftSide(), 0, getNullableParts(actions[k]->reduceRule), NULL};
|
||||
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(), getNullableParts(actions[k]->reduceRule), newLabel};
|
||||
} else if (reduction.length != 0 && actions[k]->action == ParseAction::REDUCE && !fullyReducesToNull(actions[k]->reduceRule)) {
|
||||
Reduction newReduction = {currentReached, actions[k]->reduceRule->getLeftSide(), actions[k]->reduceRule->getIndex(), getNullableParts(actions[k]->reduceRule), newLabel};
|
||||
toReduce.push(newReduction);
|
||||
}
|
||||
}
|
||||
@@ -204,8 +204,8 @@ void RNGLRParser::shifter(int i) {
|
||||
gss.addEdge(shiftTo, shift.first, newLabel);
|
||||
std::vector<ParseAction*> actions = *(table.get(shift.second, input[i+1]));
|
||||
for (std::vector<ParseAction*>::size_type j = 0; j < actions.size(); j++) {
|
||||
if (actions[j]->action == ParseAction::REDUCE && actions[j]->reduceRule->getRightSize() != 0) {
|
||||
Reduction newReduction = {shift.first, actions[j]->reduceRule->getLeftSide(), actions[j]->reduceRule->getRightSize(), getNullableParts(actions[j]->reduceRule), newLabel};
|
||||
if (actions[j]->action == ParseAction::REDUCE && !fullyReducesToNull(actions[j]->reduceRule)) {
|
||||
Reduction newReduction = {shift.first, actions[j]->reduceRule->getLeftSide(), actions[j]->reduceRule->getIndex(), getNullableParts(actions[j]->reduceRule), newLabel};
|
||||
toReduce.push(newReduction);
|
||||
}
|
||||
}
|
||||
@@ -220,10 +220,10 @@ void RNGLRParser::shifter(int i) {
|
||||
//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) {
|
||||
Reduction newReduction = {shift.first, actions[j]->reduceRule->getLeftSide(), actions[j]->reduceRule->getRightSize(), getNullableParts(actions[j]->reduceRule), newLabel};
|
||||
} else if (actions[j]->action == ParseAction::REDUCE && !fullyReducesToNull(actions[j]->reduceRule)) {
|
||||
Reduction newReduction = {shift.first, actions[j]->reduceRule->getLeftSide(), actions[j]->reduceRule->getIndex(), getNullableParts(actions[j]->reduceRule), newLabel};
|
||||
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};
|
||||
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) {
|
||||
if (nullableParts)
|
||||
children->push_back(nullableParts);
|
||||
|
||||
if (!belongsToFamily(parent, children)) {
|
||||
if (parent->getChildren().size() == 0) {
|
||||
parent->addChildren(children);
|
||||
@@ -330,18 +331,19 @@ void RNGLRParser::addStates(std::vector< State* >* stateSets, State* state) {
|
||||
if ((*currStateTotal)[i]->isAtEnd()) {
|
||||
for (std::vector<Symbol*>::size_type j = 0; j < lookahead->size(); j++)
|
||||
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
|
||||
} else if (reducesToNull((*currStateTotal)[i])) {
|
||||
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
|
||||
//the part that we've already gone through in the rule. (so we don't pop extra off stack)
|
||||
ParseRule* nullRule = (*currStateTotal)[i]->clone();
|
||||
std::vector<Symbol*> oldRightSide = nullRule->getRightSide();
|
||||
oldRightSide.erase(oldRightSide.begin()+nullRule->getIndex(), oldRightSide.end());
|
||||
nullRule->setRightSide(oldRightSide);
|
||||
//Now we use the same rule and make sure that the index location is used
|
||||
//ParseRule* nullRule = (*currStateTotal)[i]->clone();
|
||||
// std::vector<Symbol*> oldRightSide = nullRule->getRightSide();
|
||||
// oldRightSide.erase(oldRightSide.begin()+nullRule->getIndex(), oldRightSide.end());
|
||||
// nullRule->setRightSide(oldRightSide);
|
||||
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.
|
||||
@@ -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) {
|
||||
std::vector<Symbol*> avoidList;
|
||||
return reducesToNull(rule, avoidList);
|
||||
@@ -410,23 +416,37 @@ bool RNGLRParser::reducesToNull(ParseRule* rule, std::vector<Symbol*> avoidList)
|
||||
}
|
||||
|
||||
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)) {
|
||||
std::cout << "Reduces to null so adding parts " << rule->toString() << std::endl;
|
||||
//return new NodeTree<Symbol*>("FAKE_PARTS_FOR_NO_CRASH", nullSymbol);
|
||||
Symbol* symbol = rule->getLeftSide();
|
||||
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));
|
||||
} else {
|
||||
//Do something recursive
|
||||
//Be careful of cycles
|
||||
//Find recursively
|
||||
ParseRule* iterate = rule->clone();
|
||||
while (!iterate->isAtEnd()) {
|
||||
for (std::vector<ParseRule*>::size_type i = 0; i < loadedGrammer.size(); i++)
|
||||
if (*(iterate->getAtNextIndex()) == *(loadedGrammer[i]->getLeftSide()))
|
||||
symbolNode->addChild(getNullableParts(loadedGrammer[i]));
|
||||
rule->advancePointer();
|
||||
//Check to see if we've done this symbol already, if so use it
|
||||
for (std::vector<NodeTree<Symbol*>*>::size_type i = 0; i < avoidList.size(); i++) {
|
||||
if (*(iterate->getAtNextIndex()) == *(avoidList[i]->getData())) {
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user