2013-07-31 23:51:05 -04:00
# include "RNGLRParser.h"
2013-07-28 19:45:08 -04:00
2013-07-31 23:51:05 -04:00
RNGLRParser : : RNGLRParser ( ) {
//
}
RNGLRParser : : ~ RNGLRParser ( ) {
//
}
2013-10-02 03:15:20 -04:00
NodeTree < Symbol > * RNGLRParser : : parseInput ( std : : string inputString ) {
2013-07-28 19:45:08 -04:00
//Check for no tokens
2013-07-31 23:51:05 -04:00
bool accepting = false ;
2013-07-28 19:45:08 -04:00
if ( inputString = = " " ) {
2013-07-31 23:51:05 -04:00
std : : vector < ParseAction * > * zeroStateActions = table . get ( 0 , EOFSymbol ) ;
for ( int i = 0 ; i < zeroStateActions - > size ( ) ; i + + ) {
if ( ( * zeroStateActions ) [ i ] - > action = = ParseAction : : REDUCE )
accepting = true ;
}
2013-08-08 02:44:17 -04:00
if ( accepting ) {
2013-07-28 19:45:08 -04:00
std : : cout < < " Accepted! " < < std : : endl ;
2013-08-09 04:39:43 -04:00
return getNullableParts ( ( * ( stateSets [ 0 ] - > getBasis ( ) ) ) [ 0 ] - > getLeftSide ( ) ) ;
2013-08-08 02:44:17 -04:00
} else {
2013-07-28 19:45:08 -04:00
std : : cout < < " Rejected, no input (with no accepting state) " < < std : : endl ;
2013-08-08 02:44:17 -04:00
}
2013-10-02 03:15:20 -04:00
return new NodeTree < Symbol > ( ) ;
2013-07-28 19:45:08 -04:00
}
lexer . setInput ( inputString ) ;
//Now fully lex our input because this algorithm was designed in that manner and simplifies this first implementation.
//It could be converted to on-line later.
2013-10-02 03:15:20 -04:00
Symbol currentToken = lexer . next ( ) ;
2013-07-28 19:45:08 -04:00
input . push_back ( currentToken ) ;
2013-10-02 03:15:20 -04:00
while ( currentToken ! = EOFSymbol ) {
2013-07-28 19:45:08 -04:00
currentToken = lexer . next ( ) ;
2013-11-01 02:52:18 -04:00
//std::cout << "CurrentToken is " << currentToken.toString() << std::endl;
if ( currentToken = = invalidSymbol ) {
std : : cout < < " Invalid Symbol! " < < std : : endl ;
throw " Invalid Symbol, cannot lex " ;
}
2013-10-02 03:15:20 -04:00
input . push_back ( currentToken ) ;
2013-07-28 19:45:08 -04:00
}
2013-08-16 00:03:26 -04:00
std : : cout < < " \n Done with Lexing \n " < < std : : endl ;
2013-07-31 23:51:05 -04:00
2013-08-16 00:03:26 -04:00
// for (int i = 0; i < input.size(); i++)
// std::cout << "|" << input[i]->toString() << "|";
// std::cout << std::endl;
2013-07-31 23:51:05 -04:00
std : : cout < < " Setting up 0th frontier, first actions, toShift, toReduce " < < std : : endl ;
2013-07-28 19:45:08 -04:00
//Frontier 0, new node with state 0
2013-07-28 23:48:10 -04:00
NodeTree < int > * v0 = gss . newNode ( 0 ) ;
2013-07-28 19:45:08 -04:00
gss . addToFrontier ( 0 , v0 ) ;
2013-07-31 23:51:05 -04:00
std : : cout < < " Done setting up new frontier " < < std : : endl ;
std : : vector < ParseAction * > firstActions = * ( table . get ( 0 , input [ 0 ] ) ) ;
2013-07-28 19:45:08 -04:00
for ( std : : vector < ParseAction * > : : size_type i = 0 ; i < firstActions . size ( ) ; i + + ) {
if ( firstActions [ i ] - > action = = ParseAction : : SHIFT )
2013-07-31 23:51:05 -04:00
toShift . push ( std : : make_pair ( v0 , firstActions [ i ] - > shiftState ) ) ;
2013-08-13 14:01:53 -04:00
else if ( firstActions [ i ] - > action = = ParseAction : : REDUCE & & fullyReducesToNull ( firstActions [ i ] - > reduceRule ) ) {
2013-08-12 00:02:50 -04:00
Reduction newReduction = { v0 , firstActions [ i ] - > reduceRule - > getLeftSide ( ) , 0 , getNullableParts ( firstActions [ i ] - > reduceRule ) , NULL } ;
2013-08-08 02:44:17 -04:00
toReduce . push ( newReduction ) ;
//toReduce.push(std::make_pair(std::make_pair(v0, firstActions[i]->reduceRule->getLeftSide()), 0));
2013-07-28 19:45:08 -04:00
}
}
2013-08-16 00:03:26 -04:00
// std::cout << "GSS:\n" << gss.toString() << std::endl;
2013-07-31 23:51:05 -04:00
std : : cout < < " Starting parse loop " < < std : : endl ;
2013-07-28 19:45:08 -04:00
for ( int i = 0 ; i < input . size ( ) ; i + + ) {
2013-08-16 00:03:26 -04:00
// std::cout << "Checking if frontier " << i << " is empty" << std::endl;
2013-07-31 23:51:05 -04:00
if ( gss . frontierIsEmpty ( i ) ) {
std : : cout < < " Frontier " < < i < < " is empty. " < < std : : endl ;
2013-10-02 03:15:20 -04:00
std : : cout < < " Failed on " < < input [ i ] . toString ( ) < < std : : endl ;
2013-08-27 13:23:37 -04:00
std : : cout < < " Nearby is: " < < std : : endl ;
2013-12-22 01:34:59 -06:00
const int range = 10 ;
2013-08-27 13:23:37 -04:00
for ( int j = ( i - range > = 0 ? i - range : 0 ) ; j < ( i + range < input . size ( ) ? i + range : input . size ( ) ) ; j + + )
2013-12-18 18:05:21 -06:00
if ( j = = i )
std : : cout < < " ||*||*|| " < < input [ j ] . toString ( ) < < " ||*||*|| " ;
else
std : : cout < < input [ j ] . toString ( ) < < " " ;
2013-08-27 13:23:37 -04:00
std : : cout < < std : : endl ;
2013-07-28 19:45:08 -04:00
break ;
2013-07-31 23:51:05 -04:00
}
2013-08-08 02:44:17 -04:00
//Clear the vector of SPPF nodes created every step
SPPFStepNodes . clear ( ) ;
2013-07-31 23:51:05 -04:00
while ( toReduce . size ( ) ! = 0 ) {
2013-08-16 00:03:26 -04:00
//std::cout << "Reducing for " << i << std::endl;
2013-07-31 23:51:05 -04:00
//std::cout << "GSS:\n" << gss.toString() << std::endl;
2013-07-28 19:45:08 -04:00
reducer ( i ) ;
2013-07-31 23:51:05 -04:00
}
2013-08-16 00:03:26 -04:00
// std::cout << "Shifting for " << i << std::endl;
2013-07-28 19:45:08 -04:00
shifter ( i ) ;
2013-08-16 00:03:26 -04:00
//std::cout << "GSS:\n" << gss.toString() << std::endl;
2013-07-28 19:45:08 -04:00
}
2013-07-31 23:51:05 -04:00
std : : cout < < " Done with parsing loop, checking for acceptance " < < std : : endl ;
2013-08-09 04:39:43 -04:00
NodeTree < int > * accState = gss . frontierGetAccState ( input . size ( ) - 1 ) ;
2013-08-08 02:44:17 -04:00
if ( accState ) {
2013-07-28 19:45:08 -04:00
std : : cout < < " Accepted! " < < std : : endl ;
2013-08-08 02:44:17 -04:00
return gss . getEdge ( accState , v0 ) ;
}
2013-07-31 23:51:05 -04:00
2013-08-10 18:24:37 -04:00
std : : cout < < " Rejected! " < < std : : endl ;
2013-07-31 23:51:05 -04:00
std : : cout < < " GSS: \n " < < gss . toString ( ) < < std : : endl ;
2013-08-08 02:44:17 -04:00
return NULL ;
2013-07-28 19:45:08 -04:00
}
2013-07-31 23:51:05 -04:00
void RNGLRParser : : reducer ( int i ) {
2013-08-08 02:44:17 -04:00
Reduction reduction = toReduce . front ( ) ;
2013-07-31 23:51:05 -04:00
toReduce . pop ( ) ;
2013-08-16 00:03:26 -04:00
//std::cout << "Doing reduction of length " << reduction.length << " from state " << reduction.from->getData() << " to symbol " << reduction.symbol->toString() << std::endl;
2013-08-08 02:44:17 -04:00
int pathLength = reduction . length > 0 ? reduction . length - 1 : 0 ;
//Get every reachable path
std : : vector < std : : vector < NodeTree < int > * > > * paths = gss . getReachablePaths ( reduction . from , pathLength ) ;
for ( std : : vector < std : : vector < NodeTree < int > * > > : : size_type j = 0 ; j < paths - > size ( ) ; j + + ) {
std : : vector < NodeTree < int > * > currentPath = ( * paths ) [ j ] ;
//Get the edges for the current path
2013-10-02 03:15:20 -04:00
std : : vector < NodeTree < Symbol > * > pathEdges = getPathEdges ( currentPath ) ;
2013-08-10 18:24:37 -04:00
std : : reverse ( pathEdges . begin ( ) , pathEdges . end ( ) ) ;
2013-08-08 02:44:17 -04:00
//If the reduction length is 0, label as passed in is null
if ( reduction . length ! = 0 )
pathEdges . push_back ( reduction . label ) ;
2013-08-10 18:24:37 -04:00
//The end of the current path
NodeTree < int > * currentReached = currentPath [ currentPath . size ( ) - 1 ] ;
2013-08-08 02:44:17 -04:00
2013-10-02 03:15:20 -04:00
std : : cout < < " Getting the shfit state for state " < < currentReached - > getData ( ) < < " and symbol " < < reduction . symbol . toString ( ) < < std : : endl ;
2013-08-08 02:44:17 -04:00
int toState = table . getShift ( currentReached - > getData ( ) , reduction . symbol ) - > shiftState ;
//If reduction length is 0, then we make the new label the appropriate nullable parts
2013-10-02 03:15:20 -04:00
NodeTree < Symbol > * newLabel = NULL ;
2013-08-08 02:44:17 -04:00
if ( reduction . length = = 0 ) {
2013-08-12 00:02:50 -04:00
newLabel = reduction . nullableParts ;
2013-08-08 02:44:17 -04:00
} else {
//Otherwise, we create the new label if we haven't already
int reachedFrontier = gss . getContainingFrontier ( currentReached ) ;
2013-10-02 03:15:20 -04:00
for ( std : : vector < std : : pair < NodeTree < Symbol > * , int > > : : size_type k = 0 ; k < SPPFStepNodes . size ( ) ; k + + ) {
if ( SPPFStepNodes [ k ] . second = = reachedFrontier & & SPPFStepNodes [ k ] . first - > getData ( ) = = reduction . symbol ) {
2013-08-08 02:44:17 -04:00
newLabel = SPPFStepNodes [ k ] . first ;
break ;
}
}
if ( ! newLabel ) {
2013-10-02 03:15:20 -04:00
newLabel = new NodeTree < Symbol > ( " frontier: " + intToString ( reachedFrontier ) , reduction . symbol ) ;
2013-08-08 02:44:17 -04:00
SPPFStepNodes . push_back ( std : : make_pair ( newLabel , reachedFrontier ) ) ;
}
}
2013-07-28 23:48:10 -04:00
NodeTree < int > * toStateNode = gss . inFrontier ( i , toState ) ;
2013-07-28 19:45:08 -04:00
if ( toStateNode ) {
if ( ! gss . hasEdge ( toStateNode , currentReached ) ) {
2013-08-08 02:44:17 -04:00
gss . addEdge ( toStateNode , currentReached , newLabel ) ;
if ( reduction . length ! = 0 ) {
2013-07-31 23:51:05 -04:00
//Do all non null reduction
2013-08-16 00:03:26 -04:00
//std::cout << "Checking for non-null reductions in states that already existed" << std::endl;
2013-07-31 23:51:05 -04:00
std : : vector < ParseAction * > actions = * ( table . get ( toState , input [ i ] ) ) ;
2013-08-08 02:44:17 -04:00
for ( std : : vector < ParseAction * > : : size_type k = 0 ; k < actions . size ( ) ; k + + ) {
2013-08-13 14:01:53 -04:00
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 } ;
2013-08-08 02:44:17 -04:00
toReduce . push ( newReduction ) ;
}
}
2013-07-28 19:45:08 -04:00
}
}
} else {
toStateNode = gss . newNode ( toState ) ;
gss . addToFrontier ( i , toStateNode ) ;
2013-08-08 02:44:17 -04:00
gss . addEdge ( toStateNode , currentReached , newLabel ) ;
2013-07-28 19:45:08 -04:00
2013-08-16 00:03:26 -04:00
//std::cout << "Adding shifts and reductions for a state that did not exist" << std::endl;
2013-07-31 23:51:05 -04:00
std : : vector < ParseAction * > actions = * ( table . get ( toState , input [ i ] ) ) ;
2013-07-28 19:45:08 -04:00
for ( std : : vector < ParseAction * > : : size_type k = 0 ; k < actions . size ( ) ; k + + ) {
2013-08-06 01:49:45 -04:00
std : : cout < < " Action is " < < actions [ k ] - > toString ( ) < < std : : endl ;
2013-08-08 02:44:17 -04:00
if ( actions [ k ] - > action = = ParseAction : : SHIFT ) {
2013-07-31 23:51:05 -04:00
toShift . push ( std : : make_pair ( toStateNode , actions [ k ] - > shiftState ) ) ;
2013-08-13 14:01:53 -04:00
} else if ( actions [ k ] - > action = = ParseAction : : REDUCE & & fullyReducesToNull ( actions [ k ] - > reduceRule ) ) {
2013-08-12 00:02:50 -04:00
Reduction newReduction = { toStateNode , actions [ k ] - > reduceRule - > getLeftSide ( ) , 0 , getNullableParts ( actions [ k ] - > reduceRule ) , NULL } ;
2013-08-08 02:44:17 -04:00
toReduce . push ( newReduction ) ;
2013-08-13 14:01:53 -04:00
} 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 } ;
2013-08-08 02:44:17 -04:00
toReduce . push ( newReduction ) ;
}
2013-07-28 19:45:08 -04:00
}
}
2013-08-08 02:44:17 -04:00
if ( reduction . length ! = 0 )
2013-08-12 00:02:50 -04:00
addChildren ( newLabel , & pathEdges , reduction . nullableParts ) ;
2013-07-28 19:45:08 -04:00
}
}
2013-07-31 23:51:05 -04:00
void RNGLRParser : : shifter ( int i ) {
if ( i ! = input . size ( ) - 1 ) {
std : : queue < std : : pair < NodeTree < int > * , int > > nextShifts ;
2013-10-02 03:15:20 -04:00
NodeTree < Symbol > * newLabel = new NodeTree < Symbol > ( " frontier: " + intToString ( i ) , input [ i ] ) ;
2013-07-28 19:45:08 -04:00
while ( ! toShift . empty ( ) ) {
2013-07-28 23:48:10 -04:00
std : : pair < NodeTree < int > * , int > shift = toShift . front ( ) ;
2013-07-31 23:51:05 -04:00
toShift . pop ( ) ;
std : : cout < < " Current potential shift from " < < shift . first - > getData ( ) < < " to " < < shift . second < < std : : endl ;
2013-07-28 23:48:10 -04:00
NodeTree < int > * shiftTo = gss . inFrontier ( i + 1 , shift . second ) ;
2013-07-28 19:45:08 -04:00
if ( shiftTo ) {
2013-08-16 00:03:26 -04:00
//std::cout << "State already existed, just adding edge" << std::endl;
2013-08-09 04:39:43 -04:00
gss . addEdge ( shiftTo , shift . first , newLabel ) ;
2013-07-31 23:51:05 -04:00
std : : vector < ParseAction * > actions = * ( table . get ( shift . second , input [ i + 1 ] ) ) ;
2013-07-28 19:45:08 -04:00
for ( std : : vector < ParseAction * > : : size_type j = 0 ; j < actions . size ( ) ; j + + ) {
2013-08-13 14:01:53 -04:00
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 } ;
2013-08-08 02:44:17 -04:00
toReduce . push ( newReduction ) ;
}
2013-07-28 19:45:08 -04:00
}
} else {
2013-08-16 00:03:26 -04:00
//std::cout << "State did not already exist, adding" << std::endl;
2013-07-28 19:45:08 -04:00
shiftTo = gss . newNode ( shift . second ) ;
gss . addToFrontier ( i + 1 , shiftTo ) ;
2013-08-08 02:44:17 -04:00
gss . addEdge ( shiftTo , shift . first , newLabel ) ;
2013-07-31 23:51:05 -04:00
std : : vector < ParseAction * > actions = * ( table . get ( shift . second , input [ i + 1 ] ) ) ;
2013-07-28 19:45:08 -04:00
for ( std : : vector < ParseAction * > : : size_type j = 0 ; j < actions . size ( ) ; j + + ) {
2013-07-31 23:51:05 -04:00
std : : cout < < " Adding action " < < actions [ j ] - > toString ( ) < < " to either nextShifts or toReduce " < < std : : endl ;
2013-07-28 19:45:08 -04:00
//Shift
2013-08-08 02:44:17 -04:00
if ( actions [ j ] - > action = = ParseAction : : SHIFT ) {
2013-07-31 23:51:05 -04:00
nextShifts . push ( std : : make_pair ( shiftTo , actions [ j ] - > shiftState ) ) ;
2013-08-13 14:01:53 -04:00
} 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 } ;
2013-08-08 02:44:17 -04:00
toReduce . push ( newReduction ) ;
2013-08-13 14:01:53 -04:00
} else if ( actions [ j ] - > action = = ParseAction : : REDUCE & & fullyReducesToNull ( actions [ j ] - > reduceRule ) ) {
2013-08-12 00:02:50 -04:00
Reduction newReduction = { shiftTo , actions [ j ] - > reduceRule - > getLeftSide ( ) , 0 , getNullableParts ( actions [ j ] - > reduceRule ) , NULL } ;
2013-08-08 02:44:17 -04:00
toReduce . push ( newReduction ) ;
}
2013-07-28 19:45:08 -04:00
}
}
}
toShift = nextShifts ;
}
2013-08-02 02:47:01 -04:00
}
2013-10-02 03:15:20 -04:00
void RNGLRParser : : addChildren ( NodeTree < Symbol > * parent , std : : vector < NodeTree < Symbol > * > * children , NodeTree < Symbol > * nullableParts ) {
2013-08-12 00:02:50 -04:00
if ( nullableParts )
children - > push_back ( nullableParts ) ;
2013-08-13 14:01:53 -04:00
2013-08-06 01:49:45 -04:00
if ( ! belongsToFamily ( parent , children ) ) {
if ( parent - > getChildren ( ) . size ( ) = = 0 ) {
parent - > addChildren ( children ) ;
} else {
if ( ! arePacked ( parent - > getChildren ( ) ) ) {
2013-10-02 03:15:20 -04:00
NodeTree < Symbol > * subParent = new NodeTree < Symbol > ( " AmbiguityPackInner " , Symbol ( " AmbiguityPackInner " , true ) ) ;
2013-08-06 01:49:45 -04:00
setPacked ( subParent , true ) ;
2013-10-02 03:15:20 -04:00
std : : vector < NodeTree < Symbol > * > tmp = parent - > getChildren ( ) ;
2013-08-09 04:39:43 -04:00
subParent - > addChildren ( & tmp ) ;
2013-08-06 01:49:45 -04:00
parent - > clearChildren ( ) ;
parent - > addChild ( subParent ) ;
}
2013-10-02 03:15:20 -04:00
NodeTree < Symbol > * t = new NodeTree < Symbol > ( " AmbiguityPackOuter " , Symbol ( " AmbiguityPackInner " , true ) ) ;
2013-08-06 01:49:45 -04:00
setPacked ( t , true ) ;
parent - > addChild ( t ) ;
t - > addChildren ( children ) ;
}
}
}
2013-10-02 03:15:20 -04:00
bool RNGLRParser : : belongsToFamily ( NodeTree < Symbol > * node , std : : vector < NodeTree < Symbol > * > * nodes ) {
2013-08-16 00:03:26 -04:00
//std::cout << "Checking " << node->getData()->toString() << "'s family" << std::endl;
2013-10-02 03:15:20 -04:00
std : : vector < NodeTree < Symbol > * > children = node - > getChildren ( ) ;
for ( std : : vector < NodeTree < Symbol > * > : : size_type i = 0 ; i < nodes - > size ( ) ; i + + ) {
2013-08-08 02:44:17 -04:00
bool containsOne = false ;
2013-10-02 03:15:20 -04:00
for ( std : : vector < NodeTree < Symbol > * > : : size_type j = 0 ; j < children . size ( ) ; j + + ) {
2013-08-09 04:39:43 -04:00
//Not sure where null comes from. For right now, just check to be sure we don't segfault
2013-09-26 15:16:58 -04:00
if ( ( * nodes ) [ i ] = = children [ j ] | | ( ( * nodes ) [ i ] ! = NULL & & children [ j ] ! = NULL & & ( * ( * nodes ) [ i ] ) = = * ( children [ j ] ) ) ) {
2013-08-08 02:44:17 -04:00
containsOne = true ;
break ;
}
}
if ( ! containsOne ) {
return false ;
}
}
return true ;
2013-08-06 01:49:45 -04:00
}
2013-10-02 03:15:20 -04:00
bool RNGLRParser : : arePacked ( std : : vector < NodeTree < Symbol > * > nodes ) {
2013-08-06 01:49:45 -04:00
bool packed = true ;
2013-10-02 03:15:20 -04:00
for ( std : : vector < NodeTree < Symbol > * > : : size_type i = 0 ; i < nodes . size ( ) ; i + + )
2013-08-09 04:39:43 -04:00
packed & = packedMap [ * ( nodes [ i ] ) ] ;
2013-08-06 01:49:45 -04:00
return packed ;
}
2013-10-02 03:15:20 -04:00
bool RNGLRParser : : isPacked ( NodeTree < Symbol > * node ) {
2013-08-09 04:39:43 -04:00
return packedMap [ * node ] ;
2013-08-06 01:49:45 -04:00
}
2013-10-02 03:15:20 -04:00
void RNGLRParser : : setPacked ( NodeTree < Symbol > * node , bool isPacked ) {
2013-08-09 04:39:43 -04:00
packedMap [ * node ] = isPacked ;
2013-08-06 01:49:45 -04:00
}
2013-08-02 02:47:01 -04:00
//Have to use own add states function in order to construct RN table instead of LALR table
2013-08-22 15:41:30 -04:00
void RNGLRParser : : addStates ( std : : vector < State * > * stateSets , State * state , std : : queue < State * > * toDo ) {
2013-08-02 02:47:01 -04:00
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 + + ) {
2013-10-02 03:15:20 -04:00
if ( newStates [ j ] - > basis [ 0 ] - > getAtIndex ( ) = = advancedRule - > getAtIndex ( ) ) {
2013-08-02 02:47:01 -04:00
symbolAlreadyInState = true ;
2013-08-16 00:03:26 -04:00
//Add rule to state, combining with idenical rule except lookahead if exists
newStates [ j ] - > addRuleCombineLookahead ( advancedRule ) ;
2013-08-02 02:47:01 -04:00
//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 ) ;
}
}
}
//Put all our new states in the set of states only if they're not already there.
bool stateAlreadyInAllStates = false ;
2013-10-02 03:15:20 -04:00
Symbol currStateSymbol ;
2013-08-02 02:47:01 -04:00
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 + + ) {
2013-08-16 00:03:26 -04:00
if ( newStates [ i ] - > basisEqualsExceptLookahead ( * ( ( * stateSets ) [ j ] ) ) ) {
2013-08-26 15:37:49 -04:00
//if (newStates[i]->basisEquals(*((*stateSets)[j]))) {
2013-08-02 02:47:01 -04:00
stateAlreadyInAllStates = true ;
//If it does exist, we should add it as the shift/goto in the action table
2013-12-18 18:05:21 -06:00
//std::cout << "newStates[" << i << "] == stateSets[" << j << "]" << std::endl;
2013-08-23 01:51:58 -04:00
if ( ! ( ( * stateSets ) [ j ] - > basisEquals ( * ( newStates [ i ] ) ) ) )
2013-08-22 15:41:30 -04:00
toDo - > push ( ( * stateSets ) [ j ] ) ;
2013-08-16 00:03:26 -04:00
( * stateSets ) [ j ] - > combineStates ( * ( newStates [ i ] ) ) ;
2013-12-18 18:05:21 -06:00
//std::cout << j << "\t Hay, doing an inside loop state reductions!" << std::endl;
2013-08-16 00:03:26 -04:00
addStateReductionsToTable ( ( * stateSets ) [ j ] ) ;
2013-08-02 02:47:01 -04:00
table . add ( stateNum ( state ) , currStateSymbol , new ParseAction ( ParseAction : : SHIFT , j ) ) ;
2013-08-26 15:37:49 -04:00
2013-08-02 02:47:01 -04:00
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 ] ) ;
2013-08-22 15:41:30 -04:00
toDo - > push ( newStates [ i ] ) ;
2013-08-02 02:47:01 -04:00
table . add ( stateNum ( state ) , currStateSymbol , new ParseAction ( ParseAction : : SHIFT , stateSets - > size ( ) - 1 ) ) ;
}
}
2013-08-16 00:03:26 -04:00
addStateReductionsToTable ( state ) ;
}
2013-08-26 15:37:49 -04:00
2013-08-16 00:03:26 -04:00
void RNGLRParser : : addStateReductionsToTable ( State * state ) {
std : : vector < ParseRule * > * currStateTotal = state - > getTotal ( ) ;
for ( std : : vector < ParseRule * > : : size_type i = 0 ; i < currStateTotal - > size ( ) ; i + + ) {
//See if reduce
//Also, this really only needs to be done for the state's basis, but we're already iterating through, so...
2013-10-02 03:15:20 -04:00
std : : vector < Symbol > * lookahead = ( * currStateTotal ) [ i ] - > getLookahead ( ) ;
2013-08-16 00:03:26 -04:00
if ( ( * currStateTotal ) [ i ] - > isAtEnd ( ) ) {
2013-12-18 18:05:21 -06:00
for ( std : : vector < Symbol > : : size_type j = 0 ; j < lookahead - > size ( ) ; j + + ) {
2013-08-16 00:03:26 -04:00
table . add ( stateNum ( state ) , ( * lookahead ) [ j ] , new ParseAction ( ParseAction : : REDUCE , ( * currStateTotal ) [ i ] ) ) ;
2013-12-18 18:05:21 -06:00
}
2013-08-16 00:03:26 -04:00
//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;
2013-08-26 15:37:49 -04:00
//It used to be that 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
2013-08-16 00:03:26 -04:00
//the part that we've already gone through in the rule. (so we don't pop extra off stack)
//Now we use the same rule and make sure that the index location is used
2013-10-02 03:15:20 -04:00
for ( std : : vector < Symbol > : : size_type j = 0 ; j < lookahead - > size ( ) ; j + + )
2013-08-16 00:03:26 -04:00
table . add ( stateNum ( state ) , ( * lookahead ) [ j ] , new ParseAction ( ParseAction : : REDUCE , ( * currStateTotal ) [ i ] ) ) ;
}
}
2013-08-02 15:21:42 -04:00
}
2013-08-13 14:01:53 -04:00
bool RNGLRParser : : fullyReducesToNull ( ParseRule * rule ) {
return rule - > getIndex ( ) = = 0 & & reducesToNull ( rule ) ;
}
2013-08-02 15:21:42 -04:00
bool RNGLRParser : : reducesToNull ( ParseRule * rule ) {
2013-10-02 03:15:20 -04:00
std : : vector < Symbol > avoidList ;
2013-08-02 15:21:42 -04:00
return reducesToNull ( rule , avoidList ) ;
}
2013-10-02 03:15:20 -04:00
bool RNGLRParser : : reducesToNull ( ParseRule * rule , std : : vector < Symbol > avoidList ) {
2013-08-12 00:02:50 -04:00
//If the rule is completed and not null, it doesn't reduce to null, it's just completed.
if ( rule - > isAtEnd ( ) & & rule - > getRightSize ( ) ! = 0 )
return false ;
2013-10-02 03:15:20 -04:00
for ( std : : vector < Symbol > : : size_type i = 0 ; i < avoidList . size ( ) ; i + + )
if ( rule - > getLeftSide ( ) = = avoidList [ i ] )
2013-08-02 15:21:42 -04:00
return false ;
avoidList . push_back ( rule - > getLeftSide ( ) ) ;
2013-10-02 03:15:20 -04:00
std : : vector < Symbol > rightSide = rule - > getRightSide ( ) ;
2013-08-02 15:21:42 -04:00
bool reduces = true ;
2013-10-02 03:15:20 -04:00
for ( std : : vector < Symbol > : : size_type i = rule - > getIndex ( ) ; i < rightSide . size ( ) ; i + + ) {
if ( rightSide [ i ] = = nullSymbol )
2013-08-02 15:21:42 -04:00
continue ;
2013-10-02 03:15:20 -04:00
if ( rightSide [ i ] . isTerminal ( ) ) {
2013-08-02 15:21:42 -04:00
reduces = false ;
break ;
}
bool subSymbolReduces = false ;
for ( std : : vector < ParseRule * > : : size_type j = 0 ; j < loadedGrammer . size ( ) ; j + + ) {
2013-10-02 03:15:20 -04:00
if ( loadedGrammer [ j ] - > getLeftSide ( ) = = rightSide [ i ] ) {
2013-08-02 15:21:42 -04:00
if ( reducesToNull ( loadedGrammer [ j ] , avoidList ) ) {
subSymbolReduces = true ;
break ;
}
}
}
if ( ! subSymbolReduces ) {
reduces = false ;
break ;
}
}
return reduces ;
}
2013-10-02 03:15:20 -04:00
NodeTree < Symbol > * RNGLRParser : : getNullableParts ( ParseRule * rule ) {
return getNullableParts ( rule , std : : vector < NodeTree < Symbol > * > ( ) ) ;
2013-08-13 14:01:53 -04:00
}
2013-10-02 03:15:20 -04:00
NodeTree < Symbol > * RNGLRParser : : getNullableParts ( ParseRule * rule , std : : vector < NodeTree < Symbol > * > avoidList ) {
2013-08-12 00:02:50 -04:00
if ( reducesToNull ( rule ) ) {
2013-08-16 00:03:26 -04:00
//std::cout << "Reduces to null so adding parts " << rule->toString() << std::endl;
2013-10-02 03:15:20 -04:00
Symbol symbol = rule - > getLeftSide ( ) ;
NodeTree < Symbol > * symbolNode = new NodeTree < Symbol > ( symbol . getName ( ) , symbol ) ;
if ( rule - > getAtNextIndex ( ) = = nullSymbol ) {
symbolNode - > addChild ( new NodeTree < Symbol > ( nullSymbol . getName ( ) , nullSymbol ) ) ;
2013-08-12 00:02:50 -04:00
} else {
2013-08-13 14:01:53 -04:00
//Find recursively
2013-08-12 00:02:50 -04:00
ParseRule * iterate = rule - > clone ( ) ;
while ( ! iterate - > isAtEnd ( ) ) {
2013-08-13 14:01:53 -04:00
//Check to see if we've done this symbol already, if so use it
2013-10-02 03:15:20 -04:00
for ( std : : vector < NodeTree < Symbol > * > : : size_type i = 0 ; i < avoidList . size ( ) ; i + + ) {
if ( iterate - > getAtNextIndex ( ) = = avoidList [ i ] - > getData ( ) ) {
2013-08-13 14:01:53 -04:00
symbolNode - > addChild ( avoidList [ i ] ) ;
break ;
}
}
//We haven't so do it recursively
for ( std : : vector < ParseRule * > : : size_type i = 0 ; i < loadedGrammer . size ( ) ; i + + ) {
2013-10-02 03:15:20 -04:00
if ( fullyReducesToNull ( loadedGrammer [ i ] ) & & iterate - > getAtNextIndex ( ) = = loadedGrammer [ i ] - > getLeftSide ( ) ) {
NodeTree < Symbol > * symbolTree = getNullableParts ( loadedGrammer [ i ] , avoidList ) ;
2013-08-13 14:01:53 -04:00
avoidList . push_back ( symbolTree ) ;
symbolNode - > addChild ( symbolTree ) ;
}
}
iterate - > advancePointer ( ) ;
2013-08-12 00:02:50 -04:00
}
}
return symbolNode ;
}
return NULL ;
2013-08-08 02:44:17 -04:00
}
2013-10-02 03:15:20 -04:00
NodeTree < Symbol > * RNGLRParser : : getNullableParts ( Symbol symbol ) {
return new NodeTree < Symbol > ( " CRAZY_SYMBOL " , nullSymbol ) ;
2013-08-08 02:44:17 -04:00
}
2013-10-02 03:15:20 -04:00
std : : vector < NodeTree < Symbol > * > RNGLRParser : : getPathEdges ( std : : vector < NodeTree < int > * > path ) {
std : : vector < NodeTree < Symbol > * > pathEdges ;
2013-08-09 04:39:43 -04:00
for ( std : : vector < NodeTree < int > * > : : size_type i = 0 ; i < path . size ( ) - 1 ; i + + )
2013-08-08 02:44:17 -04:00
pathEdges . push_back ( gss . getEdge ( path [ i ] , path [ i + 1 ] ) ) ;
return pathEdges ;
}