RNGLR Recognizer now works for grammers without null rules.

This commit is contained in:
Nathan Braswell
2013-08-02 02:47:01 -04:00
parent 9887555dd5
commit 49d149bc1f
8 changed files with 96 additions and 1 deletions

View File

@@ -33,6 +33,8 @@ class ParseRule {
int getRightSize();
int getIndex();
std::vector<NodeTree<Symbol*>*>* nullReductions();
bool advancePointer();
bool isAtEnd();

View File

@@ -10,6 +10,7 @@ class RNGLRParser: public Parser {
NodeTree<Symbol*>* parseInput(std::string inputString);
void reducer(int i);
void shifter(int i);
void addStates(std::vector< State* >* stateSets, State* state);
private:
std::vector<Symbol*> input;
GraphStructuredStack gss;

View File

@@ -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<ParseAction*>* get(int state, Symbol* token);
ParseAction* getShift(int state, Symbol* token);
std::string toString();

View File

@@ -78,7 +78,7 @@ bool GraphStructuredStack::hasEdge(NodeTree<int>* start, NodeTree<int>* end) {
void GraphStructuredStack::addEdge(NodeTree<int>* start, NodeTree<int>* end) {
start->addChild(end);
end->addChild(start);
end->addParent(start);
}
std::string GraphStructuredStack::toString() {

View File

@@ -73,6 +73,10 @@ int ParseRule::getIndex() {
return pointerIndex;
}
std::vector<NodeTree<Symbol*>*>* ParseRule::nullReductions() {
//Return a vector of null reduction trees
}
bool ParseRule::advancePointer() {
if (pointerIndex < rightSide.size()) {
pointerIndex++;

View File

@@ -143,6 +143,7 @@ void Parser::createStateSet() {
//Add the new states
addStates(&stateSets, stateSets[i]);
}
table.remove(1, EOFSymbol);
}
int Parser::stateNum(State* state) {

View File

@@ -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<ParseRule*>* currStateTotal = state->getTotal();
for (std::vector<ParseRule*>::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<Symbol*>* lookahead = (*currStateTotal)[i]->getLookahead();
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 (std::vector<NodeTree<Symbol*>*>* 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<Symbol*>());
for (std::vector<Symbol*>::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));
}
}
}

View File

@@ -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<Symbol*>::size_type i = 0; i < symbolIndexVec.size(); i++) {
if ( *(symbolIndexVec[i]) == *tranSymbol ) {
//Has been found
symbolIndex = i;
break;
}
}
(*(table[stateNum]))[symbolIndex] = NULL;
}
std::vector<ParseAction*>* Table::get(int state, Symbol* token) {
int symbolIndex = -1;
for (std::vector<Symbol*>::size_type i = 0; i < symbolIndexVec.size(); i++) {