/******************************************************************************/ /* SRD - PARSER DEFINITIONS ***************************************************/ /******************************************************************************/ #include using namespace ebcl; /*= T_SRDEnum ================================================================*/ T_SRDEnum& T_SRDEnum::operator<< ( T_String&& word ) { if ( (*this)[ word ] != T_HashIndex::INVALID_INDEX ) { throw std::invalid_argument( "duplicate enum item" ); } const uint32_t hash( ComputeHash( word ) ); index_.add( hash ); words_.add( std::move( word ) ); return *this; } uint32_t T_SRDEnum::operator[] ( T_String const& word ) const { const uint32_t hash( ComputeHash( word ) ); uint32_t idx = index_.first( hash ); while ( idx != T_HashIndex::INVALID_INDEX ) { if ( words_[ idx ] == word ) { break; } idx = index_.next( idx ); } return idx; } uint32_t T_SRDEnum::operator[] ( char const* word ) const { const auto len = strlen( word ); const uint32_t hash( HashData( (uint8_t const*)word , len ) ); uint32_t idx = index_.first( hash ); while ( idx != T_HashIndex::INVALID_INDEX ) { auto const& w( words_[ idx ] ); if ( w.size( ) == len && !memcmp( w.data( ) , word , len ) ) { break; } idx = index_.next( idx ); } return idx; } /*= T_SRDInputItem ===========================================================*/ void ebcl::swap( T_SRDInputItem& lhs , T_SRDInputItem& rhs ) noexcept { using std::swap; swap( lhs.type_ , rhs.type_ ); swap( lhs.word_ , rhs.word_ ); swap( lhs.token_ , rhs.token_ ); swap( lhs.items_ , rhs.items_ ); swap( lhs.min_ , rhs.min_ ); swap( lhs.max_ , rhs.max_ ); } T_SRDInputItem& T_SRDInputItem::operator<< ( T_SRDInputItem item ) { if ( type_ != E_SRDInputItem::ALTERNATIVE && type_ != E_SRDInputItem::REPETITION ) { throw std::invalid_argument( "not an ALTERNATIVE or REPETITION" ); } if ( item.type( ) == type_ ) { items_.addAll( item.items( ) ); } else { items_.add( std::move( item ) ); } return *this; } /*----------------------------------------------------------------------------*/ T_StringBuilder& ebcl::operator<< ( T_StringBuilder& sb , T_SRDInputItem const& item ) { switch ( item.type( ) ) { case E_SRDInputItem::WORD: sb << item.word( ); break; case E_SRDInputItem::ENUM: sb << '[' << item.word( ) << "::*]"; break; case E_SRDInputItem::TOKEN: sb << item.token( ); break; case E_SRDInputItem::ALTERNATIVE: { auto const& alts( item.items( ) ); sb << "[ "; for ( uint32_t i = 0 ; i < alts.size( ) ; i ++ ) { if ( i != 0 ) { sb << " | "; } sb << alts[ i ]; } sb << " ]"; break; } case E_SRDInputItem::REPETITION: { auto const& seq( item.items( ) ); const bool listBits( seq.size( ) != 1 && ( item.min( ) != 1 || item.max( ) != 1 ) ); if ( listBits ) { sb << "[ "; } for ( uint32_t i = 0 ; i < seq.size( ) ; i ++ ) { if ( i != 0 ) { sb << ' '; } sb << seq[ i ]; } if ( listBits ) { if ( seq.size( ) ) { sb << ' '; } sb << ']'; } if ( item.min( ) == 0 && item.max( ) == 1 ) { sb << '?'; } else if ( item.max( ) == UINT32_MAX ) { if ( item.min( ) == 0 ) { sb << '*'; } else { if ( item.min( ) != 1 ) { sb << '{' << item.min( ); } sb << '+'; if ( item.min( ) != 1 ) { sb << '}'; } } } else if ( item.min( ) == item.max( ) && item.min( ) != 1 ) { sb << '{' << item.min( ) << '}'; } else if ( item.min( ) != item.max( ) ) { sb << '{' << item.min( ) << ',' << item.max( ) << '}'; } break; } } return sb; } /*= T_SRDInputRule ===========================================================*/ T_SRDInputRule& T_SRDInputRule::operator<< ( T_SRDInputItem item ) { items_.add( std::move( item ) ); return *this; } T_StringBuilder& ebcl::operator<< ( T_StringBuilder& sb , T_SRDInputRule const& item ) { auto const& seq( item.rule( ) ); sb << '('; for ( uint32_t i = 0 ; i < seq.size( ) ; i ++ ) { sb << ' ' << seq[ i ]; } if ( item.context( ) ) { sb << " ..." << item.context( ) << "..."; } sb << " )"; return sb; } /*= T_SRDContext =============================================================*/ T_SRDContext::T_SRDContext( T_String name , T_String parent ) : name_( std::move( name ) ) , parent_( std::move( parent ) ) , rules_( 16 ) { } T_SRDContext& T_SRDContext::operator<< ( T_SRDInputRule rule ) { rules_.add( std::move( rule ) ); return *this; } T_StringBuilder& T_SRDContext::dump( T_StringBuilder& sb , T_String const& separator ) { const auto nr( rules_.size( ) ); for ( uint32_t i = 0 ; i < nr ; i ++ ) { if ( i > 0 ) { sb << separator; } sb << rules_[ i ]; } return sb; } /*= T_SRDParserDefs ==========================================================*/ T_SRDParserDefs::T_SRDParserDefs( T_String defaultContext ) : dfCtx_( std::move( defaultContext ) ) , ctx_( []( T_SRDContext const& c ) -> T_String const& { return c.name( ); } , 64 , 64 , 64 ) , enums_( []( T_SRDEnum const& e ) -> T_String const& { return e.name( ); } , 64 , 64 , 64 ) { ctx_.add( T_SRDContext( dfCtx_ ) ); } /*----------------------------------------------------------------------------*/ void T_SRDParserDefs::defaultContext( T_String const& name ) { if ( name == dfCtx_ ) { return; } if ( !ctx_.contains( name ) ) { throw std::invalid_argument( "default context must exist" ); } dfCtx_ = name; } uint32_t T_SRDParserDefs::contextId( T_String const& name ) const { return ctx_.indexOf( name ); } T_SRDParserDefs& T_SRDParserDefs::operator<< ( SetHandler sh ) { if ( sh.start ) { onStart_ = sh.handler; } else { onFinish_ = sh.handler; } return *this; } T_SRDContext& T_SRDParserDefs::context( T_String const& name ) { if ( !ctx_.contains( name ) ) { ctx_.add( T_SRDContext( name ) ); } return *( ctx_.get( name ) ); } T_SRDContext& T_SRDParserDefs::context( T_String const& name , T_String const& parent ) { if ( !ctx_.contains( name ) ) { ctx_.add( T_SRDContext( name , parent ) ); } T_SRDContext& c( *( ctx_.get( name ) ) ); if ( c.parent( ) != parent ) { throw std::invalid_argument( "incorrect parent name" ); } return c; } /*----------------------------------------------------------------------------*/ bool T_SRDParserDefs::hasEnum( T_String const& name ) const { return enums_.contains( name ); } T_SRDEnum& T_SRDParserDefs::enumeration( T_String const& name ) { if ( !enums_.contains( name ) ) { enums_.add( T_SRDEnum( name ) ); } return *( enums_.get( name ) ); } T_SRDEnum const& T_SRDParserDefs::enumeration( T_String const& name ) const { auto eptr( enums_.get( name ) ); if ( eptr == nullptr ) { throw std::invalid_argument( "unknown enum" ); } return *eptr; }