std::map< symbol, symbolset > grammar::reachabilitysets( ) const { std::map< symbol, symbolset > result; // Every symbol of the grammar is reachable from itself: symbolset all = allsymbols( ); for( symbolset::const_iterator p = all. begin( ); p != all. end( ); ++ p ) { result[ *p ]. insert( *p ); } // For every rule A -> B1 ... Bk, each Bi is reachable from A. for( std::vector< rule > :: const_iterator r = rules. begin( ); r != rules. end( ); ++ r ) { for( std::list< symbol > :: const_iterator p = r -> rhs. begin( ); p != r -> rhs. end( ); ++ p ) { result [ r -> lhs ]. insert( *p ); } } // And we compute the transitive closure: // If B in result[A], C in result[B] then C must be in result [A]. bool change = true; while( change ) { change = false; for( std::map< symbol, symbolset > :: iterator p = result. begin( ); p != result. end( ); ++ p ) { symbolset s; for( symbolset::const_iterator q = p -> second. begin( ); q != p -> second. end( ); ++ q ) { s. insert( result [ *q ] ); } if( p -> second. insert(s)) change = true; } } return result; }
/* tail - returns the current tail of the symbol table */ static int tail(void) { Symbol p = allsymbols(identifiers); p = up(p); if (p) return symboluid(p); else return 0; }
std::map< symbol, symbolset > grammar::firstsets( const symbolset& nullable ) const { std::map< symbol, symbolset > result; symbolset symbols = allsymbols( ); // Every symbol is in its own first set: for( symbolset::const_iterator p = symbols. begin( ); p != symbols. end( ); ++ p ) { result [ *p ]. insert( *p ); } bool change = true; while( change ) { change = false; for( std::vector< rule > :: const_iterator r = rules. begin( ); r != rules. end( ); ++ r ) { std::list< symbol > :: const_iterator pos = r -> rhs. begin( ); bool nullablebeforepos = true; while( pos != r -> rhs. end( ) && nullablebeforepos ) { bool b = result [ r -> lhs ]. insert( result [ *pos ] ); if(b) change = true; if( !nullable. contains( *pos )) nullablebeforepos = false; ++ pos; } } } return result; }