End of gencpp experimentation. Parsed Scene and Actor component header + AttributeSet.h

This commit is contained in:
Edward R. Gonzalez 2024-04-16 05:02:58 -04:00
parent 020a2de91a
commit d3deeb31a0
5 changed files with 499 additions and 236 deletions

View File

@ -143,7 +143,8 @@ public:
#pragma region UObject
void GetLifetimeReplicatedProps( TArray< FLifetimeProperty >& OutLifetimeProps ) const override;
void GetLifetimeReplicatedProps( TArray< FLifetimeProperty >& OutLifetimeProps ) const override = 0;
;
#pragma endregion UObject
};

View File

@ -9,9 +9,9 @@
using namespace gen;
#include "GasaGenCommon.cpp"
#include "GasaGen_ue_parse_testing.cpp"
#include "GasaGen_UGasaAttributeSet.cpp"
int gen_main()
{
gen::init();
@ -22,24 +22,23 @@ int gen_main()
umeta_generated_body = code_str( GENERATED_BODY() );
gasa_api = code_str( GASA_API );
StrC str_generated_body = txt("GENERATED_BODY(");
StrC str_generated_uclass_body = txt("GENERATED_UCLASS_BODY(");
StrC str_property_binding_impl = txt("PROPERTY_BINDING_IMPLEMENTATION");
StrC str_uclass = txt("UCLASS(");
StrC str_ufunction = txt("UFUNCTION(");
StrC str_uproperty = txt("UPROPERTY(");
StrC str_declare_log_category_extern = txt("DECLARE_LOG_CATEGORY_EXTERN(");
StrC str_enum_class_flags = txt("ENUM_CLASS_FLAGS(");
StrC str_declare_class = txt("DECLARE_CLASS(");
StrC str_define_default_object_initializer_constructor_call = txt("DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(");
StrC str_macro_text = txt("TEXT(");
StrC str_declare_multicast_delegate_one_parameter = txt("DECLARE_MULTICAST_DELEGATE_OneParam(");
StrC str_declare_multicast_delegate_two_parameter = txt("DECLARE_MULTICAST_DELEGATE_TwoParams(");
StrC str_declare_multicast_delegate_three_parameter = txt("DECLARE_MULTICAST_DELEGATE_ThreeParams(");
StrC str_declare_delegate_retval_one_param = txt("DECLARE_DELEGATE_RetVal_OneParam(");
StrC str_declare_function = txt("DECLARE_FUNCTION(");
StrC str_result_decl = txt("RESULT_DECL");
StrC str_property_binding_implementation = txt("PROPERTY_BINDING_IMPLEMENTATION(");
StrC str_GENERATED_BODY = txt("GENERATED_BODY(");
StrC str_GENERATED_UCLASS_BODY = txt("GENERATED_UCLASS_BODY(");
StrC str_PROPERTY_BINDING_IMPLEMENTATION = txt("PROPERTY_BINDING_IMPLEMENTATION(");
StrC str_UCLASS = txt("UCLASS(");
StrC str_UFUNCTION = txt("UFUNCTION(");
StrC str_UPROPERTY = txt("UPROPERTY(");
StrC str_DECLARE_LOG_CATEGORY_EXTERN = txt("DECLARE_LOG_CATEGORY_EXTERN(");
StrC str_ENUM_CLASS_FLAGS = txt("ENUM_CLASS_FLAGS(");
StrC str_DECLARE_CLASS = txt("DECLARE_CLASS(");
StrC str_DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL = txt("DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(");
StrC str_TEXT = txt("TEXT(");
StrC str_DECLARE_MULTICAST_DELEGATE_OneParam = txt("DECLARE_MULTICAST_DELEGATE_OneParam(");
StrC str_DECLARE_MULTICAST_DELEGATE_TwoParams = txt("DECLARE_MULTICAST_DELEGATE_TwoParams(");
StrC str_DECLARE_MULTICAST_DELEGATE_ThreeParams = txt("DECLARE_MULTICAST_DELEGATE_ThreeParams(");
StrC str_DECLARE_DELEGATE_RetVal_OneParam = txt("DECLARE_DELEGATE_RetVal_OneParam(");
StrC str_DECLARE_FUNCTION = txt("DECLARE_FUNCTION(");
StrC str_RESULT_DECL = txt("RESULT_DECL");
StrC str_FORCEINLINE = txt("FORCEINLINE");
StrC str_UENUM = txt("UENUM(");
StrC str_UMETA = txt("UMETA(");
@ -57,28 +56,27 @@ int gen_main()
StrC str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_OneParam = txt("DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_OneParam(");
StrC str_UPARAM = txt("UPARAM(");
StrC str_FORCEINLINE_DEBUGGABLE = txt("FORCEINLINE_DEBUGGABLE");
StrC str_DECLARE_EVENT_ThreeParams = txt("DECLARE_EVENT_ThreeParams(");
StrC str_USTRUCT = txt("USTRUCT(");
StrC str_GENERATED_USTRUCT_BODY = txt("GENERATED_USTRUCT_BODY(");
PreprocessorDefines.append( get_cached_string(str_generated_body));
PreprocessorDefines.append( get_cached_string(str_generated_uclass_body));
PreprocessorDefines.append( get_cached_string(str_property_binding_impl));
// PreprocessorDefines.append( get_cached_string(str_ue_deprecated));
PreprocessorDefines.append( get_cached_string(str_uclass));
PreprocessorDefines.append( get_cached_string(str_ufunction));
PreprocessorDefines.append( get_cached_string(str_uproperty));
// PreprocessorDefines.append( get_cached_string(str_umg_api));
PreprocessorDefines.append( get_cached_string(str_declare_log_category_extern));
PreprocessorDefines.append( get_cached_string(str_enum_class_flags));
PreprocessorDefines.append( get_cached_string(str_declare_class));
PreprocessorDefines.append( get_cached_string(str_define_default_object_initializer_constructor_call));
// PreprocessorDefines.append( get_cached_string(str_core_object_api));
PreprocessorDefines.append( get_cached_string(str_macro_text));
PreprocessorDefines.append( get_cached_string(str_declare_multicast_delegate_one_parameter));
PreprocessorDefines.append( get_cached_string(str_declare_multicast_delegate_two_parameter));
PreprocessorDefines.append( get_cached_string(str_declare_multicast_delegate_three_parameter));
PreprocessorDefines.append( get_cached_string(str_declare_delegate_retval_one_param));
PreprocessorDefines.append( get_cached_string(str_declare_function));
PreprocessorDefines.append( get_cached_string(str_result_decl));
PreprocessorDefines.append( get_cached_string(str_property_binding_implementation));
PreprocessorDefines.append( get_cached_string(str_GENERATED_BODY));
PreprocessorDefines.append( get_cached_string(str_GENERATED_UCLASS_BODY));
PreprocessorDefines.append( get_cached_string(str_PROPERTY_BINDING_IMPLEMENTATION));
PreprocessorDefines.append( get_cached_string(str_UCLASS));
PreprocessorDefines.append( get_cached_string(str_UFUNCTION));
PreprocessorDefines.append( get_cached_string(str_UPROPERTY));
PreprocessorDefines.append( get_cached_string(str_DECLARE_LOG_CATEGORY_EXTERN));
PreprocessorDefines.append( get_cached_string(str_ENUM_CLASS_FLAGS));
PreprocessorDefines.append( get_cached_string(str_DECLARE_CLASS));
PreprocessorDefines.append( get_cached_string(str_DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL));
PreprocessorDefines.append( get_cached_string(str_TEXT));
PreprocessorDefines.append( get_cached_string(str_DECLARE_MULTICAST_DELEGATE_OneParam));
PreprocessorDefines.append( get_cached_string(str_DECLARE_MULTICAST_DELEGATE_TwoParams));
PreprocessorDefines.append( get_cached_string(str_DECLARE_MULTICAST_DELEGATE_ThreeParams));
PreprocessorDefines.append( get_cached_string(str_DECLARE_DELEGATE_RetVal_OneParam));
PreprocessorDefines.append( get_cached_string(str_DECLARE_FUNCTION));
PreprocessorDefines.append( get_cached_string(str_RESULT_DECL));
PreprocessorDefines.append( get_cached_string(str_FORCEINLINE));
PreprocessorDefines.append( get_cached_string(str_UENUM));
PreprocessorDefines.append( get_cached_string(str_UMETA));
@ -89,7 +87,6 @@ int gen_main()
PreprocessorDefines.append( get_cached_string(str_DECLARE_DELEGATE_SixParams));
PreprocessorDefines.append( get_cached_string(str_DECLARE_EVENT_TwoParams));
PreprocessorDefines.append( get_cached_string(str_DECLARE_DELEGATE_RetVal_ThreeParams));
// PreprocessorDefines.append( get_cached_string(str_ENGINE_API));
PreprocessorDefines.append( get_cached_string(str_PRAGMA_DISABLE_DEPRECATION_WARNINGS));
PreprocessorDefines.append( get_cached_string(str_PRAGMA_ENABLE_DEPRECATION_WARNINGS));
PreprocessorDefines.append( get_cached_string(str_DEFINE_ACTORDESC_TYPE));
@ -97,117 +94,13 @@ int gen_main()
PreprocessorDefines.append( get_cached_string(str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_OneParam));
PreprocessorDefines.append( get_cached_string(str_UPARAM));
PreprocessorDefines.append( get_cached_string(str_FORCEINLINE_DEBUGGABLE));
PreprocessorDefines.append( get_cached_string(str_DECLARE_EVENT_ThreeParams));
PreprocessorDefines.append( get_cached_string(str_USTRUCT));
PreprocessorDefines.append( get_cached_string(str_GENERATED_USTRUCT_BODY));
FileContents content;
ue_parse_testing();
#define path_UProgressBar \
"C:/projects/Unreal/Surgo/UE/Engine/Source/Runtime/UMG/Public/Components/ProgressBar.h"
#if 0
content = file_read_contents( GlobalAllocator, true, path_UProgressBar );
CodeBody parsed_uprogressbar = parse_global_body( StrC { content.size, (char const*)content.data });
log_fmt("\n\n");
for ( Code gcode : parsed_uprogressbar )
{
if ( gcode->Type == CodeT::Class )
{
log_fmt("Class %S - Definitions:\n", gcode->Name);
if (gcode->Body->Type != CodeT::Class_Body)
continue;
for ( Code class_code : gcode->Body->cast<CodeBody>() )
{
switch ( class_code->Type )
{
case CodeT::Variable:
case CodeT::Function:
case CodeT::Function_Fwd:
if ( class_code->Name )
{
log_fmt("%s\n", class_code->Name );
// log_fmt("%s\n", class_code->to_string() );
}
break;
}
}
}
}
#endif
#define path_UObject \
R"(C:\projects\Unreal\Surgo\UE\Engine\Source\Runtime\CoreUObject\Public\UObject\Object.h)"
#if 0
content = file_read_contents( GlobalAllocator, true, path_UObject );
CodeBody parsed_uobject = parse_global_body( StrC { content.size, (char const*)content.data });
log_fmt("\n\n");
for ( Code gcode : parsed_uobject )
{
if ( gcode->Type == CodeT::Class )
{
log_fmt("Class %S - Definitions:\n", gcode->Name);
// log_fmt("%s\n", gcode->to_string() );
if (gcode->Body->Type != CodeT::Class_Body)
continue;
for ( Code class_code : gcode->Body->cast<CodeBody>() )
{
switch ( class_code->Type )
{
case CodeT::Constructor:
case CodeT::Constructor_Fwd:
case CodeT::Variable:
case CodeT::Function:
case CodeT::Function_Fwd:
if ( class_code->Name )
{
log_fmt("%s\n", class_code->Name );
// log_fmt("%s\n", class_code->to_string() );
}
break;
}
}
}
}
#endif
#define path_AActor \
R"(C:\projects\Unreal\Surgo\UE\Engine\Source\Runtime\Engine\Classes\GameFramework\Actor.h)"
#if 1
content = file_read_contents( GlobalAllocator, true, path_AActor );
CodeBody parsed_aactor = parse_global_body( StrC { content.size, (char const*)content.data });
log_fmt("\n\n");
for ( Code gcode : parsed_aactor )
{
if ( gcode->Type == CodeT::Class )
{
log_fmt("Class %S - Definitions:\n", gcode->Name);
if (gcode->Body->Type != CodeT::Class_Body)
continue;
for ( Code class_code : gcode->Body->cast<CodeBody>() )
{
switch ( class_code->Type )
{
case CodeT::Variable:
case CodeT::Function:
case CodeT::Function_Fwd:
if ( class_code->Name )
{
log_fmt("%s\n", class_code->Name );
}
break;
}
}
}
}
#endif
// StrC str_gasa_api = txt("GASA_API");
StrC str_gasa_api = txt("GASA_API");
gen_UGasaAttributeSet();
return 0;

View File

@ -0,0 +1,213 @@
void ue_parse_testing()
{
FileContents content;
#define path_UProgressBar \
"C:/projects/Unreal/Surgo/UE/Engine/Source/Runtime/UMG/Public/Components/ProgressBar.h"
#if 0
content = file_read_contents( GlobalAllocator, true, path_UProgressBar );
CodeBody parsed_uprogressbar = parse_global_body( StrC { content.size, (char const*)content.data });
log_fmt("\n\n");
for ( Code gcode : parsed_uprogressbar )
{
if ( gcode->Type == CodeT::Class )
{
log_fmt("Class %S - Definitions:\n", gcode->Name);
if (gcode->Body->Type != CodeT::Class_Body)
continue;
for ( Code class_code : gcode->Body->cast<CodeBody>() )
{
switch ( class_code->Type )
{
case CodeT::Variable:
case CodeT::Function:
case CodeT::Function_Fwd:
if ( class_code->Name )
{
log_fmt("%s\n", class_code->Name );
// log_fmt("%s\n", class_code->to_string() );
}
break;
}
}
}
}
#endif
#define path_UObject \
R"(C:\projects\Unreal\Surgo\UE\Engine\Source\Runtime\CoreUObject\Public\UObject\Object.h)"
#if 0
content = file_read_contents( GlobalAllocator, true, path_UObject );
CodeBody parsed_uobject = parse_global_body( StrC { content.size, (char const*)content.data });
log_fmt("\n\n");
for ( Code gcode : parsed_uobject )
{
if ( gcode->Type == CodeT::Class )
{
log_fmt("Class %S - Definitions:\n", gcode->Name);
// log_fmt("%s\n", gcode->to_string() );
if (gcode->Body->Type != CodeT::Class_Body)
continue;
for ( Code class_code : gcode->Body->cast<CodeBody>() )
{
switch ( class_code->Type )
{
case CodeT::Constructor:
case CodeT::Constructor_Fwd:
case CodeT::Variable:
case CodeT::Function:
case CodeT::Function_Fwd:
if ( class_code->Name )
{
log_fmt("%s\n", class_code->Name );
// log_fmt("%s\n", class_code->to_string() );
}
break;
}
}
}
}
#endif
#define path_AActor \
R"(C:\projects\Unreal\Surgo\UE\Engine\Source\Runtime\Engine\Classes\GameFramework\Actor.h)"
#if 0
content = file_read_contents( GlobalAllocator, true, path_AActor );
CodeBody parsed_aactor = parse_global_body( StrC { content.size, (char const*)content.data });
log_fmt("\n\n");
for ( Code gcode : parsed_aactor )
{
if ( gcode->Type == CodeT::Class )
{
log_fmt("Class %S - Definitions:\n", gcode->Name);
if (gcode->Body->Type != CodeT::Class_Body)
continue;
for ( Code class_code : gcode->Body->cast<CodeBody>() )
{
switch ( class_code->Type )
{
case CodeT::Variable:
case CodeT::Function:
case CodeT::Function_Fwd:
if ( class_code->Name )
{
log_fmt("%s\n", class_code->Name );
}
break;
}
}
}
}
#endif
#define path_ActorComponent \
R"(C:\projects\Unreal\Surgo\UE\Engine\Source\Runtime\Engine\Classes\Components\ActorComponent.h)"
#if 0
content = file_read_contents( GlobalAllocator, true, path_ActorComponent );
CodeBody parsed_actor_component = parse_global_body( StrC { content.size, (char const*)content.data });
for ( Code gcode : parsed_actor_component )
{
if ( gcode->Type == CodeT::Class )
{
log_fmt("\n\n");
log_fmt("Class %S - Definitions:\n", gcode->Name);
if (gcode->Body->Type != CodeT::Class_Body)
continue;
for ( Code class_code : gcode->Body->cast<CodeBody>() )
{
switch ( class_code->Type )
{
case CodeT::Variable:
case CodeT::Function:
case CodeT::Function_Fwd:
if ( class_code->Name )
{
log_fmt("%s\n", class_code->Name );
}
break;
}
}
}
}
#endif
#define path_SceneComponent \
R"(C:\projects\Unreal\Surgo\UE\Engine\Source\Runtime\Engine\Classes\Components\SceneComponent.h)"
#if 0
content = file_read_contents( GlobalAllocator, true, path_SceneComponent );
CodeBody parsed_scene_component = parse_global_body( StrC { content.size, (char const*)content.data });
for ( Code gcode : parsed_scene_component )
{
if ( gcode->Type == CodeT::Class )
{
log_fmt("\n\n");
log_fmt("Class %S - Definitions:\n", gcode->Name);
if (gcode->Body->Type != CodeT::Class_Body)
continue;
for ( Code class_code : gcode->Body->cast<CodeBody>() )
{
switch ( class_code->Type )
{
case CodeT::Variable:
case CodeT::Function:
case CodeT::Function_Fwd:
if ( class_code->Name )
{
log_fmt("%s\n", class_code->Name );
}
break;
}
}
}
}
#endif
#define path_AttributeSet \
R"(C:\projects\Unreal\Surgo\UE\Engine\Plugins\Runtime\GameplayAbilities\Source\GameplayAbilities\Public\AttributeSet.h)"
#if 0
content = file_read_contents( GlobalAllocator, true, path_AttributeSet );
CodeBody parsed_attribute_set = parse_global_body( StrC { content.size, (char const*)content.data });
for ( Code gcode : parsed_attribute_set )
{
if ( gcode->Type == CodeT::Class )
{
log_fmt("\n\n");
log_fmt("Class %S - Definitions:\n", gcode->Name);
if (gcode->Body->Type != CodeT::Class_Body)
continue;
for ( Code class_code : gcode->Body->cast<CodeBody>() )
{
switch ( class_code->Type )
{
case CodeT::Variable:
case CodeT::Function:
case CodeT::Function_Fwd:
if ( class_code->Name )
{
log_fmt("%s\n", class_code->Name );
}
break;
}
}
}
}
#endif
}

View File

@ -1742,6 +1742,8 @@ void CodeDestructor::to_string_fwd( String& result )
if ( ast->Specs.has( ESpecifier::Pure ) )
result.append( " = 0;" );
else if (ast->Body)
result.append_fmt( " = %S;", ast->Body.to_string() );
}
else
result.append_fmt( "~%S();", ast->Parent->Name );
@ -1905,7 +1907,7 @@ void CodeFriend::to_string( String& result )
{
result.append_fmt( "friend %S", ast->Declaration->to_string() );
if ( result[ result.length() - 1 ] != ';' )
if ( ast->Declaration->Type != ECode::Function && result[ result.length() - 1 ] != ';' )
{
result.append( ";" );
}
@ -2023,7 +2025,7 @@ void CodeFn::to_string_fwd( String& result )
{
for ( SpecifierT spec : ast->Specs )
{
if ( ESpecifier::is_trailing( spec ) )
if ( ESpecifier::is_trailing( spec ) && ! spec != ESpecifier::Pure )
{
StrC spec_str = ESpecifier::to_str( spec );
result.append_fmt( " %.*s", spec_str.Len, spec_str.Ptr );
@ -2031,6 +2033,11 @@ void CodeFn::to_string_fwd( String& result )
}
}
if ( ast->Specs.has( ESpecifier::Pure ) )
result.append( " = 0;" );
else if (ast->Body)
result.append_fmt( " = %S;", ast->Body.to_string() );
if ( ast->InlineCmt )
result.append_fmt( "; %S", ast->InlineCmt->Content );
else
@ -3408,7 +3415,6 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy
case Unary_Plus :
case Unary_Minus :
case BNot :
if ( ! params_code )
is_member_symbol = true;
@ -3444,6 +3450,38 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy
}
}
break;
case BNot:
{
// Some compilers let you do this...
// if ( ! ret_type.is_equal( t_bool) )
// {
// log_failure( "gen::def_operator: return type is not a boolean - %s", params_code.debug_str() );
// return OpValidateResult::Fail;
// }
if ( ! params_code )
is_member_symbol = true;
else
{
if ( params_code->Type != ECode::Parameters )
{
log_failure( "gen::def_operator: params is not of Parameters type - %s", params_code.debug_str() );
return OpValidateResult::Fail;
}
if ( params_code->NumEntries > 1 )
{
log_failure(
"gen::def_operator: operator%s may not have more than one parameter - param count: %d",
to_str( op ),
params_code->NumEntries
);
return OpValidateResult::Fail;
}
}
break;
}
case Add :
case Subtract :
@ -3578,6 +3616,11 @@ OpValidateResult operator__validate( OperatorT op, CodeParam params_code, CodeTy
case Comma :
check_params();
break;
case New:
case Delete:
// This library doesn't support validating new and delete yet.
break;
#undef specs
}
@ -5611,7 +5654,8 @@ namespace parser
Entry( UMG_API, "UMG_API" ) \
Entry( COREUOBJECT_API, "COREUOBJECT_API" ) \
Entry( ENGINE_API, "ENGINE_API" ) \
Entry( GASA_API, "GASA_API" )
Entry( GASA_API, "GASA_API" ) \
Entry( GAMEPLAYABILITIES_API, "GAMEPLAYABILITIES_API" )
enum Type : u32
{
@ -5717,6 +5761,7 @@ namespace parser
COREUOBJECT_API,
ENGINE_API,
GASA_API,
GAMEPLAYABILITIES_API,
NumTokens
};
@ -5825,6 +5870,7 @@ namespace parser
{ sizeof( "COREUOBJECT_API" ), "COREUOBJECT_API" },
{ sizeof( "ENGINE_API" ), "ENGINE_API" },
{ sizeof( "GASA_API" ), "GASA_API" },
{ sizeof( "GAMEPLAYABILITIES_API" ), "GAMEPLAYABILITIES_API" },
};
return lookup[ type ];
}
@ -5992,7 +6038,7 @@ namespace parser
while ( Arr[ idx ].Type == TokType::NewLine )
idx++;
return Arr[ idx ];
return Arr[ idx + 1 ];
}
return Arr[ idx + 1 ];
@ -8360,7 +8406,6 @@ namespace parser
if ( tok.Type == TokType::Identifier )
{
tok = tokens[ idx - 2 ];
bool is_indirection = tok.Type == TokType::Ampersand || tok.Type == TokType::Star;
bool ok_to_parse = false;
@ -8378,10 +8423,12 @@ namespace parser
ok_to_parse = true;
}
else if ( tok.Type == TokType::Assign_Classifer
&& tokens[idx - 4].Type == TokType::Decl_Class
&& tokens[idx - 5].Type == which )
&& ( ( tokens[idx - 5].Type == which && tokens[idx - 4].Type == TokType::Decl_Class )
|| ( tokens[idx - 4].Type == which))
)
{
// Its a forward declaration of an enum class
// Its a forward declaration of an enum
// <enum> <type_identifier> : <identifier>;
// <enum> <class> <type_identifier> : <identifier>;
ok_to_parse = true;
Code result = parse_enum();
@ -8407,6 +8454,27 @@ namespace parser
Context.pop();
return result;
}
else if ( tok.Type >= TokType::Type_Unsigned && tok.Type <= TokType::Type_MS_W64 )
{
tok = tokens[ idx - 2 ];
if ( tok.Type != TokType::Assign_Classifer
|| ( ( tokens[idx - 5].Type != which && tokens[idx - 4].Type != TokType::Decl_Class )
&& ( tokens[idx - 4].Type != which))
)
{
log_failure( "Unsupported or bad member definition after %s declaration\n%s", to_str(which), Context.to_string() );
Context.pop();
return CodeInvalid;
}
// Its a forward declaration of an enum class
// <enum> <type_identifier> : <identifier>;
// <enum> <class> <type_identifier> : <identifier>;
Code result = parse_enum();
Context.pop();
return result;
}
else if ( tok.Type == TokType::BraceCurly_Close )
{
// Its a definition
@ -8580,6 +8648,20 @@ namespace parser
}
// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers> { <Body> }
}
else if ( check(TokType::Operator) && currtok.Text[0] == '=' )
{
eat(TokType::Operator);
specifiers.append( ESpecifier::Pure );
eat( TokType::Number);
Token stmt_end = currtok;
eat( TokType::Statement_End );
// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers> = 0;
if ( currtok_noskip.Type == TokType::Comment && currtok_noskip.Line == stmt_end.Line )
inline_cmt = parse_comment();
// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers>; <InlineCmt>
}
else
{
Token stmt_end = currtok;
@ -9111,6 +9193,8 @@ namespace parser
Context.Scope->Name = currtok;
bool was_new_or_delete = false;
OperatorT op = Invalid;
switch ( currtok.Text[ 0 ] )
{
@ -9301,17 +9385,70 @@ namespace parser
break;
default :
{
break;
}
}
StrC str_new = to_str(OperatorT::New);
StrC str_delete = to_str(OperatorT::Delete);
if ( str_compare( currtok.Text, str_new.Ptr, max(str_new.Len - 1, currtok.Length)) == 0)
{
op = OperatorT::New;
eat( ETokType::Identifier );
was_new_or_delete = true;
s32 idx = Context.Tokens.Idx + 1;
{
while ( Context.Tokens[ idx ].Type == TokType::NewLine )
idx++;
}
Token next = Context.Tokens[idx];
if ( currtok.Type == TokType::Operator && str_compare(currtok.Text, "[]", 2) == 0)
{
eat(ETokType::Operator);
op = OperatorT::NewArray;
}
else if ( currtok.Type == TokType::BraceSquare_Open && next.Type == TokType::BraceSquare_Close)
{
eat(ETokType::BraceSquare_Open);
eat(ETokType::BraceSquare_Close);
op = OperatorT::NewArray;
}
}
else if ( str_compare( currtok.Text, str_delete.Ptr, max(str_delete.Len - 1, currtok.Length )) == 0)
{
op = OperatorT::Delete;
eat(ETokType::Identifier);
was_new_or_delete = true;
s32 idx = Context.Tokens.Idx + 1;
{
while ( Context.Tokens[ idx ].Type == TokType::NewLine )
idx++;
}
Token next = Context.Tokens[idx];
if ( currtok.Type == TokType::Operator && str_compare(currtok.Text, "[]", 2) == 0)
{
eat(ETokType::Operator);
op = OperatorT::DeleteArray;
}
else if ( currtok.Type == TokType::BraceSquare_Open && next.Type == TokType::BraceSquare_Close)
{
eat(ETokType::BraceSquare_Open);
eat(ETokType::BraceSquare_Close);
op = OperatorT::DeleteArray;
}
}
else
{
if ( op == Invalid )
{
log_failure( "Invalid operator '%s'\n%s", currtok.Text, Context.to_string() );
log_failure( "Invalid operator '%s'\n%s", prevtok.Text, Context.to_string() );
Context.pop();
return CodeInvalid;
}
}
}
break;
}
if ( ! was_new_or_delete)
eat( currtok.Type );
// <ExportFlag> <Attributes> <Specifiers> <ReturnType> <Qualifier::...> operator <Op>
@ -10288,19 +10425,26 @@ namespace parser
if ( check( TokType::Operator ) && currtok.Text[ 0 ] == '=' )
{
eat( TokType::Operator );
// <Virtual Specifier> ~<Name>() =
if ( left && currtok.Text[ 0 ] == '0' )
bool skip_formatting = true;
Token next = Context.Tokens.next(skip_formatting);
if ( left && next.Text[ 0 ] == '0' )
{
eat( TokType::Operator );
eat( TokType::Number );
// <Virtual Specifier> ~<Name>() = 0
specifiers.append( ESpecifier::Pure );
}
else if ( left && str_compare( next.Text, "default", sizeof("default") - 1 ) == 0)
{
body = parse_assignment_expression();
// <Virtual Specifier> ~<
}
else
{
log_failure( "Pure specifier expected due to '=' token\n%s", Context.to_string() );
log_failure( "Pure or default specifier expected due to '=' token\n%s", Context.to_string() );
return CodeInvalid;
}
@ -10326,7 +10470,7 @@ namespace parser
if ( specifiers )
result->Specs = specifiers;
if ( body )
if ( body && body->Type == ECode::Function_Body )
{
result->Body = body;
result->Type = ECode::Destructor;
@ -10640,36 +10784,40 @@ namespace parser
Context.Scope->Name = name;
// friend <ReturnType> <Name>
function = parse_function_after_name( ModuleFlag::None, NoCode, NoCode, type, name );
// Parameter list
CodeParam params = parse_params();
// CodeParam params = parse_params();
// friend <ReturnType> <Name> ( <Parameters> )
function = make_code();
function->Type = Function_Fwd;
function->Name = get_cached_string( name );
function->ReturnType = type;
// function = make_code();
// function->Type = Function_Fwd;
// function->Name = get_cached_string( name );
// function->ReturnType = type;
if ( params )
function->Params = params;
// if ( params )
// function->Params = params;
}
CodeComment inline_cmt = NoCode;
if ( function && function->Type == ECode::Function_Fwd )
{
Token stmt_end = currtok;
eat( TokType::Statement_End );
// friend <Type>;
// friend <ReturnType> <Name> ( <Parameters> );
CodeComment inline_cmt = NoCode;
if ( currtok_noskip.Type == TokType::Comment && currtok_noskip.Line == stmt_end.Line )
inline_cmt = parse_comment();
// friend <Type>; <InlineCmt>
// friend <ReturnType> <Name> ( <Parameters> ); <InlineCmt>
}
CodeFriend result = ( CodeFriend )make_code();
result->Type = Friend;
if ( function )
result->Declaration = function;
else
result->Declaration = type;

View File

@ -339,6 +339,10 @@ namespace EOperator
PtrToMemOfPtr,
FunctionCall,
Comma,
New,
NewArray,
Delete,
DeleteArray,
NumOps
};
@ -388,6 +392,10 @@ namespace EOperator
{ sizeof( "->*" ), "->*" },
{ sizeof( "()" ), "()" },
{ sizeof( "," ), "," },
{ sizeof( "new" ), "new" },
{ sizeof( "new[]" ), "new[]" },
{ sizeof( "delete" ), "delete" },
{ sizeof( "delete[]" ), "delete[]" },
};
return lookup[ op ];
}
@ -822,7 +830,7 @@ struct AST
union
{
AST* ArrExpr; // Typename
AST* Body; // Class, Constructr, Destructor, Enum, Function, Namespace, Struct, Union
AST* Body; // Class, Constructr, Destructor, Enum, Friend, Function, Namespace, Struct, Union
AST* Declaration; // Friend, Template
AST* Value; // Parameter, Variable
};
@ -902,7 +910,7 @@ struct AST_POD
union
{
AST* ArrExpr; // Typename
AST* Body; // Class, Constructr, Destructor, Enum, Function, Namespace, Struct, Union
AST* Body; // Class, Constructr, Destructor, Enum, Friend, Function, Namespace, Struct, Union
AST* Declaration; // Friend, Template
AST* Value; // Parameter, Variable
};