Use a vector of active GrammarStates to track new states

The previous algorithm would loop through all states but only process
those that didn't have their processed flag set.  Much faster to only
iterate through those states that haven't been processed.
This commit is contained in:
Charles Baker 2023-05-21 21:15:38 +12:00
parent ebe173cb12
commit 9d90804ae2
4 changed files with 30 additions and 58 deletions

View file

@ -326,7 +326,7 @@ void GrammarGenerator::closure( const std::shared_ptr<GrammarState>& state )
// @return
// The goto state generated when accepting \e symbol from \e state.
*/
std::shared_ptr<GrammarState> GrammarGenerator::goto_( const std::shared_ptr<GrammarState>& state, const GrammarSymbol& symbol )
std::shared_ptr<GrammarState> GrammarGenerator::goto_( const GrammarState* state, const GrammarSymbol& symbol )
{
LALR_ASSERT( state );
@ -853,38 +853,39 @@ void GrammarGenerator::generate_states( const GrammarSymbol* start_symbol, const
closure( start_state );
states_.insert( start_state );
start_state_ = start_state.get();
int added = 1;
{
while ( added > 0 )
{
added = 0;
for ( set<shared_ptr<GrammarState>, GrammarStateLess>::const_iterator i = states_.begin(); i != states_.end(); ++i )
{
const shared_ptr<GrammarState>& state = *i;
LALR_ASSERT( state );
if ( !state->processed() )
{
vector<GrammarState*> next_states;
vector<GrammarState*> states;
states.push_back( start_state_ );
while ( !states.empty() )
{
for ( GrammarState* state : states )
{
for ( vector<unique_ptr<GrammarSymbol>>::const_iterator j = symbols.begin(); j != symbols.end(); ++j )
{
state->set_processed( true );
for ( vector<unique_ptr<GrammarSymbol>>::const_iterator j = symbols.begin(); j != symbols.end(); ++j )
GrammarSymbol* symbol = j->get();
LALR_ASSERT( symbol );
if ( symbol != end_symbol )
{
GrammarSymbol* symbol = j->get();
LALR_ASSERT( symbol );
if ( symbol != end_symbol )
std::shared_ptr<GrammarState> goto_state = goto_( state, *symbol );
if ( goto_state )
{
std::shared_ptr<GrammarState> goto_state = goto_( state, *symbol );
if ( goto_state )
LALR_ASSERT( !goto_state->items().empty() );
std::shared_ptr<GrammarState> actual_goto_state = *states_.insert( goto_state ).first;
if ( goto_state == actual_goto_state )
{
LALR_ASSERT( !goto_state->items().empty() );
std::shared_ptr<GrammarState> actual_goto_state = *states_.insert( goto_state ).first;
added += goto_state == actual_goto_state ? 1 : 0;
state->add_shift_transition( shift_transition(symbol, actual_goto_state.get()) );
next_states.push_back( goto_state.get() );
}
state->add_shift_transition( shift_transition(symbol, actual_goto_state.get()) );
}
}
}
}
states.clear();
next_states.swap( states );
}
}

View file

@ -69,7 +69,7 @@ private:
GrammarTransition* reduce_transition( const GrammarSymbol* symbol, const GrammarProduction* production );
GrammarSymbolSet spontaneous_lookaheads( const GrammarItem& item ) const;
void closure( const std::shared_ptr<GrammarState>& state );
std::shared_ptr<GrammarState> goto_( const std::shared_ptr<GrammarState>& state, const GrammarSymbol& symbol );
std::shared_ptr<GrammarState> goto_( const GrammarState* state, const GrammarSymbol& symbol );
void replace_references_to_symbol( GrammarSymbol* to_symbol, GrammarSymbol* with_symbol );
void check_for_undefined_symbol_errors();
void check_for_unreferenced_symbol_errors();

View file

@ -22,7 +22,6 @@ GrammarState::GrammarState()
: items_()
, transitions_by_symbol_index_()
, transitions_()
, processed_( false )
, index_( INVALID_INDEX )
{
}
@ -31,13 +30,11 @@ GrammarState::GrammarState( GrammarState&& state )
: items_()
, transitions_by_symbol_index_()
, transitions_()
, processed_( false )
, index_( INVALID_INDEX )
{
std::swap( items_, state.items_ );
std::swap( transitions_by_symbol_index_, state.transitions_by_symbol_index_ );
std::swap( transitions_, state.transitions_ );
std::swap( processed_, state.processed_ );
std::swap( index_, state.index_ );
}
@ -45,7 +42,6 @@ GrammarState::GrammarState( const GrammarState& state )
: items_( state.items_ )
, transitions_by_symbol_index_( state.transitions_by_symbol_index_ )
, transitions_( state.transitions_ )
, processed_( state.processed_ )
, index_( state.index_ )
{
}
@ -76,10 +72,10 @@ GrammarItem* GrammarState::find_item( GrammarProduction* production, int positio
// @return
// The items.
*/
// const std::set<GrammarItem>& GrammarState::items() const
// {
// return items_;
// }
const std::set<GrammarItem>& GrammarState::items() const
{
return items_;
}
/**
// Find a transition on \e symbol from this state.
@ -127,17 +123,6 @@ int GrammarState::count_valid_transitions() const
return valid_transitions;
}
/**
// Has this state been processed?
//
// @return
// True if this state has been processed otherwise false.
*/
bool GrammarState::processed() const
{
return processed_;
}
/**
// Get the index of this state.
//
@ -247,17 +232,6 @@ GrammarTransition* GrammarState::find_transition_by_symbol( const GrammarSymbol*
return nullptr;
}
/**
// Set this state as having been processed.
//
// @param processed
// True to mark this state as processed or false to mark it as not processed.
*/
void GrammarState::set_processed( bool processed )
{
processed_ = processed;
}
/**
// Set the index of this state.
//

View file

@ -21,7 +21,6 @@ class GrammarState
std::set<GrammarItem> items_; ///< The items that define the positions within the grammar that this state represents.
std::vector<GrammarTransition*> transitions_by_symbol_index_; ///< Transitions from this state by symbol index.
std::vector<GrammarTransition*> transitions_; ///< Transitions from this state.
bool processed_; ///< True if this state has been processed during state machine generation otherwise false.
int index_; ///< The index of this state.
public:
@ -30,12 +29,11 @@ public:
GrammarState( const GrammarState& state );
GrammarItem* find_item( GrammarProduction* production, int position ) const;
const std::set<GrammarItem>& items() const { return items_; }
const std::set<GrammarItem>& items() const;
const GrammarTransition* find_transition_by_symbol( const GrammarSymbol* symbol ) const;
const std::vector<GrammarTransition*>& transitions() const;
int count_valid_transitions() const;
std::string label() const;
bool processed() const;
int index() const;
bool operator<( const GrammarState& state ) const;
@ -43,7 +41,6 @@ public:
void add_shift_transition( GrammarTransition* transition );
void add_reduce_transition( GrammarTransition* transition );
GrammarTransition* find_transition_by_symbol( const GrammarSymbol* symbol );
void set_processed( bool processed );
void set_index( int index );
static const int INVALID_INDEX = -1;