corelib/src/SRDDefinitions.cc

297 lines
6.7 KiB
C++

/******************************************************************************/
/* SRD - PARSER DEFINITIONS ***************************************************/
/******************************************************************************/
#include <lw/lib/SRDDefinitions.hh>
using namespace lw;
/*= 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 lw::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& lw::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& lw::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;
}