mirror of
https://github.com/Ed94/gencpp.git
synced 2024-11-10 02:54:53 -08:00
Somehow overlooked unions... More stuff on parser constructors
This commit is contained in:
parent
d541b33b22
commit
38a60e4b91
@ -156,7 +156,7 @@ struct ArrayHeader
|
|||||||
|
|
||||||
## Gen's DSL
|
## Gen's DSL
|
||||||
|
|
||||||
If you don't mind a low amount of macros (61 sloc), a DSL may be optionally defined with:
|
If you don't mind a low amount of macros (~80 sloc), a DSL may be optionally defined with:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
GEN_DEFINE_DSL
|
GEN_DEFINE_DSL
|
||||||
|
609
project/gen.cpp
609
project/gen.cpp
@ -2017,6 +2017,34 @@ namespace gen
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Code def_union( s32 length, char const* name, Code body )
|
||||||
|
{
|
||||||
|
name_check( def_union, length, name );
|
||||||
|
|
||||||
|
if ( body && body->Type != ECode::Union_Body )
|
||||||
|
{
|
||||||
|
log_failure( "gen::def_union: body was not a Union_Body type" );
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code
|
||||||
|
result = make_code();
|
||||||
|
result->Name = get_cached_string( name, length );
|
||||||
|
|
||||||
|
if ( body )
|
||||||
|
{
|
||||||
|
result->Type = ECode::Union;
|
||||||
|
result->add_entry( body );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result->Type = ECode::Union_Fwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.lock();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Code def_using( u32 length, char const* name, Code type, UsingT specifier )
|
Code def_using( u32 length, char const* name, Code type, UsingT specifier )
|
||||||
{
|
{
|
||||||
name_check( def_using, length, name );
|
name_check( def_using, length, name );
|
||||||
@ -2201,7 +2229,7 @@ namespace gen
|
|||||||
|
|
||||||
Code
|
Code
|
||||||
result = make_code();
|
result = make_code();
|
||||||
result->Type = Class_Body;
|
result->Type = Enum_Body;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -2529,6 +2557,73 @@ namespace gen
|
|||||||
result.lock();
|
result.lock();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Code def_union_body( s32 num, ... )
|
||||||
|
{
|
||||||
|
def_body_start( def_union_body );
|
||||||
|
|
||||||
|
Code
|
||||||
|
result = make_code();
|
||||||
|
result->Type = Union_Body;
|
||||||
|
|
||||||
|
va_list va;
|
||||||
|
va_start(va, num);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Code entry = va_arg(va, Code);
|
||||||
|
|
||||||
|
if ( ! entry )
|
||||||
|
{
|
||||||
|
log_failure("gen::def_union_body: Provided a null entry");
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( entry->Type != Untyped )
|
||||||
|
{
|
||||||
|
log_failure("gen::def_union_body: Entry type is not allowed - %s. Must be of untyped type.", entry->debug_str() ); \
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
result->add_entry( entry );
|
||||||
|
}
|
||||||
|
while ( num--, num > 0 );
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
result.lock();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code def_union_body( s32 num, Code* codes )
|
||||||
|
{
|
||||||
|
def_body_code_array_start( def_union_body );
|
||||||
|
|
||||||
|
Code
|
||||||
|
result = make_code();
|
||||||
|
result->Type = Union_Body;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Code entry = *codes;
|
||||||
|
|
||||||
|
if ( ! entry )
|
||||||
|
{
|
||||||
|
log_failure("gen::def_union_body: Provided a null entry");
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( entry->Type != Untyped )
|
||||||
|
{
|
||||||
|
log_failure("gen::def_union_body: Entry type is not allowed: %s", entry->debug_str() ); \
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
result->add_entry( entry );
|
||||||
|
}
|
||||||
|
while ( codes++, num--, num > 0 );
|
||||||
|
|
||||||
|
result.lock();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#pragma endregion Upfront Constructors
|
#pragma endregion Upfront Constructors
|
||||||
|
|
||||||
#pragma region Incremetnal Constructors
|
#pragma region Incremetnal Constructors
|
||||||
@ -3389,13 +3484,21 @@ namespace gen
|
|||||||
}
|
}
|
||||||
|
|
||||||
# define currtok toks.Arr[toks.Idx]
|
# define currtok toks.Arr[toks.Idx]
|
||||||
# define eat( Type_ ) toks.__eat( Type_, txt(context) )
|
# define eat( Type_ ) toks.__eat( Type_, context )
|
||||||
# define left array_count(toks.Arr) - toks.Idx
|
# define left array_count(toks.Arr) - toks.Idx
|
||||||
|
|
||||||
# define check( Type_ ) left && currtok.Type == Type_
|
# define check( Type_ ) left && currtok.Type == Type_
|
||||||
#pragma endregion Helper Macros
|
#pragma endregion Helper Macros
|
||||||
|
Code parse_class ( Parser::TokArray& toks, char const* context );
|
||||||
Code parse_type( Parser::TokArray& toks, char const* func_name );
|
Code parse_enum ( Parser::TokArray& toks, char const* context );
|
||||||
|
Code parse_friend ( Parser::TokArray& toks, char const* context );
|
||||||
|
Code parse_function( Parser::TokArray& toks, char const* context );
|
||||||
|
Code parse_struct ( Parser::TokArray& toks, char const* context );
|
||||||
|
Code parse_variable( Parser::TokArray& toks, char const* context );
|
||||||
|
Code parse_type ( Parser::TokArray& toks, char const* context );
|
||||||
|
Code parse_typedef ( Parser::TokArray& toks, char const* context );
|
||||||
|
Code parse_union ( Parser::TokArray& toks, char const* context );
|
||||||
|
Code parse_using ( Parser::TokArray& toks, char const* context );
|
||||||
|
|
||||||
inline
|
inline
|
||||||
Code parse_array_decl( Parser::TokArray& toks, char const* func_name )
|
Code parse_array_decl( Parser::TokArray& toks, char const* func_name )
|
||||||
@ -3549,43 +3652,215 @@ namespace gen
|
|||||||
# undef context
|
# undef context
|
||||||
}
|
}
|
||||||
|
|
||||||
Code parse_class( s32 length, char const* def )
|
Code parse_class_struct_body( Parser::TokArray& toks, char const* context )
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
# define context parse_class
|
eat( TokType::BraceCurly_Open );
|
||||||
|
|
||||||
TokArray toks = lex( length, def );
|
Code
|
||||||
if ( toks.Arr == nullptr )
|
result = make_code();
|
||||||
|
result->Type = Class_Body;
|
||||||
|
|
||||||
|
while ( left && currtok.Type != TokType::BraceCurly_Close )
|
||||||
|
{
|
||||||
|
Code member = Code::Invalid;
|
||||||
|
|
||||||
|
switch ( currtok.Type )
|
||||||
|
{
|
||||||
|
case TokType::Comment:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Access_Public:
|
||||||
|
case TokType::Access_Protected:
|
||||||
|
case TokType::Access_Private:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Class:
|
||||||
|
member = parse_class( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Enum:
|
||||||
|
member = parse_enum( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Friend:
|
||||||
|
member = parse_friend( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Struct:
|
||||||
|
member = parse_struct( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Typedef:
|
||||||
|
member = parse_typedef( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Union:
|
||||||
|
member = parse_variable( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Using:
|
||||||
|
member = parse_using( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Identifier:
|
||||||
|
case TokType::Spec_Const:
|
||||||
|
case TokType::Spec_Consteval:
|
||||||
|
case TokType::Spec_Constexpr:
|
||||||
|
case TokType::Spec_Constinit:
|
||||||
|
case TokType::Spec_Inline:
|
||||||
|
case TokType::Spec_Static:
|
||||||
|
case TokType::Spec_ThreadLocal:
|
||||||
|
case TokType::Spec_Volatile:
|
||||||
|
case TokType::Type_Unsigned:
|
||||||
|
case TokType::Type_Signed:
|
||||||
|
case TokType::Type_Short:
|
||||||
|
case TokType::Type_Long:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( member == Code::Invalid )
|
||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
|
|
||||||
|
result->add_entry( member );
|
||||||
|
|
||||||
|
eat( currtok.Type );
|
||||||
|
}
|
||||||
|
|
||||||
|
eat( TokType::BraceCurly_Close );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_function_body( Parser::TokArray& toks, char const* context )
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
|
eat( TokType::BraceCurly_Open );
|
||||||
|
|
||||||
|
Code
|
||||||
|
result = make_code();
|
||||||
|
result->Type = Function_Body;
|
||||||
|
|
||||||
|
while ( left && currtok.Type != TokType::BraceCurly_Close )
|
||||||
|
{
|
||||||
|
Code member = Code::Invalid;
|
||||||
|
|
||||||
|
switch ( currtok.Type )
|
||||||
|
{
|
||||||
|
case TokType::Comment:
|
||||||
|
// TODO: Add comment to function body?
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Class:
|
||||||
|
member = parse_class( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Enum:
|
||||||
|
member = parse_enum( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Struct:
|
||||||
|
member = parse_struct( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Typedef:
|
||||||
|
member = parse_typedef( toks, context );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Union:
|
||||||
|
member = parse_union( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Decl_Using:
|
||||||
|
member = parse_using( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Identifier:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Spec_Const:
|
||||||
|
case TokType::Spec_Constexpr:
|
||||||
|
case TokType::Spec_Constinit:
|
||||||
|
case TokType::Spec_Static:
|
||||||
|
case TokType::Spec_ThreadLocal:
|
||||||
|
case TokType::Spec_Volatile:
|
||||||
|
// Can be all kinds of crap
|
||||||
|
|
||||||
|
case TokType::Type_Unsigned:
|
||||||
|
case TokType::Type_Signed:
|
||||||
|
case TokType::Type_Short:
|
||||||
|
case TokType::Type_Long:
|
||||||
|
member = parse_variable( toks, context );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Spec_API:
|
||||||
|
log_failure( "gen::%s: %s not allowed in function body", context, str_tok_type( currtok.Type ) );
|
||||||
|
return Code::Invalid;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Token untyped_tok = currtok;
|
||||||
|
|
||||||
|
while ( left && currtok.Type != TokType::Statement_End )
|
||||||
|
{
|
||||||
|
untyped_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)untyped_tok.Text;
|
||||||
|
eat( currtok.Type );
|
||||||
|
}
|
||||||
|
|
||||||
|
Code member = untyped_str( untyped_tok.Length, untyped_tok.Text );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( member == Code::Invalid )
|
||||||
|
return Code::Invalid;
|
||||||
|
|
||||||
|
result->add_entry( member );
|
||||||
|
|
||||||
|
eat( currtok.Type );
|
||||||
|
}
|
||||||
|
|
||||||
|
eat( TokType::BraceCurly_Close );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_class( Parser::TokArray& toks, char const* context )
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
|
||||||
Token name { nullptr, 0, TokType::Invalid };
|
Token name { nullptr, 0, TokType::Invalid };
|
||||||
|
|
||||||
Code parent = { nullptr };
|
Code parent = { nullptr };
|
||||||
Code speciifes = { nullptr };
|
Code speciifes = { nullptr };
|
||||||
Code body = { nullptr };
|
Code body = { nullptr };
|
||||||
|
|
||||||
do
|
Code result = Code::Invalid;
|
||||||
{
|
|
||||||
|
|
||||||
}
|
eat( TokType::Decl_Class );
|
||||||
while ( left--, left > 0 );
|
|
||||||
|
|
||||||
return Code::Invalid;
|
not_implemented();
|
||||||
# undef context
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Code parse_enum( s32 length, char const* def )
|
Code parse_class( s32 length, char const* def )
|
||||||
{
|
{
|
||||||
|
# define context txt(parse_class)
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
|
||||||
# define context parse_enum
|
|
||||||
check_parse_args( parse_enum, length, def );
|
|
||||||
|
|
||||||
TokArray toks = lex( length, def );
|
TokArray toks = lex( length, def );
|
||||||
if ( toks.Arr == nullptr )
|
if ( toks.Arr == nullptr )
|
||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
|
|
||||||
|
return parse_class( toks, context );
|
||||||
|
# undef context
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_enum( Parser::TokArray& toks, char const* context )
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
|
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
|
||||||
s32 num_specifiers = 0;
|
s32 num_specifiers = 0;
|
||||||
|
|
||||||
@ -3671,21 +3946,28 @@ namespace gen
|
|||||||
|
|
||||||
result.lock();
|
result.lock();
|
||||||
return result;
|
return result;
|
||||||
# undef context
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Code parse_friend( s32 length, char const* def )
|
Code parse_enum( s32 length, char const* def )
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
using namespace ECode;
|
|
||||||
|
|
||||||
# define context parse_friend
|
# define context parse_enum
|
||||||
check_parse_args( parse_friend, length, def );
|
check_parse_args( parse_enum, length, def );
|
||||||
|
|
||||||
TokArray toks = lex( length, def );
|
TokArray toks = lex( length, def );
|
||||||
if ( toks.Arr == nullptr )
|
if ( toks.Arr == nullptr )
|
||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
|
|
||||||
|
return parse_enum( toks, txt(parse_enum) );
|
||||||
|
# undef context
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_friend( Parser::TokArray& toks, char const* context )
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
eat( TokType::Decl_Friend );
|
eat( TokType::Decl_Friend );
|
||||||
|
|
||||||
Code function = { nullptr };
|
Code function = { nullptr };
|
||||||
@ -3731,9 +4013,165 @@ namespace gen
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Code parse_friend( s32 length, char const* def )
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
|
# define context parse_friend
|
||||||
|
check_parse_args( parse_friend, length, def );
|
||||||
|
|
||||||
|
TokArray toks = lex( length, def );
|
||||||
|
if ( toks.Arr == nullptr )
|
||||||
|
return Code::Invalid;
|
||||||
|
|
||||||
|
return parse_friend( toks, txt(parse_friend) );
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_global_body( Parser::TokArray& toks, char const* context )
|
||||||
|
{
|
||||||
|
not_implemented();
|
||||||
|
}
|
||||||
|
|
||||||
Code parse_global_body( s32 length, char const* def )
|
Code parse_global_body( s32 length, char const* def )
|
||||||
{
|
{
|
||||||
not_implemented( parse_global_body );
|
using namespace Parser;
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
|
Code result = make_code();
|
||||||
|
result->Type = Global_Body;
|
||||||
|
|
||||||
|
while ( left )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
result.lock();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_functon( Parser::TokArray& toks, char const* context )
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
|
||||||
|
// TODO: Add attribute parsing support
|
||||||
|
|
||||||
|
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
|
||||||
|
s32 num_specifiers = 0;
|
||||||
|
|
||||||
|
Code lang_linkage = Code::Invalid;
|
||||||
|
Code attributes = Code::Invalid;
|
||||||
|
Code array_expr = Code::Invalid;
|
||||||
|
Code specifiers = Code::Invalid;
|
||||||
|
|
||||||
|
while ( left && tok_is_specifier( currtok ) )
|
||||||
|
{
|
||||||
|
SpecifierT spec = ESpecifier::to_type( currtok.Text, currtok.Length );
|
||||||
|
|
||||||
|
switch ( spec )
|
||||||
|
{
|
||||||
|
case ESpecifier::Constexpr:
|
||||||
|
case ESpecifier::Export:
|
||||||
|
case ESpecifier::External_Linkage:
|
||||||
|
case ESpecifier::Import:
|
||||||
|
case ESpecifier::Local_Persist:
|
||||||
|
case ESpecifier::Mutable:
|
||||||
|
case ESpecifier::Static_Member:
|
||||||
|
case ESpecifier::Thread_Local:
|
||||||
|
case ESpecifier::Volatile:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log_failure( "gen::parse_variable: invalid specifier " txt(spec) " for variable" );
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( spec == ESpecifier::External_Linkage )
|
||||||
|
{
|
||||||
|
specs_found[num_specifiers] = spec;
|
||||||
|
num_specifiers++;
|
||||||
|
eat( TokType::Spec_Extern );
|
||||||
|
|
||||||
|
if ( currtok.Type == TokType::String )
|
||||||
|
{
|
||||||
|
lang_linkage = untyped_str( currtok.Length, currtok.Text );
|
||||||
|
eat( TokType::String );
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
specs_found[num_specifiers] = spec;
|
||||||
|
num_specifiers++;
|
||||||
|
eat( currtok.Type );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( num_specifiers )
|
||||||
|
{
|
||||||
|
specifiers = def_specifiers( num_specifiers, specs_found );
|
||||||
|
}
|
||||||
|
|
||||||
|
Code ret_type = parse_type( toks, txt(parse_function) );
|
||||||
|
if ( ret_type == Code::Invalid )
|
||||||
|
return Code::Invalid;
|
||||||
|
|
||||||
|
Token name = parse_identifier( toks, txt(parse_function) );
|
||||||
|
if ( ! name )
|
||||||
|
return Code::Invalid;
|
||||||
|
|
||||||
|
Code params = parse_params( toks, txt(parse_function) );
|
||||||
|
|
||||||
|
Code body = Code::Invalid;
|
||||||
|
if ( check( TokType::BraceCurly_Open ) )
|
||||||
|
{
|
||||||
|
body = parse_function_body( toks, txt(parse_function) );
|
||||||
|
if ( body == Code::Invalid )
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eat( TokType::Statement_End );
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
|
Code
|
||||||
|
result = make_code();
|
||||||
|
result->Name = get_cached_string( name.Text, name.Length );
|
||||||
|
|
||||||
|
if ( body )
|
||||||
|
{
|
||||||
|
switch ( body->Type )
|
||||||
|
{
|
||||||
|
case Function_Body:
|
||||||
|
case Untyped:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
log_failure("gen::def_function: body must be either of Function_Body or Untyped type. %s", body->debug_str());
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result->Type = Function;
|
||||||
|
result->add_entry( body );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result->Type = Function_Fwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( specifiers )
|
||||||
|
result->add_entry( specifiers );
|
||||||
|
|
||||||
|
result->add_entry( ret_type );
|
||||||
|
|
||||||
|
if ( params )
|
||||||
|
result->add_entry( params );
|
||||||
|
|
||||||
|
result.lock();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Code parse_function( s32 length, char const* def )
|
Code parse_function( s32 length, char const* def )
|
||||||
@ -3747,15 +4185,16 @@ namespace gen
|
|||||||
arena_init_from_allocator( & mem, heap(), kilobytes( 10 ) );
|
arena_init_from_allocator( & mem, heap(), kilobytes( 10 ) );
|
||||||
do_once_end
|
do_once_end
|
||||||
|
|
||||||
|
TokArray toks = lex( length, def );
|
||||||
|
if ( toks.Arr == nullptr )
|
||||||
|
return Code::Invalid;
|
||||||
|
|
||||||
|
return parse_functon( toks, txt(parse_function) );
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_namespace( Parser::TokArray& toks, char const* context )
|
||||||
Code
|
{
|
||||||
result = make_code();
|
not_implemented();
|
||||||
|
|
||||||
|
|
||||||
result.lock();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Code parse_namespace( s32 length, char const* def )
|
Code parse_namespace( s32 length, char const* def )
|
||||||
@ -3763,11 +4202,21 @@ namespace gen
|
|||||||
not_implemented( parse_namespace );
|
not_implemented( parse_namespace );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Code parse_operator( Parser::TokArray& toks, char const* context )
|
||||||
|
{
|
||||||
|
not_implemented();
|
||||||
|
}
|
||||||
|
|
||||||
Code parse_operator( s32 length, char const* def )
|
Code parse_operator( s32 length, char const* def )
|
||||||
{
|
{
|
||||||
not_implemented( parse_operator );
|
not_implemented( parse_operator );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Code parse_struct( Parser::TokArray& toks, char const* context )
|
||||||
|
{
|
||||||
|
not_implemented();
|
||||||
|
}
|
||||||
|
|
||||||
Code parse_struct( s32 length, char const* def )
|
Code parse_struct( s32 length, char const* def )
|
||||||
{
|
{
|
||||||
Arena mem;
|
Arena mem;
|
||||||
@ -3789,25 +4238,19 @@ namespace gen
|
|||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
Code parse_variable( s32 length, char const* def )
|
Code parse_variable( Parser::TokArray& toks, char const* context )
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
|
||||||
# define context parse_variable
|
|
||||||
check_parse_args( parse_variable, length, def );
|
|
||||||
|
|
||||||
TokArray toks = lex( length, def );
|
|
||||||
if ( toks.Arr == nullptr )
|
|
||||||
return Code::Invalid;
|
|
||||||
|
|
||||||
Token name = { nullptr, 0, TokType::Invalid };
|
Token name = { nullptr, 0, TokType::Invalid };
|
||||||
|
|
||||||
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
|
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
|
||||||
s32 num_specifiers = 0;
|
s32 num_specifiers = 0;
|
||||||
|
|
||||||
Code lang_linkage;
|
Code lang_linkage = Code::Invalid;
|
||||||
Code attributes;
|
Code attributes = Code::Invalid;
|
||||||
Code array_expr = { nullptr };
|
Code array_expr = Code::Invalid;
|
||||||
|
Code specifiers = Code::Invalid;
|
||||||
|
|
||||||
if ( check( TokType::BraceSquare_Open ) )
|
if ( check( TokType::BraceSquare_Open ) )
|
||||||
{
|
{
|
||||||
@ -3872,6 +4315,11 @@ namespace gen
|
|||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( num_specifiers )
|
||||||
|
{
|
||||||
|
specifiers = def_specifiers( num_specifiers, specs_found );
|
||||||
|
}
|
||||||
|
|
||||||
Code type = parse_type( toks, txt(parse_variable) );
|
Code type = parse_type( toks, txt(parse_variable) );
|
||||||
|
|
||||||
if ( type == Code::Invalid )
|
if ( type == Code::Invalid )
|
||||||
@ -3886,7 +4334,7 @@ namespace gen
|
|||||||
name = currtok;
|
name = currtok;
|
||||||
eat( TokType::Identifier );
|
eat( TokType::Identifier );
|
||||||
|
|
||||||
Code expr = { nullptr };
|
Code expr = Code::Invalid;
|
||||||
|
|
||||||
if ( currtok.IsAssign )
|
if ( currtok.IsAssign )
|
||||||
{
|
{
|
||||||
@ -3927,10 +4375,28 @@ namespace gen
|
|||||||
if ( attributes )
|
if ( attributes )
|
||||||
result->add_entry( attributes );
|
result->add_entry( attributes );
|
||||||
|
|
||||||
|
if (specifiers)
|
||||||
|
result->add_entry( specifiers );
|
||||||
|
|
||||||
if ( expr )
|
if ( expr )
|
||||||
result->add_entry( expr );
|
result->add_entry( expr );
|
||||||
|
|
||||||
|
result.lock();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_variable( s32 length, char const* def )
|
||||||
|
{
|
||||||
|
# define context txt(parse_variable)
|
||||||
|
using namespace Parser;
|
||||||
|
|
||||||
|
check_parse_args( parse_variable, length, def );
|
||||||
|
|
||||||
|
TokArray toks = lex( length, def );
|
||||||
|
if ( toks.Arr == nullptr )
|
||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
|
|
||||||
|
return parse_variable( toks, txt(parse_variable) );
|
||||||
# undef context
|
# undef context
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4040,17 +4506,10 @@ namespace gen
|
|||||||
# undef context
|
# undef context
|
||||||
}
|
}
|
||||||
|
|
||||||
Code parse_typedef( s32 length, char const* def )
|
Code parse_typedef( Parser::TokArray& toks, char const* context )
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
|
||||||
# define context parse_typedef
|
|
||||||
check_parse_args( parse_typedef, length, def );
|
|
||||||
|
|
||||||
TokArray toks = lex( length, def );
|
|
||||||
if ( toks.Arr == nullptr )
|
|
||||||
return Code::Invalid;
|
|
||||||
|
|
||||||
Token name = { nullptr, 0, TokType::Invalid };
|
Token name = { nullptr, 0, TokType::Invalid };
|
||||||
Code array_expr = { nullptr };
|
Code array_expr = { nullptr };
|
||||||
Code type = { nullptr };
|
Code type = { nullptr };
|
||||||
@ -4086,20 +4545,41 @@ namespace gen
|
|||||||
|
|
||||||
result.lock();
|
result.lock();
|
||||||
return result;
|
return result;
|
||||||
# undef context
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Code parse_using( s32 length, char const* def )
|
Code parse_typedef( s32 length, char const* def )
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
|
||||||
# define context parse_using
|
# define context parse_typedef
|
||||||
check_parse_args( parse_using, length, def );
|
check_parse_args( parse_typedef, length, def );
|
||||||
|
|
||||||
TokArray toks = lex( length, def );
|
TokArray toks = lex( length, def );
|
||||||
if ( toks.Arr == nullptr )
|
if ( toks.Arr == nullptr )
|
||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
|
|
||||||
|
return parse_typedef( toks, txt(parse_typedef) );
|
||||||
|
# undef context
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_union( Parser::TokArray& toks, char const* context )
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_union( s32 length, char const* def )
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_using( Parser::TokArray& toks, char const* context )
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
|
||||||
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
|
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
|
||||||
s32 num_specifiers = 0;
|
s32 num_specifiers = 0;
|
||||||
|
|
||||||
@ -4144,6 +4624,20 @@ namespace gen
|
|||||||
|
|
||||||
result.lock();
|
result.lock();
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_using( s32 length, char const* def )
|
||||||
|
{
|
||||||
|
# define context parse_using
|
||||||
|
using namespace Parser;
|
||||||
|
|
||||||
|
check_parse_args( parse_using, length, def );
|
||||||
|
|
||||||
|
TokArray toks = lex( length, def );
|
||||||
|
if ( toks.Arr == nullptr )
|
||||||
|
return Code::Invalid;
|
||||||
|
|
||||||
|
return parse_using( toks, txt(parse_using) );
|
||||||
# undef context
|
# undef context
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4192,6 +4686,11 @@ namespace gen
|
|||||||
not_implemented( parse_typedefs );
|
not_implemented( parse_typedefs );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 parse_unions( s32 length, char const* union_defs, Code* out_union_codes )
|
||||||
|
{
|
||||||
|
not_implemented( parse_unions );
|
||||||
|
}
|
||||||
|
|
||||||
s32 parse_usings( s32 length, char const* usings_def, Code* out_using_codes )
|
s32 parse_usings( s32 length, char const* usings_def, Code* out_using_codes )
|
||||||
{
|
{
|
||||||
not_implemented( parse_usings );
|
not_implemented( parse_usings );
|
||||||
|
@ -73,6 +73,8 @@ namespace gen
|
|||||||
Entry( Typedef ) \
|
Entry( Typedef ) \
|
||||||
Entry( Typename ) \
|
Entry( Typename ) \
|
||||||
Entry( Union ) \
|
Entry( Union ) \
|
||||||
|
Entry( Union_Fwd ) \
|
||||||
|
Entry( Union_Body) \
|
||||||
Entry( Using ) \
|
Entry( Using ) \
|
||||||
Entry( Using_Namespace )
|
Entry( Using_Namespace )
|
||||||
|
|
||||||
@ -726,6 +728,7 @@ namespace gen
|
|||||||
Code def_struct ( s32 length, char const* name, Code parent = NoCode, Code specifiers = NoCode, Code body = NoCode );
|
Code def_struct ( s32 length, char const* name, Code parent = NoCode, Code specifiers = NoCode, Code body = NoCode );
|
||||||
Code def_typedef ( s32 length, char const* name, Code type );
|
Code def_typedef ( s32 length, char const* name, Code type );
|
||||||
Code def_type ( s32 length, char const* name, Code specifiers = NoCode, Code ArrayExpr = NoCode );
|
Code def_type ( s32 length, char const* name, Code specifiers = NoCode, Code ArrayExpr = NoCode );
|
||||||
|
Code def_union ( s32 length, char const* name, Code body = NoCode );
|
||||||
Code def_using ( s32 length, char const* name, Code type = NoCode, UsingT specifier = UsingRegular );
|
Code def_using ( s32 length, char const* name, Code type = NoCode, UsingT specifier = UsingRegular );
|
||||||
|
|
||||||
Code def_variable ( Code type, s32 length, char const* name, Code value = NoCode, Code specifiers = NoCode );
|
Code def_variable ( Code type, s32 length, char const* name, Code value = NoCode, Code specifiers = NoCode );
|
||||||
@ -747,6 +750,8 @@ namespace gen
|
|||||||
Code def_specifiers ( s32 num, SpecifierT* specs );
|
Code def_specifiers ( s32 num, SpecifierT* specs );
|
||||||
Code def_struct_body ( s32 num, ... );
|
Code def_struct_body ( s32 num, ... );
|
||||||
Code def_struct_body ( s32 num, Code* codes );
|
Code def_struct_body ( s32 num, Code* codes );
|
||||||
|
Code def_union_body ( s32 num, ... );
|
||||||
|
Code def_union_body ( s32 num, Code* codes );
|
||||||
# pragma endregion Upfront
|
# pragma endregion Upfront
|
||||||
|
|
||||||
# pragma region Incremental
|
# pragma region Incremental
|
||||||
@ -761,6 +766,7 @@ namespace gen
|
|||||||
Code make_params ();
|
Code make_params ();
|
||||||
Code make_specifiers ();
|
Code make_specifiers ();
|
||||||
Code make_struct ( s32 length, char const* name, Code parent = NoCode, Code specifiers = NoCode );
|
Code make_struct ( s32 length, char const* name, Code parent = NoCode, Code specifiers = NoCode );
|
||||||
|
Code make_union ( s32 length, char const* name );
|
||||||
# endif
|
# endif
|
||||||
# pragma endregion Incremental
|
# pragma endregion Incremental
|
||||||
|
|
||||||
@ -777,6 +783,7 @@ namespace gen
|
|||||||
Code parse_variable ( s32 length, char const* var_def );
|
Code parse_variable ( s32 length, char const* var_def );
|
||||||
Code parse_type ( s32 length, char const* type_def );
|
Code parse_type ( s32 length, char const* type_def );
|
||||||
Code parse_typedef ( s32 length, char const* typedef_def );
|
Code parse_typedef ( s32 length, char const* typedef_def );
|
||||||
|
Code parse_union ( s32 length, char const* union_def );
|
||||||
Code parse_using ( s32 length, char const* using_def );
|
Code parse_using ( s32 length, char const* using_def );
|
||||||
|
|
||||||
s32 parse_classes ( s32 length, char const* class_defs, Code* out_class_codes );
|
s32 parse_classes ( s32 length, char const* class_defs, Code* out_class_codes );
|
||||||
@ -788,6 +795,7 @@ namespace gen
|
|||||||
s32 parse_structs ( s32 length, char const* struct_defs, Code* out_struct_codes );
|
s32 parse_structs ( s32 length, char const* struct_defs, Code* out_struct_codes );
|
||||||
s32 parse_variables ( s32 length, char const* var_defs, Code* out_var_codes );
|
s32 parse_variables ( s32 length, char const* var_defs, Code* out_var_codes );
|
||||||
s32 parse_typedefs ( s32 length, char const* typedef_defs, Code* out_typedef_codes );
|
s32 parse_typedefs ( s32 length, char const* typedef_defs, Code* out_typedef_codes );
|
||||||
|
s32 parse_unions ( s32 length, char const* union_defs, Code* out_union_codes );
|
||||||
s32 parse_usings ( s32 length, char const* using_defs, Code* out_using_codes );
|
s32 parse_usings ( s32 length, char const* using_defs, Code* out_using_codes );
|
||||||
#endif
|
#endif
|
||||||
#pragma endregion Parsing
|
#pragma endregion Parsing
|
||||||
@ -1024,16 +1032,19 @@ namespace gen
|
|||||||
# define variable( Type_, Name_, ... ) gen::def_variable ( type_ns(Type_), txt_n_len(Name_), __VA_ARGS__ )
|
# define variable( Type_, Name_, ... ) gen::def_variable ( type_ns(Type_), txt_n_len(Name_), __VA_ARGS__ )
|
||||||
# define type( Value_, ... ) gen::def_type ( txt_n_len(Value_), __VA_ARGS__ )
|
# define type( Value_, ... ) gen::def_type ( txt_n_len(Value_), __VA_ARGS__ )
|
||||||
# define type_fmt( Fmt_, ... ) gen::def_type ( bprintf( Fmt_, __VA_ARGS__ ) )
|
# define type_fmt( Fmt_, ... ) gen::def_type ( bprintf( Fmt_, __VA_ARGS__ ) )
|
||||||
|
# define union( Name_, ... ) gen::def_union ( txt_n_len(Name_), __VA_ARGS__ )
|
||||||
# define using( Name_, Type_ ) gen::def_using ( txt_n_len(Name_), type_ns(Type_) )
|
# define using( Name_, Type_ ) gen::def_using ( txt_n_len(Name_), type_ns(Type_) )
|
||||||
# define using_namespace( Name_ ) gen::def_using_namespace( txt_n_len(Name_) )
|
# define using_namespace( Name_ ) gen::def_using_namespace( txt_n_len(Name_) )
|
||||||
|
|
||||||
# define class_body( ... ) gen::def_class_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
# define class_body( ... ) gen::def_class_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
||||||
# define enum_body( ... ) gen::def_enum_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
# define enum_body( ... ) gen::def_enum_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
||||||
|
# define extern_linkage_body( ... ) gen::def_extern_linkage_body( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
||||||
# define global_body( ... ) gen::def_global_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
# define global_body( ... ) gen::def_global_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
||||||
# define function_body( ... ) gen::def_function_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
# define function_body( ... ) gen::def_function_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
||||||
# define namespace_body( ... ) gen::def_namespace_body( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
# define namespace_body( ... ) gen::def_namespace_body( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
||||||
# define operator_body( ... ) gen::def_operator_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
# define operator_body( ... ) gen::def_operator_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
||||||
# define struct_body( ... ) gen::def_struct_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
# define struct_body( ... ) gen::def_struct_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
||||||
|
# define union_body( ... ) gen::def_union_body ( macro_num_args( __VA_ARGS__ ), __VA_ARGS__ )
|
||||||
|
|
||||||
# ifdef GEN_FEATURE_INCREMENTAL
|
# ifdef GEN_FEATURE_INCREMENTAL
|
||||||
// Incremental
|
// Incremental
|
||||||
@ -1054,6 +1065,7 @@ namespace gen
|
|||||||
# define variable_code( ... ) gen::parse_variable ( txt_n_len( __VA_ARGS__ ))
|
# define variable_code( ... ) gen::parse_variable ( txt_n_len( __VA_ARGS__ ))
|
||||||
# define type_code( ... ) gen::parse_type ( txt_n_len( __VA_ARGS__ ))
|
# define type_code( ... ) gen::parse_type ( txt_n_len( __VA_ARGS__ ))
|
||||||
# define typedef_code( ... ) gen::parse_typedef ( txt_n_len( __VA_ARGS__ ))
|
# define typedef_code( ... ) gen::parse_typedef ( txt_n_len( __VA_ARGS__ ))
|
||||||
|
# define union_code( ... ) gen::parse_union ( txt_n_len( __VA_ARGS__ ))
|
||||||
# define using_code( ... ) gen::parse_code ( txt_n_len( __VA_ARGS__ ))
|
# define using_code( ... ) gen::parse_code ( txt_n_len( __VA_ARGS__ ))
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@ -4,6 +4,12 @@
|
|||||||
#ifdef gen_time
|
#ifdef gen_time
|
||||||
#include "gen.cpp"
|
#include "gen.cpp"
|
||||||
|
|
||||||
|
using namespace gen;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int gen_main()
|
int gen_main()
|
||||||
{
|
{
|
||||||
Memory::setup();
|
Memory::setup();
|
||||||
|
Loading…
Reference in New Issue
Block a user