diff --git a/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.h b/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.h index a612b0b..2ff1f77 100644 --- a/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.h +++ b/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.h @@ -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 }; diff --git a/Project/Source/GasaGen/GasaGen.cpp b/Project/Source/GasaGen/GasaGen.cpp index 060b500..f63ce16 100644 --- a/Project/Source/GasaGen/GasaGen.cpp +++ b/Project/Source/GasaGen/GasaGen.cpp @@ -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() ) - { - 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() ) - { - 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() ) - { - 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; diff --git a/Project/Source/GasaGen/GasaGen_ue_parse_testing.cpp b/Project/Source/GasaGen/GasaGen_ue_parse_testing.cpp new file mode 100644 index 0000000..f024e4e --- /dev/null +++ b/Project/Source/GasaGen/GasaGen_ue_parse_testing.cpp @@ -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() ) + { + 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() ) + { + 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() ) + { + 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() ) + { + 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() ) + { + 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() ) + { + 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 +} diff --git a/Project/Source/GasaGen/gen.cpp b/Project/Source/GasaGen/gen.cpp index 5c3f013..f61b82d 100644 --- a/Project/Source/GasaGen/gen.cpp +++ b/Project/Source/GasaGen/gen.cpp @@ -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 ]; @@ -8359,8 +8405,7 @@ namespace parser } if ( tok.Type == TokType::Identifier ) { - tok = tokens[ idx - 2 ]; - + 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 + // : ; // : ; 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 + // : ; + // : ; + Code result = parse_enum(); + Context.pop(); + return result; + } else if ( tok.Type == TokType::BraceCurly_Close ) { // Its a definition @@ -8580,6 +8648,20 @@ namespace parser } // ( ) { } } + 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 ); + // ( ) = 0; + + if ( currtok_noskip.Type == TokType::Comment && currtok_noskip.Line == stmt_end.Line ) + inline_cmt = parse_comment(); + // ( ) ; + } 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,18 +9385,71 @@ 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", prevtok.Text, Context.to_string() ); + Context.pop(); + return CodeInvalid; + } + } } + break; } - if ( op == Invalid ) - { - log_failure( "Invalid operator '%s'\n%s", currtok.Text, Context.to_string() ); - Context.pop(); - return CodeInvalid; - } - - eat( currtok.Type ); + if ( ! was_new_or_delete) + eat( currtok.Type ); // operator // Parse Params @@ -10288,19 +10425,26 @@ namespace parser if ( check( TokType::Operator ) && currtok.Text[ 0 ] == '=' ) { - eat( TokType::Operator ); // ~() = - 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 ); // ~() = 0 specifiers.append( ESpecifier::Pure ); } + else if ( left && str_compare( next.Text, "default", sizeof("default") - 1 ) == 0) + { + body = parse_assignment_expression(); + // ~< + } 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 + function = parse_function_after_name( ModuleFlag::None, NoCode, NoCode, type, name ); + // Parameter list - CodeParam params = parse_params(); + // CodeParam params = parse_params(); // friend ( ) - 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; } - Token stmt_end = currtok; - eat( TokType::Statement_End ); - // friend ; - // friend ( ); - CodeComment inline_cmt = NoCode; - if ( currtok_noskip.Type == TokType::Comment && currtok_noskip.Line == stmt_end.Line ) - inline_cmt = parse_comment(); - // friend ; - // friend ( ); + if ( function && function->Type == ECode::Function_Fwd ) + { + Token stmt_end = currtok; + eat( TokType::Statement_End ); + // friend ; + // friend ( ); + + if ( currtok_noskip.Type == TokType::Comment && currtok_noskip.Line == stmt_end.Line ) + inline_cmt = parse_comment(); + // friend ; + // friend ( ); + } CodeFriend result = ( CodeFriend )make_code(); result->Type = Friend; if ( function ) result->Declaration = function; - else result->Declaration = type; diff --git a/Project/Source/GasaGen/gen.hpp b/Project/Source/GasaGen/gen.hpp index 3af0b3e..2768c08 100644 --- a/Project/Source/GasaGen/gen.hpp +++ b/Project/Source/GasaGen/gen.hpp @@ -339,55 +339,63 @@ namespace EOperator PtrToMemOfPtr, FunctionCall, Comma, + New, + NewArray, + Delete, + DeleteArray, NumOps }; StrC to_str( Type op ) { local_persist StrC lookup[] { - { sizeof( "INVALID" ), "INVALID" }, - { sizeof( "=" ), "=" }, - { sizeof( "+=" ), "+=" }, - { sizeof( "-=" ), "-=" }, - { sizeof( "*=" ), "*=" }, - { sizeof( "/=" ), "/=" }, - { sizeof( "%=" ), "%=" }, - { sizeof( "&=" ), "&=" }, - { sizeof( "|=" ), "|=" }, - { sizeof( "^=" ), "^=" }, - { sizeof( "<<=" ), "<<=" }, - { sizeof( ">>=" ), ">>=" }, - { sizeof( "++" ), "++" }, - { sizeof( "--" ), "--" }, - { sizeof( "+" ), "+" }, - { sizeof( "-" ), "-" }, - { sizeof( "!" ), "!" }, - { sizeof( "+" ), "+" }, - { sizeof( "-" ), "-" }, - { sizeof( "*" ), "*" }, - { sizeof( "/" ), "/" }, - { sizeof( "%" ), "%" }, - { sizeof( "~" ), "~" }, - { sizeof( "&" ), "&" }, - { sizeof( "|" ), "|" }, - { sizeof( "^" ), "^" }, - { sizeof( "<<" ), "<<" }, - { sizeof( ">>" ), ">>" }, - { sizeof( "&&" ), "&&" }, - { sizeof( "||" ), "||" }, - { sizeof( "==" ), "==" }, - { sizeof( "!=" ), "!=" }, - { sizeof( "<" ), "<" }, - { sizeof( ">" ), ">" }, - { sizeof( "<=" ), "<=" }, - { sizeof( ">=" ), ">=" }, - { sizeof( "[]" ), "[]" }, - { sizeof( "*" ), "*" }, - { sizeof( "&" ), "&" }, - { sizeof( "->" ), "->" }, - { sizeof( "->*" ), "->*" }, - { sizeof( "()" ), "()" }, - { sizeof( "," ), "," }, + { sizeof( "INVALID" ), "INVALID" }, + { sizeof( "=" ), "=" }, + { sizeof( "+=" ), "+=" }, + { sizeof( "-=" ), "-=" }, + { sizeof( "*=" ), "*=" }, + { sizeof( "/=" ), "/=" }, + { sizeof( "%=" ), "%=" }, + { sizeof( "&=" ), "&=" }, + { sizeof( "|=" ), "|=" }, + { sizeof( "^=" ), "^=" }, + { sizeof( "<<=" ), "<<=" }, + { sizeof( ">>=" ), ">>=" }, + { sizeof( "++" ), "++" }, + { sizeof( "--" ), "--" }, + { sizeof( "+" ), "+" }, + { sizeof( "-" ), "-" }, + { sizeof( "!" ), "!" }, + { sizeof( "+" ), "+" }, + { sizeof( "-" ), "-" }, + { sizeof( "*" ), "*" }, + { sizeof( "/" ), "/" }, + { sizeof( "%" ), "%" }, + { sizeof( "~" ), "~" }, + { sizeof( "&" ), "&" }, + { sizeof( "|" ), "|" }, + { sizeof( "^" ), "^" }, + { sizeof( "<<" ), "<<" }, + { sizeof( ">>" ), ">>" }, + { sizeof( "&&" ), "&&" }, + { sizeof( "||" ), "||" }, + { sizeof( "==" ), "==" }, + { sizeof( "!=" ), "!=" }, + { sizeof( "<" ), "<" }, + { sizeof( ">" ), ">" }, + { sizeof( "<=" ), "<=" }, + { sizeof( ">=" ), ">=" }, + { sizeof( "[]" ), "[]" }, + { sizeof( "*" ), "*" }, + { sizeof( "&" ), "&" }, + { sizeof( "->" ), "->" }, + { 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 };