From 49d149bc1fef988e7e1b5d9c44f764c19dd411f6 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Fri, 2 Aug 2013 02:47:01 -0400 Subject: [PATCH] RNGLR Recognizer now works for grammers without null rules. --- include/ParseRule.h | 2 + include/RNGLRParser.h | 1 + include/Table.h | 1 + src/GraphStructuredStack.cpp | 2 +- src/ParseRule.cpp | 4 ++ src/Parser.cpp | 1 + src/RNGLRParser.cpp | 73 ++++++++++++++++++++++++++++++++++++ src/Table.cpp | 13 +++++++ 8 files changed, 96 insertions(+), 1 deletion(-) diff --git a/include/ParseRule.h b/include/ParseRule.h index ba5cca9..ee778fa 100644 --- a/include/ParseRule.h +++ b/include/ParseRule.h @@ -33,6 +33,8 @@ class ParseRule { int getRightSize(); int getIndex(); + std::vector*>* nullReductions(); + bool advancePointer(); bool isAtEnd(); diff --git a/include/RNGLRParser.h b/include/RNGLRParser.h index d8ed0be..b7f2a2e 100644 --- a/include/RNGLRParser.h +++ b/include/RNGLRParser.h @@ -10,6 +10,7 @@ class RNGLRParser: public Parser { NodeTree* parseInput(std::string inputString); void reducer(int i); void shifter(int i); + void addStates(std::vector< State* >* stateSets, State* state); private: std::vector input; GraphStructuredStack gss; diff --git a/include/Table.h b/include/Table.h index 659111b..bc7994b 100644 --- a/include/Table.h +++ b/include/Table.h @@ -13,6 +13,7 @@ class Table { ~Table(); void setSymbols(Symbol* EOFSymbol, Symbol* nullSymbol); void add(int stateNum, Symbol* tranSymbol, ParseAction* action); + void remove(int stateNum, Symbol* tranSymbol); std::vector* get(int state, Symbol* token); ParseAction* getShift(int state, Symbol* token); std::string toString(); diff --git a/src/GraphStructuredStack.cpp b/src/GraphStructuredStack.cpp index 83a57cf..66ecf9b 100644 --- a/src/GraphStructuredStack.cpp +++ b/src/GraphStructuredStack.cpp @@ -78,7 +78,7 @@ bool GraphStructuredStack::hasEdge(NodeTree* start, NodeTree* end) { void GraphStructuredStack::addEdge(NodeTree* start, NodeTree* end) { start->addChild(end); - end->addChild(start); + end->addParent(start); } std::string GraphStructuredStack::toString() { diff --git a/src/ParseRule.cpp b/src/ParseRule.cpp index 41254c3..c8991ab 100644 --- a/src/ParseRule.cpp +++ b/src/ParseRule.cpp @@ -73,6 +73,10 @@ int ParseRule::getIndex() { return pointerIndex; } +std::vector*>* ParseRule::nullReductions() { + //Return a vector of null reduction trees +} + bool ParseRule::advancePointer() { if (pointerIndex < rightSide.size()) { pointerIndex++; diff --git a/src/Parser.cpp b/src/Parser.cpp index 048d666..06f1e19 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -143,6 +143,7 @@ void Parser::createStateSet() { //Add the new states addStates(&stateSets, stateSets[i]); } + table.remove(1, EOFSymbol); } int Parser::stateNum(State* state) { diff --git a/src/RNGLRParser.cpp b/src/RNGLRParser.cpp index 79462fb..7e3bb3e 100644 --- a/src/RNGLRParser.cpp +++ b/src/RNGLRParser.cpp @@ -167,4 +167,77 @@ void RNGLRParser::shifter(int i) { } toShift = nextShifts; } +} + +//Have to use own add states function in order to construct RN table instead of LALR table +void RNGLRParser::addStates(std::vector< State* >* stateSets, State* state) { + std::cout << "RNGLR ADD STATES" << std::endl; + std::vector< State* > newStates; + //For each rule in the state we already have + std::vector* currStateTotal = state->getTotal(); + for (std::vector::size_type i = 0; i < currStateTotal->size(); i++) { + //Clone the current rule + ParseRule* advancedRule = (*currStateTotal)[i]->clone(); + //Try to advance the pointer, if sucessful see if it is the correct next symbol + if (advancedRule->advancePointer()) { + //Technically, it should be the set of rules sharing this symbol advanced past in the basis for new state + + //So search our new states to see if any of them use this advanced symbol as a base. + //If so, add this rule to them. + //If not, create it. + bool symbolAlreadyInState = false; + for (std::vector< State* >::size_type j = 0; j < newStates.size(); j++) { + if (*(newStates[j]->basis[0]->getAtIndex()) == *(advancedRule->getAtIndex())) { + symbolAlreadyInState = true; + //So now check to see if this exact rule is in this state + if (!newStates[j]->containsRule(advancedRule)) + newStates[j]->basis.push_back(advancedRule); + //We found a state with the same symbol, so stop searching + break; + } + } + if (!symbolAlreadyInState) { + State* newState = new State(stateSets->size()+newStates.size(),advancedRule, state); + newStates.push_back(newState); + } + } + //Also add any completed rules as reduces in the action table + //See if reduce + //Also, this really only needs to be done for the state's basis, but we're already iterating through, so... + std::vector* lookahead = (*currStateTotal)[i]->getLookahead(); + if ((*currStateTotal)[i]->isAtEnd()) { + for (std::vector::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 (std::vector*>* reduceTrees = (*currStateTotal)[i]->nullReductions(), reduceTrees) { + std::cout << "REDUCE TREES" << std::endl; + //If is a rule that produces only NULL, add in the approprite reduction, but use a new rule with a right side of length 0. (so we don't pop off stack) + ParseRule* nullRule = (*currStateTotal)[i]->clone(); + nullRule->setRightSide(* new std::vector()); + for (std::vector::size_type j = 0; j < lookahead->size(); j++) + 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. + bool stateAlreadyInAllStates = false; + Symbol* currStateSymbol; + for (std::vector< State * >::size_type i = 0; i < newStates.size(); i++) { + stateAlreadyInAllStates = false; + currStateSymbol = (*(newStates[i]->getBasis()))[0]->getAtIndex(); + for (std::vector< State * >::size_type j = 0; j < stateSets->size(); j++) { + if (newStates[i]->basisEquals(*((*stateSets)[j]))) { + stateAlreadyInAllStates = true; + //If it does exist, we should add it as the shift/goto in the action table + (*stateSets)[j]->addParents(newStates[i]->getParents()); + table.add(stateNum(state), currStateSymbol, new ParseAction(ParseAction::SHIFT, j)); + break; + } + } + if (!stateAlreadyInAllStates) { + //If the state does not already exist, add it and add it as the shift/goto in the action table + stateSets->push_back(newStates[i]); + table.add(stateNum(state), currStateSymbol, new ParseAction(ParseAction::SHIFT, stateSets->size()-1)); + } + } } \ No newline at end of file diff --git a/src/Table.cpp b/src/Table.cpp index 39373c3..044a804 100644 --- a/src/Table.cpp +++ b/src/Table.cpp @@ -71,6 +71,19 @@ void Table::add(int stateNum, Symbol* tranSymbol, ParseAction* action) { } } +void Table::remove(int stateNum, Symbol* tranSymbol) { + //find out what index this symbol is on + int symbolIndex = -1; + for (std::vector::size_type i = 0; i < symbolIndexVec.size(); i++) { + if ( *(symbolIndexVec[i]) == *tranSymbol ) { + //Has been found + symbolIndex = i; + break; + } + } + (*(table[stateNum]))[symbolIndex] = NULL; +} + std::vector* Table::get(int state, Symbol* token) { int symbolIndex = -1; for (std::vector::size_type i = 0; i < symbolIndexVec.size(); i++) {