297 lines
6.7 KiB
C++
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;
|
|
}
|