Can parse AActor with gencpp
This commit is contained in:
		@@ -9,7 +9,7 @@ UGasaAttributeSet::UGasaAttributeSet()
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	InitHealth( 100.f );
 | 
						InitHealth( 100.f );
 | 
				
			||||||
	InitMaxHealth( 100.f );
 | 
						InitMaxHealth( 100.f );
 | 
				
			||||||
	InitMana( ( 50.f ) );
 | 
						InitMana( 50.f );
 | 
				
			||||||
	InitMaxMana( 50.f );
 | 
						InitMaxMana( 50.f );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,16 +26,12 @@ int gen_main()
 | 
				
			|||||||
	StrC str_generated_uclass_body                                 = txt("GENERATED_UCLASS_BODY(");
 | 
						StrC str_generated_uclass_body                                 = txt("GENERATED_UCLASS_BODY(");
 | 
				
			||||||
	StrC str_property_binding_impl                                 = txt("PROPERTY_BINDING_IMPLEMENTATION");
 | 
						StrC str_property_binding_impl                                 = txt("PROPERTY_BINDING_IMPLEMENTATION");
 | 
				
			||||||
	StrC str_uclass                                                = txt("UCLASS(");
 | 
						StrC str_uclass                                                = txt("UCLASS(");
 | 
				
			||||||
	StrC str_ue_deprecated         = txt("UE_DEPRECATED(");
 | 
					 | 
				
			||||||
	StrC str_ufunction                                             = txt("UFUNCTION(");
 | 
						StrC str_ufunction                                             = txt("UFUNCTION(");
 | 
				
			||||||
	StrC str_uproperty                                             = txt("UPROPERTY(");
 | 
						StrC str_uproperty                                             = txt("UPROPERTY(");
 | 
				
			||||||
	StrC str_umg_api               = txt("UMG_API");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	StrC str_declare_log_category_extern                           = txt("DECLARE_LOG_CATEGORY_EXTERN(");
 | 
						StrC str_declare_log_category_extern                           = txt("DECLARE_LOG_CATEGORY_EXTERN(");
 | 
				
			||||||
	StrC str_enum_class_flags                                      = txt("ENUM_CLASS_FLAGS(");
 | 
						StrC str_enum_class_flags                                      = txt("ENUM_CLASS_FLAGS(");
 | 
				
			||||||
	StrC str_declare_class                                         = txt("DECLARE_CLASS(");
 | 
						StrC str_declare_class                                         = txt("DECLARE_CLASS(");
 | 
				
			||||||
	StrC str_define_default_object_initializer_constructor_call    = txt("DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(");
 | 
						StrC str_define_default_object_initializer_constructor_call    = txt("DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(");
 | 
				
			||||||
	StrC str_core_object_api = txt("COREUOBJECT_API");
 | 
					 | 
				
			||||||
	StrC str_macro_text                                            = txt("TEXT(");
 | 
						StrC str_macro_text                                            = txt("TEXT(");
 | 
				
			||||||
	StrC str_declare_multicast_delegate_one_parameter              = txt("DECLARE_MULTICAST_DELEGATE_OneParam(");
 | 
						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_two_parameter              = txt("DECLARE_MULTICAST_DELEGATE_TwoParams(");
 | 
				
			||||||
@@ -45,20 +41,36 @@ int gen_main()
 | 
				
			|||||||
	StrC str_result_decl                                           = txt("RESULT_DECL");
 | 
						StrC str_result_decl                                           = txt("RESULT_DECL");
 | 
				
			||||||
	StrC str_property_binding_implementation                       = txt("PROPERTY_BINDING_IMPLEMENTATION(");
 | 
						StrC str_property_binding_implementation                       = txt("PROPERTY_BINDING_IMPLEMENTATION(");
 | 
				
			||||||
	StrC str_FORCEINLINE                                           = txt("FORCEINLINE");
 | 
						StrC str_FORCEINLINE                                           = txt("FORCEINLINE");
 | 
				
			||||||
 | 
						StrC str_UENUM                                                 = txt("UENUM(");
 | 
				
			||||||
 | 
						StrC str_UMETA                                                 = txt("UMETA(");
 | 
				
			||||||
 | 
						StrC str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FiveParams  = txt("DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FiveParams(");
 | 
				
			||||||
 | 
						StrC str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_SevenParams = txt("DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_SevenParams(");
 | 
				
			||||||
 | 
						StrC str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_NineParams  = txt("DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_NineParams(");
 | 
				
			||||||
 | 
						StrC str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FourParams  = txt("DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FourParams(");
 | 
				
			||||||
 | 
						StrC str_DECLARE_DELEGATE_SixParams                            = txt("DECLARE_DELEGATE_SixParams(");
 | 
				
			||||||
 | 
						StrC str_DECLARE_EVENT_TwoParams                               = txt("DECLARE_EVENT_TwoParams(");
 | 
				
			||||||
 | 
						StrC str_DECLARE_DELEGATE_RetVal_ThreeParams                   = txt("DECLARE_DELEGATE_RetVal_ThreeParams(");
 | 
				
			||||||
 | 
						StrC str_PRAGMA_DISABLE_DEPRECATION_WARNINGS                   = txt("PRAGMA_DISABLE_DEPRECATION_WARNINGS");
 | 
				
			||||||
 | 
						StrC str_PRAGMA_ENABLE_DEPRECATION_WARNINGS                    = txt("PRAGMA_ENABLE_DEPRECATION_WARNINGS");
 | 
				
			||||||
 | 
						StrC str_DEFINE_ACTORDESC_TYPE                                 = txt("DEFINE_ACTORDESC_TYPE(");
 | 
				
			||||||
 | 
						StrC str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_TwoParams   = txt("DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_TwoParams(");
 | 
				
			||||||
 | 
						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");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_generated_body));
 | 
						PreprocessorDefines.append( get_cached_string(str_generated_body));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_generated_uclass_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_property_binding_impl));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_ue_deprecated));
 | 
						// PreprocessorDefines.append( get_cached_string(str_ue_deprecated));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_uclass));
 | 
						PreprocessorDefines.append( get_cached_string(str_uclass));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_ufunction));
 | 
						PreprocessorDefines.append( get_cached_string(str_ufunction));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_uproperty));
 | 
						PreprocessorDefines.append( get_cached_string(str_uproperty));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_umg_api));
 | 
						// PreprocessorDefines.append( get_cached_string(str_umg_api));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_declare_log_category_extern));
 | 
						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_enum_class_flags));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_declare_class));
 | 
						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_define_default_object_initializer_constructor_call));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_core_object_api));
 | 
						// PreprocessorDefines.append( get_cached_string(str_core_object_api));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_macro_text));
 | 
						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_one_parameter));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_declare_multicast_delegate_two_parameter));
 | 
						PreprocessorDefines.append( get_cached_string(str_declare_multicast_delegate_two_parameter));
 | 
				
			||||||
@@ -68,11 +80,31 @@ int gen_main()
 | 
				
			|||||||
	PreprocessorDefines.append( get_cached_string(str_result_decl));
 | 
						PreprocessorDefines.append( get_cached_string(str_result_decl));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_property_binding_implementation));
 | 
						PreprocessorDefines.append( get_cached_string(str_property_binding_implementation));
 | 
				
			||||||
	PreprocessorDefines.append( get_cached_string(str_FORCEINLINE));
 | 
						PreprocessorDefines.append( get_cached_string(str_FORCEINLINE));
 | 
				
			||||||
 | 
						PreprocessorDefines.append( get_cached_string(str_UENUM));
 | 
				
			||||||
 | 
						PreprocessorDefines.append( get_cached_string(str_UMETA));
 | 
				
			||||||
 | 
						PreprocessorDefines.append( get_cached_string(str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FiveParams));
 | 
				
			||||||
 | 
						PreprocessorDefines.append( get_cached_string(str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_SevenParams));
 | 
				
			||||||
 | 
						PreprocessorDefines.append( get_cached_string(str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_NineParams));
 | 
				
			||||||
 | 
						PreprocessorDefines.append( get_cached_string(str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FourParams));
 | 
				
			||||||
 | 
						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));
 | 
				
			||||||
 | 
						PreprocessorDefines.append( get_cached_string(str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_TwoParams));
 | 
				
			||||||
 | 
						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));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						FileContents content;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define path_UProgressBar \
 | 
					#define path_UProgressBar \
 | 
				
			||||||
	"C:/projects/Unreal/Surgo/UE/Engine/Source/Runtime/UMG/Public/Components/ProgressBar.h"
 | 
						"C:/projects/Unreal/Surgo/UE/Engine/Source/Runtime/UMG/Public/Components/ProgressBar.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FileContents content = file_read_contents( GlobalAllocator, true, path_UProgressBar );
 | 
					#if 0
 | 
				
			||||||
 | 
						content = file_read_contents( GlobalAllocator, true, path_UProgressBar );
 | 
				
			||||||
	CodeBody parsed_uprogressbar = parse_global_body( StrC { content.size, (char const*)content.data });
 | 
						CodeBody parsed_uprogressbar = parse_global_body( StrC { content.size, (char const*)content.data });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log_fmt("\n\n");
 | 
						log_fmt("\n\n");
 | 
				
			||||||
@@ -93,22 +125,63 @@ int gen_main()
 | 
				
			|||||||
					case CodeT::Function_Fwd:
 | 
										case CodeT::Function_Fwd:
 | 
				
			||||||
						if ( class_code->Name )
 | 
											if ( class_code->Name )
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							log_fmt("%s\n", class_code->Name );
 | 
												// log_fmt("%s\n", class_code->Name );
 | 
				
			||||||
 | 
												log_fmt("%s\n", class_code->to_string() );
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define path_UObject \
 | 
					#define path_UObject \
 | 
				
			||||||
	R"(C:\projects\Unreal\Surgo\UE\Engine\Source\Runtime\CoreUObject\Public\UObject\Object.h)"
 | 
						R"(C:\projects\Unreal\Surgo\UE\Engine\Source\Runtime\CoreUObject\Public\UObject\Object.h)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
	content = file_read_contents( GlobalAllocator, true, path_UObject );
 | 
						content = file_read_contents( GlobalAllocator, true, path_UObject );
 | 
				
			||||||
	CodeBody parsed_uobject = parse_global_body( StrC { content.size, (char const*)content.data });
 | 
						CodeBody parsed_uobject = parse_global_body( StrC { content.size, (char const*)content.data });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log_fmt("\n\n");
 | 
						log_fmt("\n\n");
 | 
				
			||||||
	for ( Code gcode : parsed_uobject )
 | 
						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 )
 | 
							if ( gcode->Type == CodeT::Class )
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -121,8 +194,8 @@ int gen_main()
 | 
				
			|||||||
				switch ( class_code->Type )
 | 
									switch ( class_code->Type )
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					case CodeT::Variable:
 | 
										case CodeT::Variable:
 | 
				
			||||||
					case CodeT::Function:
 | 
										// case CodeT::Function:
 | 
				
			||||||
					case CodeT::Function_Fwd:
 | 
										// case CodeT::Function_Fwd:
 | 
				
			||||||
						if ( class_code->Name )
 | 
											if ( class_code->Name )
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							log_fmt("%s\n", class_code->Name );
 | 
												log_fmt("%s\n", class_code->Name );
 | 
				
			||||||
@@ -132,8 +205,9 @@ int gen_main()
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	StrC str_gasa_api = txt("GASA_API");
 | 
						// StrC str_gasa_api = txt("GASA_API");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gen_UGasaAttributeSet();
 | 
						gen_UGasaAttributeSet();
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -114,7 +114,7 @@ void gen_UGasaAttributeSet()
 | 
				
			|||||||
				{
 | 
									{
 | 
				
			||||||
					InitHealth( 100.f );
 | 
										InitHealth( 100.f );
 | 
				
			||||||
					InitMaxHealth( 100.f );
 | 
										InitMaxHealth( 100.f );
 | 
				
			||||||
					InitMana(( 50.f ));
 | 
										InitMana( 50.f );
 | 
				
			||||||
					InitMaxMana( 50.f );
 | 
										InitMaxMana( 50.f );
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			));
 | 
								));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1588,7 +1588,12 @@ void CodeConstructor::to_string_def( String& result )
 | 
				
			|||||||
void CodeConstructor::to_string_fwd( String& result )
 | 
					void CodeConstructor::to_string_fwd( String& result )
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	AST* ClassStructParent = ast->Parent->Parent;
 | 
						AST* ClassStructParent = ast->Parent->Parent;
 | 
				
			||||||
 | 
						if (ClassStructParent) {
 | 
				
			||||||
		result.append( ClassStructParent->Name );
 | 
							result.append( ClassStructParent->Name );
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							result.append( ast->Name );
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ( ast->Params )
 | 
						if ( ast->Params )
 | 
				
			||||||
		result.append_fmt( "( %S )", ast->Params.to_string() );
 | 
							result.append_fmt( "( %S )", ast->Params.to_string() );
 | 
				
			||||||
@@ -2273,10 +2278,9 @@ void CodeParam::to_string( String& result )
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	if ( ast->Macro )
 | 
						if ( ast->Macro )
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// Were using the convention that if the value type is a macro we ignore everything else
 | 
					 | 
				
			||||||
		// Related to parsing: ( <macro>, ... )
 | 
							// Related to parsing: ( <macro>, ... )
 | 
				
			||||||
		result.append( ast->Macro.ast->Content );
 | 
							result.append( ast->Macro.ast->Content );
 | 
				
			||||||
		return;
 | 
							// Could also be: ( <macro> <type <name>, ... )
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ( ast->Name )
 | 
						if ( ast->Name )
 | 
				
			||||||
@@ -2285,8 +2289,9 @@ void CodeParam::to_string( String& result )
 | 
				
			|||||||
			result.append_fmt( " %S", ast->Name );
 | 
								result.append_fmt( " %S", ast->Name );
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			result.append_fmt( " %S %S", ast->ValueType.to_string(), ast->Name );
 | 
								result.append_fmt( " %S %S", ast->ValueType.to_string(), ast->Name );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else if ( ast->ValueType )
 | 
				
			||||||
		result.append_fmt( " %S", ast->ValueType.to_string() );
 | 
							result.append_fmt( " %S", ast->ValueType.to_string() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ( ast->Value )
 | 
						if ( ast->Value )
 | 
				
			||||||
@@ -5599,7 +5604,14 @@ namespace parser
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	namespace ETokType
 | 
						namespace ETokType
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
#define GEN_DEFINE_ATTRIBUTE_TOKENS Entry( API_Export, GEN_API_Export_Code ) Entry( API_Import, GEN_API_Import_Code )
 | 
					#define GEN_DEFINE_ATTRIBUTE_TOKENS \
 | 
				
			||||||
 | 
						Entry( API_Export, "GEN_API_Export_Code" ) \
 | 
				
			||||||
 | 
						Entry( API_Import, "GEN_API_Import_Code" ) \
 | 
				
			||||||
 | 
						Entry( UE_DEPRECATED, "UE_DEPRECATED(" ) \
 | 
				
			||||||
 | 
						Entry( UMG_API, "UMG_API" ) \
 | 
				
			||||||
 | 
						Entry( COREUOBJECT_API, "COREUOBJECT_API" ) \
 | 
				
			||||||
 | 
						Entry( ENGINE_API, "ENGINE_API" ) \
 | 
				
			||||||
 | 
						Entry( GASA_API, "GASA_API" )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		enum Type : u32
 | 
							enum Type : u32
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -5700,6 +5712,11 @@ namespace parser
 | 
				
			|||||||
			__Attributes_Start,
 | 
								__Attributes_Start,
 | 
				
			||||||
			API_Export,
 | 
								API_Export,
 | 
				
			||||||
			API_Import,
 | 
								API_Import,
 | 
				
			||||||
 | 
								UE_DEPRECATED,
 | 
				
			||||||
 | 
								UMG_API,
 | 
				
			||||||
 | 
								COREUOBJECT_API,
 | 
				
			||||||
 | 
								ENGINE_API,
 | 
				
			||||||
 | 
								GASA_API,
 | 
				
			||||||
			NumTokens
 | 
								NumTokens
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -5803,6 +5820,11 @@ namespace parser
 | 
				
			|||||||
				{ sizeof( "__attrib_start__" ),    "__attrib_start__"    },
 | 
									{ sizeof( "__attrib_start__" ),    "__attrib_start__"    },
 | 
				
			||||||
				{ sizeof( "GEN_API_Export_Code" ), "GEN_API_Export_Code" },
 | 
									{ sizeof( "GEN_API_Export_Code" ), "GEN_API_Export_Code" },
 | 
				
			||||||
				{ sizeof( "GEN_API_Import_Code" ), "GEN_API_Import_Code" },
 | 
									{ sizeof( "GEN_API_Import_Code" ), "GEN_API_Import_Code" },
 | 
				
			||||||
 | 
									{ sizeof( "UE_DEPRECATED" ),       "UE_DEPRECATED"       },
 | 
				
			||||||
 | 
									{ sizeof( "UMG_API" ),             "UMG_API"             },
 | 
				
			||||||
 | 
									{ sizeof( "COREUOBJECT_API" ),     "COREUOBJECT_API"     },
 | 
				
			||||||
 | 
									{ sizeof( "ENGINE_API" ),          "ENGINE_API"          },
 | 
				
			||||||
 | 
									{ sizeof( "GASA_API" ),            "GASA_API"            },
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
			return lookup[ type ];
 | 
								return lookup[ type ];
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -5982,7 +6004,7 @@ namespace parser
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	global Arena_64KB defines_map_arena;
 | 
						global Arena_128KB defines_map_arena;
 | 
				
			||||||
	global HashTable< StrC > defines;
 | 
						global HashTable< StrC > defines;
 | 
				
			||||||
	global Array< Token > Tokens;
 | 
						global Array< Token > Tokens;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -6283,6 +6305,11 @@ namespace parser
 | 
				
			|||||||
			token.Flags |= TF_AccessSpecifier;
 | 
								token.Flags |= TF_AccessSpecifier;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( type > TokType::__Attributes_Start )
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								token.Flags |= TF_Attribute;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ( type == ETokType::Decl_Extern_Linkage )
 | 
							if ( type == ETokType::Decl_Extern_Linkage )
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			SkipWhitespace();
 | 
								SkipWhitespace();
 | 
				
			||||||
@@ -7174,7 +7201,7 @@ namespace parser
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		Tokens            = Array< Token >::init_reserve( LexArena, ( LexAllocator_Size - sizeof( Array< Token >::Header ) ) / sizeof( Token ) );
 | 
							Tokens            = Array< Token >::init_reserve( LexArena, ( LexAllocator_Size - sizeof( Array< Token >::Header ) ) / sizeof( Token ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		defines_map_arena = Arena_64KB::init();
 | 
							defines_map_arena = Arena_128KB::init();
 | 
				
			||||||
		defines           = HashTable< StrC >::init( defines_map_arena );
 | 
							defines           = HashTable< StrC >::init( defines_map_arena );
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -7256,7 +7283,7 @@ namespace parser
 | 
				
			|||||||
	internal CodeStruct      parse_struct( bool inplace_def = false );
 | 
						internal CodeStruct      parse_struct( bool inplace_def = false );
 | 
				
			||||||
	internal CodeVar         parse_variable();
 | 
						internal CodeVar         parse_variable();
 | 
				
			||||||
	internal CodeTemplate    parse_template();
 | 
						internal CodeTemplate    parse_template();
 | 
				
			||||||
	internal CodeType        parse_type( bool* is_function = nullptr );
 | 
						internal CodeType        parse_type( bool from_template = false, bool* is_function = nullptr );
 | 
				
			||||||
	internal CodeTypedef     parse_typedef();
 | 
						internal CodeTypedef     parse_typedef();
 | 
				
			||||||
	internal CodeUnion       parse_union( bool inplace_def = false );
 | 
						internal CodeUnion       parse_union( bool inplace_def = false );
 | 
				
			||||||
	internal CodeUsing       parse_using();
 | 
						internal CodeUsing       parse_using();
 | 
				
			||||||
@@ -7594,15 +7621,18 @@ namespace parser
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		push_scope();
 | 
							push_scope();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Token start = NullToken;
 | 
							Token start = currtok;
 | 
				
			||||||
		s32   len   = 0;
 | 
							s32   len   = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// There can be more than one attribute. If there is flatten them to a single string.
 | 
				
			||||||
 | 
							// TODO(Ed): Support keeping an linked list of attributes similar to parameters
 | 
				
			||||||
 | 
							while ( left && currtok.is_attribute() )
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
			if ( check( TokType::Attribute_Open ) )
 | 
								if ( check( TokType::Attribute_Open ) )
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				eat( TokType::Attribute_Open );
 | 
									eat( TokType::Attribute_Open );
 | 
				
			||||||
				// [[
 | 
									// [[
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			start = currtok;
 | 
					 | 
				
			||||||
				while ( left && currtok.Type != TokType::Attribute_Close )
 | 
									while ( left && currtok.Type != TokType::Attribute_Close )
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					eat( currtok.Type );
 | 
										eat( currtok.Type );
 | 
				
			||||||
@@ -7612,9 +7642,8 @@ namespace parser
 | 
				
			|||||||
				eat( TokType::Attribute_Close );
 | 
									eat( TokType::Attribute_Close );
 | 
				
			||||||
				// [[ <Content> ]]
 | 
									// [[ <Content> ]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			s32 len = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )start.Text;
 | 
									len = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )start.Text;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					 | 
				
			||||||
			else if ( check( TokType::Decl_GNU_Attribute ) )
 | 
								else if ( check( TokType::Decl_GNU_Attribute ) )
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				eat( TokType::Decl_GNU_Attribute );
 | 
									eat( TokType::Decl_GNU_Attribute );
 | 
				
			||||||
@@ -7622,7 +7651,6 @@ namespace parser
 | 
				
			|||||||
				eat( TokType::Capture_Start );
 | 
									eat( TokType::Capture_Start );
 | 
				
			||||||
				// __attribute__((
 | 
									// __attribute__((
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			start = currtok;
 | 
					 | 
				
			||||||
				while ( left && currtok.Type != TokType::Capture_End )
 | 
									while ( left && currtok.Type != TokType::Capture_End )
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					eat( currtok.Type );
 | 
										eat( currtok.Type );
 | 
				
			||||||
@@ -7633,16 +7661,14 @@ namespace parser
 | 
				
			|||||||
				eat( TokType::Capture_End );
 | 
									eat( TokType::Capture_End );
 | 
				
			||||||
				// __attribute__(( <Content> ))
 | 
									// __attribute__(( <Content> ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			s32 len = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )start.Text;
 | 
									len = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )start.Text;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					 | 
				
			||||||
			else if ( check( TokType::Decl_MSVC_Attribute ) )
 | 
								else if ( check( TokType::Decl_MSVC_Attribute ) )
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				eat( TokType::Decl_MSVC_Attribute );
 | 
									eat( TokType::Decl_MSVC_Attribute );
 | 
				
			||||||
				eat( TokType::Capture_Start );
 | 
									eat( TokType::Capture_Start );
 | 
				
			||||||
				// __declspec(
 | 
									// __declspec(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			start = currtok;
 | 
					 | 
				
			||||||
				while ( left && currtok.Type != TokType::Capture_End )
 | 
									while ( left && currtok.Type != TokType::Capture_End )
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					eat( currtok.Type );
 | 
										eat( currtok.Type );
 | 
				
			||||||
@@ -7652,14 +7678,33 @@ namespace parser
 | 
				
			|||||||
				eat( TokType::Capture_End );
 | 
									eat( TokType::Capture_End );
 | 
				
			||||||
				// __declspec( <Content> )
 | 
									// __declspec( <Content> )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			s32 len = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )start.Text;
 | 
									len = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )start.Text;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					 | 
				
			||||||
			else if ( currtok.is_attribute() )
 | 
								else if ( currtok.is_attribute() )
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				eat( currtok.Type );
 | 
									eat( currtok.Type );
 | 
				
			||||||
			s32 len = start.Length;
 | 
					 | 
				
			||||||
				// <Attribute>
 | 
									// <Attribute>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// If its a macro based attribute, this could be a functional macro such as Unreal's UE_DEPRECATED(...)
 | 
				
			||||||
 | 
									if ( check( TokType::Capture_Start))
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										eat( TokType::Capture_Start );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										s32 level = 0;
 | 
				
			||||||
 | 
										while (left && currtok.Type != TokType::Capture_End && level == 0)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											if (currtok.Type == TokType::Capture_Start)
 | 
				
			||||||
 | 
												++ level;
 | 
				
			||||||
 | 
											if (currtok.Type == TokType::Capture_End)
 | 
				
			||||||
 | 
												--level;
 | 
				
			||||||
 | 
											eat(currtok.Type);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										eat(TokType::Capture_End);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									len = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )start.Text;
 | 
				
			||||||
 | 
									// <Attribute> ( ... )
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ( len > 0 )
 | 
							if ( len > 0 )
 | 
				
			||||||
@@ -8036,6 +8081,24 @@ namespace parser
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
					// <Attributes> <Specifiers>
 | 
										// <Attributes> <Specifiers>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if ( currtok.is_attribute() )
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											// Unfortuantely Unreal has code where there is attirbutes before specifiers
 | 
				
			||||||
 | 
											CodeAttributes more_attributes = parse_attributes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if ( attributes )
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												String fused = String::make_reserve( GlobalAllocator, attributes->Content.length() + more_attributes->Content.length() );
 | 
				
			||||||
 | 
												fused.append_fmt( "%S %S", attributes->Content, more_attributes->Content );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												attributes->Name    = get_cached_string(fused);
 | 
				
			||||||
 | 
												attributes->Content = attributes->Name;
 | 
				
			||||||
 | 
												// <Attributes> <Specifiers> <Attributes>
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											attributes = more_attributes;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if ( currtok.Type == TokType::Operator && currtok.Text[ 0 ] == '~' )
 | 
										if ( currtok.Type == TokType::Operator && currtok.Text[ 0 ] == '~' )
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						member = parse_destructor( specifiers );
 | 
											member = parse_destructor( specifiers );
 | 
				
			||||||
@@ -8451,6 +8514,9 @@ namespace parser
 | 
				
			|||||||
			result->Type = Function_Fwd;
 | 
								result->Type = Function_Fwd;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( attributes )
 | 
				
			||||||
 | 
								result->Attributes = attributes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ( specifiers )
 | 
							if ( specifiers )
 | 
				
			||||||
			result->Specs = specifiers;
 | 
								result->Specs = specifiers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -9339,30 +9405,42 @@ namespace parser
 | 
				
			|||||||
			// or < ... >
 | 
								// or < ... >
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Ex: Unreal has this type of macro:                 vvvvvvvv
 | 
							#define CheckEndParams() \
 | 
				
			||||||
		// COREUOBJECT_API void CallFunction( FFrame& Stack, RESULT_DECL, UFunction* Function );
 | 
								(use_template_capture ? (currtok.Text[ 0 ] != '>') : (currtok.Type != TokType::Capture_End))
 | 
				
			||||||
		// This is so that a 'ValueType for the param is a preprocesor macro to support this nasty macro usage'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ( ! check(TokType::Preprocess_Macro))
 | 
							// Ex: Unreal has this type of macro:                 vvvvvvvvv
 | 
				
			||||||
 | 
							// COREUOBJECT_API void CallFunction( FFrame& Stack, RESULT_DECL, UFunction* Function );
 | 
				
			||||||
 | 
							// and:                 vvvv
 | 
				
			||||||
 | 
							// AddComponentByClass(UPARAM(meta = (AllowAbstract = "false")) TSubclassOf<UActorComponent> Class, bool bManualAttachment, ...
 | 
				
			||||||
 | 
							if ( check(TokType::Preprocess_Macro))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			type = parse_type();
 | 
								macro = parse_simple_preprocess(ETokType::Preprocess_Macro);
 | 
				
			||||||
 | 
								// ( <Macro>
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if ( currtok.Type != TokType::Comma )
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								type = parse_type( use_template_capture );
 | 
				
			||||||
			if ( type == Code::Invalid )
 | 
								if ( type == Code::Invalid )
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				Context.pop();
 | 
									Context.pop();
 | 
				
			||||||
				return CodeInvalid;
 | 
									return CodeInvalid;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// ( <ValueType>
 | 
								// ( <Macro> <ValueType>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ( check( TokType::Identifier ) )
 | 
								if ( check( TokType::Identifier ) )
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				name = currtok;
 | 
									name = currtok;
 | 
				
			||||||
				eat( TokType::Identifier );
 | 
									eat( TokType::Identifier );
 | 
				
			||||||
				// ( <ValueType> <Name>
 | 
									// ( <Macro> <ValueType> <Name>
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if ( bitfield_is_equal( u32, currtok.Flags, TF_Assign ) )
 | 
								// In template captures you can have a typename have direct assignment without a name
 | 
				
			||||||
 | 
								// typename = typename ...
 | 
				
			||||||
 | 
								// Which would result in a static value type from a struct expansion (traditionally)
 | 
				
			||||||
 | 
								if ( ( name.Text || use_template_capture ) && bitfield_is_equal( u32, currtok.Flags, TF_Assign ) )
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				eat( TokType::Operator );
 | 
									eat( TokType::Operator );
 | 
				
			||||||
					// ( <ValueType> <Name> =
 | 
									// ( <Macro> <ValueType> <Name> =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Token value_tok = currtok;
 | 
									Token value_tok = currtok;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -9373,21 +9451,32 @@ namespace parser
 | 
				
			|||||||
					return CodeInvalid;
 | 
										return CodeInvalid;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					while ( left && currtok.Type != TokType::Comma && currtok.Type != TokType::Capture_End )
 | 
									s32 capture_level  = 0;
 | 
				
			||||||
 | 
									s32 template_level = 0;
 | 
				
			||||||
 | 
									while ( left && (currtok.Type != TokType::Comma) && template_level >= 0 && CheckEndParams() || capture_level > 0 || template_level > 0 )
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
 | 
										if (currtok.Text[ 0 ] == '<')
 | 
				
			||||||
 | 
											++ template_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if (currtok.Text[ 0 ] == '>')
 | 
				
			||||||
 | 
											-- template_level;
 | 
				
			||||||
 | 
										if (currtok.Type == TokType::Operator && currtok.Text[1] == '>')
 | 
				
			||||||
 | 
											-- template_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if ( currtok.Type == ETokType::Capture_Start)
 | 
				
			||||||
 | 
											++ capture_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if ( currtok.Type == ETokType::Capture_End)
 | 
				
			||||||
 | 
											-- capture_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					value_tok.Length = ( ( sptr )currtok.Text + currtok.Length ) - ( sptr )value_tok.Text;
 | 
										value_tok.Length = ( ( sptr )currtok.Text + currtok.Length ) - ( sptr )value_tok.Text;
 | 
				
			||||||
					eat( currtok.Type );
 | 
										eat( currtok.Type );
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				value = untyped_str( strip_formatting( value_tok, strip_formatting_dont_preserve_newlines ) );
 | 
									value = untyped_str( strip_formatting( value_tok, strip_formatting_dont_preserve_newlines ) );
 | 
				
			||||||
					// ( <ValueType> <Name> = <Expression>
 | 
									// ( <Macro> <ValueType> <Name> = <Expression>
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else {
 | 
					 | 
				
			||||||
			macro = parse_simple_preprocess(ETokType::Preprocess_Macro);
 | 
					 | 
				
			||||||
			// ( <Macro>
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		CodeParam result = ( CodeParam )make_code();
 | 
							CodeParam result = ( CodeParam )make_code();
 | 
				
			||||||
		result->Type     = Parameters;
 | 
							result->Type     = Parameters;
 | 
				
			||||||
@@ -9404,10 +9493,10 @@ namespace parser
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		result->NumEntries++;
 | 
							result->NumEntries++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		while ( left && use_template_capture ? currtok.Type != TokType::Operator && currtok.Text[ 0 ] != '>' : currtok.Type != TokType::Capture_End )
 | 
							while ( check(TokType::Comma) )
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			eat( TokType::Comma );
 | 
								eat( TokType::Comma );
 | 
				
			||||||
			// ( <ValueType> <Name> = <Expression>,
 | 
								// ( <Macro> <ValueType> <Name> = <Expression>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Code type  = { nullptr };
 | 
								Code type  = { nullptr };
 | 
				
			||||||
			Code value = { nullptr };
 | 
								Code value = { nullptr };
 | 
				
			||||||
@@ -9417,18 +9506,27 @@ namespace parser
 | 
				
			|||||||
				eat( TokType::Varadic_Argument );
 | 
									eat( TokType::Varadic_Argument );
 | 
				
			||||||
				result.append( param_varadic );
 | 
									result.append( param_varadic );
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
				// ( <ValueType> <Name> = <Expression>, ...
 | 
									// ( <Macro> <ValueType> <Name> = <Expression>, ...
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ( ! check(TokType::Preprocess_Macro))
 | 
								// Ex: Unreal has this type of macro:                 vvvvvvvvv
 | 
				
			||||||
 | 
								// COREUOBJECT_API void CallFunction( FFrame& Stack, RESULT_DECL, UFunction* Function );
 | 
				
			||||||
 | 
								// and:                 vvvv
 | 
				
			||||||
 | 
								// AddComponentByClass(UPARAM(meta = (AllowAbstract = "false")) TSubclassOf<UActorComponent> Class, bool bManualAttachment, ...
 | 
				
			||||||
 | 
								if ( check(TokType::Preprocess_Macro))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				type = parse_type();
 | 
									macro = parse_simple_preprocess(ETokType::Preprocess_Macro);
 | 
				
			||||||
 | 
									// ( <Macro>
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if ( currtok.Type != TokType::Comma )
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									type = parse_type( use_template_capture );
 | 
				
			||||||
				if ( type == Code::Invalid )
 | 
									if ( type == Code::Invalid )
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Context.pop();
 | 
										Context.pop();
 | 
				
			||||||
					return CodeInvalid;
 | 
										return CodeInvalid;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				// ( <ValueType> <Name> = <Expression>, <ValueType>
 | 
									// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				name = { nullptr, 0, TokType::Invalid, false };
 | 
									name = { nullptr, 0, TokType::Invalid, false };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -9436,12 +9534,16 @@ namespace parser
 | 
				
			|||||||
				{
 | 
									{
 | 
				
			||||||
					name = currtok;
 | 
										name = currtok;
 | 
				
			||||||
					eat( TokType::Identifier );
 | 
										eat( TokType::Identifier );
 | 
				
			||||||
					// ( <ValueType> <Name> = <Expression>, <ValueType> <Name>
 | 
										// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name>
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if ( bitfield_is_equal( u32, currtok.Flags, TF_Assign ) )
 | 
									// In template captures you can have a typename have direct assignment without a name
 | 
				
			||||||
 | 
									// typename = typename ...
 | 
				
			||||||
 | 
									// Which would result in a static value type from a struct expansion (traditionally)
 | 
				
			||||||
 | 
									if ( ( name.Text || use_template_capture ) && bitfield_is_equal( u32, currtok.Flags, TF_Assign ) )
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					eat( TokType::Operator );
 | 
										eat( TokType::Operator );
 | 
				
			||||||
						// ( <ValueType> <Name> = <Expression>, <ValueType> <Name> =
 | 
										// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					Token value_tok = currtok;
 | 
										Token value_tok = currtok;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -9452,21 +9554,36 @@ namespace parser
 | 
				
			|||||||
						return CodeInvalid;
 | 
											return CodeInvalid;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						while ( left && currtok.Type != TokType::Comma && currtok.Type != TokType::Capture_End )
 | 
										s32 capture_level  = 0;
 | 
				
			||||||
 | 
										s32 template_level = 0;
 | 
				
			||||||
 | 
										while ( left
 | 
				
			||||||
 | 
										&& currtok.Type != TokType::Comma
 | 
				
			||||||
 | 
										&& template_level >= 0
 | 
				
			||||||
 | 
										&& CheckEndParams()
 | 
				
			||||||
 | 
										|| capture_level > 0 || template_level > 0 )
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
 | 
											if (currtok.Text[ 0 ] == '<')
 | 
				
			||||||
 | 
												++ template_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if (currtok.Text[ 0 ] == '>')
 | 
				
			||||||
 | 
												-- template_level;
 | 
				
			||||||
 | 
											if (currtok.Type == TokType::Operator && currtok.Text[1] == '>')
 | 
				
			||||||
 | 
												-- template_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if ( currtok.Type == ETokType::Capture_Start)
 | 
				
			||||||
 | 
												++ capture_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if ( currtok.Type == ETokType::Capture_End)
 | 
				
			||||||
 | 
												-- capture_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						value_tok.Length = ( ( sptr )currtok.Text + currtok.Length ) - ( sptr )value_tok.Text;
 | 
											value_tok.Length = ( ( sptr )currtok.Text + currtok.Length ) - ( sptr )value_tok.Text;
 | 
				
			||||||
						eat( currtok.Type );
 | 
											eat( currtok.Type );
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					value = untyped_str( strip_formatting( value_tok, strip_formatting_dont_preserve_newlines ) );
 | 
										value = untyped_str( strip_formatting( value_tok, strip_formatting_dont_preserve_newlines ) );
 | 
				
			||||||
						// ( <ValueType> <Name> = <Expression>, <ValueType> <Name> = <Expression>
 | 
										// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression>
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				}
 | 
									// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression>, ..
 | 
				
			||||||
				// ( <ValueType> <Name> = <Expression>, <ValueType> <Name> = <Expression>, ..
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else {
 | 
					 | 
				
			||||||
				macro = parse_simple_preprocess(ETokType::Preprocess_Macro);
 | 
					 | 
				
			||||||
				// ( ..., <Macro>
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			CodeParam param = ( CodeParam )make_code();
 | 
								CodeParam param = ( CodeParam )make_code();
 | 
				
			||||||
@@ -9487,7 +9604,7 @@ namespace parser
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if ( ! use_template_capture )
 | 
							if ( ! use_template_capture )
 | 
				
			||||||
			eat( TokType::Capture_End );
 | 
								eat( TokType::Capture_End );
 | 
				
			||||||
		// ( <ValueType> <Name> = <Expression>, <ValueType> <Name> = <Expression>, .. )
 | 
							// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression>, .. )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -9498,7 +9615,7 @@ namespace parser
 | 
				
			|||||||
				return CodeInvalid;
 | 
									return CodeInvalid;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			eat( TokType::Operator );
 | 
								eat( TokType::Operator );
 | 
				
			||||||
			// < <ValueType> <Name> = <Expression>, <ValueType> <Name> = <Expression>, .. >
 | 
								// < <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression>, .. >
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Context.pop();
 | 
							Context.pop();
 | 
				
			||||||
@@ -9669,18 +9786,22 @@ namespace parser
 | 
				
			|||||||
			// <
 | 
								// <
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			s32 level = 0;
 | 
								s32 level = 0;
 | 
				
			||||||
			while ( left && ( currtok.Text[ 0 ] != '>' || level > 0 ) )
 | 
								while ( left && level >= 0 && ( currtok.Text[ 0 ] != '>' || level > 0 ) )
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if ( currtok.Text[ 0 ] == '<' )
 | 
									if ( currtok.Text[ 0 ] == '<' )
 | 
				
			||||||
					level++;
 | 
										level++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if ( currtok.Text[ 0 ] == '>' )
 | 
									if ( currtok.Text[ 0 ] == '>' )
 | 
				
			||||||
					level--;
 | 
										level--;
 | 
				
			||||||
 | 
									if ( currtok.Type == TokType::Operator && currtok.Text[1] == '>')
 | 
				
			||||||
 | 
										level--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				eat( currtok.Type );
 | 
									eat( currtok.Type );
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// < <Content>
 | 
								// < <Content>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Due to the >> token, this could have been eaten early...
 | 
				
			||||||
 | 
								if (level == 0)
 | 
				
			||||||
				eat( TokType::Operator );
 | 
									eat( TokType::Operator );
 | 
				
			||||||
			// < <Content> >
 | 
								// < <Content> >
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -9955,6 +10076,9 @@ namespace parser
 | 
				
			|||||||
			// <Name> ( <Parameters> ) : <InitializerList>
 | 
								// <Name> ( <Parameters> ) : <InitializerList>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			initializer_list = untyped_str( initializer_list_tok );
 | 
								initializer_list = untyped_str( initializer_list_tok );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// TODO(Ed): Constructors can have post-fix specifiers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			body = parse_function_body();
 | 
								body = parse_function_body();
 | 
				
			||||||
			// <Name> ( <Parameters> ) : <InitializerList> { <Body> }
 | 
								// <Name> ( <Parameters> ) : <InitializerList> { <Body> }
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -9978,8 +10102,6 @@ namespace parser
 | 
				
			|||||||
			// <Name> ( <Parameters> ); <InlineCmt>
 | 
								// <Name> ( <Parameters> ); <InlineCmt>
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// TODO(Ed): Constructors can have post-fix specifiers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		CodeConstructor result = ( CodeConstructor )make_code();
 | 
							CodeConstructor result = ( CodeConstructor )make_code();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		result->Name = get_cached_string(identifier);
 | 
							result->Name = get_cached_string(identifier);
 | 
				
			||||||
@@ -10243,10 +10365,18 @@ namespace parser
 | 
				
			|||||||
						}
 | 
											}
 | 
				
			||||||
						// <Name> = <Expression>
 | 
											// <Name> = <Expression>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											// Unreal UMETA macro support
 | 
				
			||||||
 | 
											if ( currtok.Type == TokType::Preprocess_Macro )
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												eat( TokType::Preprocess_Macro );
 | 
				
			||||||
 | 
												// <Name> = <Expression> <Macro>
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						if ( currtok.Type == TokType::Comma )
 | 
											if ( currtok.Type == TokType::Comma )
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							eat( TokType::Comma );
 | 
												eat( TokType::Comma );
 | 
				
			||||||
							// <Name> = <Expression>,
 | 
												// <Name> = <Expression> <Macro>,
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						entry.Length = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )entry.Text;
 | 
											entry.Length = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )entry.Text;
 | 
				
			||||||
@@ -10800,7 +10930,7 @@ namespace parser
 | 
				
			|||||||
			s32        NumSpecifiers = 0;
 | 
								s32        NumSpecifiers = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			attributes = parse_attributes();
 | 
								attributes = parse_attributes();
 | 
				
			||||||
			// <export> template< <Parameters> > <Attributes> <specifiers.
 | 
								// <export> template< <Parameters> > <Attributes>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Specifiers Parsing
 | 
								// Specifiers Parsing
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
@@ -10850,8 +10980,121 @@ namespace parser
 | 
				
			|||||||
				// <export> template< <Parameters> > <Attributes> <Specifiers>
 | 
									// <export> template< <Parameters> > <Attributes> <Specifiers>
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// TODO(Ed) : Port over user-defined operator cast detection from
 | 
								// Possible constructor implemented at global file scope.
 | 
				
			||||||
			//parse_global_nspace (which is a source defintion version) or parse_class_struct_body (which is an inline class definition)
 | 
								{
 | 
				
			||||||
 | 
									/*
 | 
				
			||||||
 | 
										To check if a definition is for a constructor we can go straight to the opening parenthesis for its parameters
 | 
				
			||||||
 | 
										From There we work backwards to see if we come across two identifiers with the same name between an member access
 | 
				
			||||||
 | 
										:: operator, there can be template parameters on the left of the :: so we ignore those.
 | 
				
			||||||
 | 
										Whats important is that	its back to back.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										This has multiple possible faults. What we parse using this method may not filter out if something has a "return type"
 | 
				
			||||||
 | 
										This is bad since technically you could have a namespace nested into another namespace with the same name.
 | 
				
			||||||
 | 
										If this awful pattern is done the only way to distiguish with this coarse parse is to know there is no return type defined.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										We could fix this by attempting to parse a type, but we would have to have a way to have it soft fail and rollback.
 | 
				
			||||||
 | 
									*/
 | 
				
			||||||
 | 
									TokArray tokens = Context.Tokens;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									s32 idx         = tokens.Idx;
 | 
				
			||||||
 | 
									s32 level       = 0;
 | 
				
			||||||
 | 
									for ( ; idx < tokens.Arr.num(); idx++ )
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										if ( level == 0 && tokens[ idx ].Type == TokType::Capture_Start )
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									-- idx;
 | 
				
			||||||
 | 
									Token tok_right = tokens[idx];
 | 
				
			||||||
 | 
									Token tok_left  = NullToken;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (tok_right.Type != TokType::Identifier)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										// We're not dealing with a constructor if there is no identifier right before the opening of a parameter's scope.
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									-- idx;
 | 
				
			||||||
 | 
									tok_left = tokens[idx];
 | 
				
			||||||
 | 
									// <Attributes> <Specifiers> ... <Identifier>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ( tok_left.Type != TokType::Access_StaticSymbol )
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									-- idx;
 | 
				
			||||||
 | 
									tok_left = tokens[idx];
 | 
				
			||||||
 | 
									// <Attributes> <Specifiers> ... :: <Identifier>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// We search toward the left until we find the next valid identifier
 | 
				
			||||||
 | 
									s32 capture_level  = 0;
 | 
				
			||||||
 | 
									s32 template_level = 0;
 | 
				
			||||||
 | 
									while ( idx != tokens.Idx )
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										if (tok_left.Text[ 0 ] == '<')
 | 
				
			||||||
 | 
											++ template_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if (tok_left.Text[ 0 ] == '>')
 | 
				
			||||||
 | 
											-- template_level;
 | 
				
			||||||
 | 
										if (tok_left.Type == TokType::Operator && tok_left.Text[1] == '>')
 | 
				
			||||||
 | 
											-- template_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if ( template_level != 0 && tok_left.Type == ETokType::Capture_Start)
 | 
				
			||||||
 | 
											++ capture_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if ( template_level != 0 && tok_left.Type == ETokType::Capture_End)
 | 
				
			||||||
 | 
											-- capture_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if ( capture_level == 0 && template_level == 0  && tok_left.Type == TokType::Identifier )
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										-- idx;
 | 
				
			||||||
 | 
										tok_left = tokens[idx];
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									bool is_same = str_compare( tok_right.Text, tok_left.Text, tok_right.Length ) == 0;
 | 
				
			||||||
 | 
									if (tok_left.Type == TokType::Identifier && is_same)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										// We have found the pattern we desired
 | 
				
			||||||
 | 
										// <Name> :: <Name> (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										definition = parse_constructor( specifiers );
 | 
				
			||||||
 | 
										// <Attributes> <Specifiers> <Name> :: <Name> <Type> () { ... }
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// User Defined operator casts
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									bool found_operator_cast_outside_class_implmentation = false;
 | 
				
			||||||
 | 
									s32  idx = Context.Tokens.Idx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									for ( ; idx < Context.Tokens.Arr.num(); idx++ )
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Token tok = Context.Tokens[ idx ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if ( tok.Type == TokType::Identifier )
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											idx++;
 | 
				
			||||||
 | 
											tok = Context.Tokens[ idx ];
 | 
				
			||||||
 | 
											if ( tok.Type == TokType::Access_StaticSymbol )
 | 
				
			||||||
 | 
												continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if ( tok.Type == TokType::Decl_Operator )
 | 
				
			||||||
 | 
											found_operator_cast_outside_class_implmentation = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ( found_operator_cast_outside_class_implmentation )
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										definition = parse_operator_cast( specifiers );
 | 
				
			||||||
 | 
										// <Attributes> <Specifiers> <Name> :: operator <Type> () { ... }
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			definition = parse_operator_function_or_variable( expects_function, attributes, specifiers );
 | 
								definition = parse_operator_function_or_variable( expects_function, attributes, specifiers );
 | 
				
			||||||
			// <export> template< <Parameters> > <Attributes> <Specifiers> ...
 | 
								// <export> template< <Parameters> > <Attributes> <Specifiers> ...
 | 
				
			||||||
@@ -10881,7 +11124,7 @@ namespace parser
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	    The excess whitespace cannot be stripped however, because there is no semantic awareness within the first capture group.
 | 
						    The excess whitespace cannot be stripped however, because there is no semantic awareness within the first capture group.
 | 
				
			||||||
	*/
 | 
						*/
 | 
				
			||||||
	internal CodeType parse_type( bool* typedef_is_function )
 | 
						internal CodeType parse_type( bool from_template, bool* typedef_is_function )
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		push_scope();
 | 
							push_scope();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -10921,8 +11164,16 @@ namespace parser
 | 
				
			|||||||
			return CodeInvalid;
 | 
								return CodeInvalid;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( from_template && currtok.Type == TokType::Decl_Class )
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// If a value's type is being parsed from a template, class can be used instead of typename.
 | 
				
			||||||
 | 
								name = currtok;
 | 
				
			||||||
 | 
								eat(TokType::Decl_Class);
 | 
				
			||||||
 | 
								// <class>
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// All kinds of nonsense can makeup a type signature, first we check for a in-place definition of a class, enum, struct, or union
 | 
							// All kinds of nonsense can makeup a type signature, first we check for a in-place definition of a class, enum, struct, or union
 | 
				
			||||||
		if ( currtok.Type == TokType::Decl_Class || currtok.Type == TokType::Decl_Enum || currtok.Type == TokType::Decl_Struct
 | 
							else if ( currtok.Type == TokType::Decl_Class || currtok.Type == TokType::Decl_Enum || currtok.Type == TokType::Decl_Struct
 | 
				
			||||||
		     || currtok.Type == TokType::Decl_Union )
 | 
							     || currtok.Type == TokType::Decl_Union )
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			eat( currtok.Type );
 | 
								eat( currtok.Type );
 | 
				
			||||||
@@ -11429,7 +11680,7 @@ namespace parser
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				type = parse_type( &is_function );
 | 
									type = parse_type( false, &is_function );
 | 
				
			||||||
			// <ModuleFalgs> typedef <UnderlyingType>
 | 
								// <ModuleFalgs> typedef <UnderlyingType>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ( check( TokType::Identifier ) )
 | 
								if ( check( TokType::Identifier ) )
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -121,6 +121,20 @@
 | 
				
			|||||||
		</Expand>
 | 
							</Expand>
 | 
				
			||||||
	</Type>
 | 
						</Type>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<Type Name="gen::AST_Constructor">
 | 
				
			||||||
 | 
							<DisplayString>{Name} Type: {Type}</DisplayString>
 | 
				
			||||||
 | 
							<Expand>
 | 
				
			||||||
 | 
								<Item Name="InlineCmt">InlineCmt</Item>
 | 
				
			||||||
 | 
								<Item Name="Specs">Specs</Item>
 | 
				
			||||||
 | 
								<Item Name="InitializerList">InitializerList</Item>
 | 
				
			||||||
 | 
								<Item Name="Params">Params</Item>
 | 
				
			||||||
 | 
								<Item Name="Body">Body</Item>
 | 
				
			||||||
 | 
								<Item Name="Parent">Parent</Item>
 | 
				
			||||||
 | 
								<Item Name="Prev">Prev</Item>
 | 
				
			||||||
 | 
								<Item Name="Next">Next</Item>
 | 
				
			||||||
 | 
							</Expand>
 | 
				
			||||||
 | 
						</Type>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<Type Name="gen::AST_Class">
 | 
						<Type Name="gen::AST_Class">
 | 
				
			||||||
		<DisplayString>{Name} Type: {Type}</DisplayString>
 | 
							<DisplayString>{Name} Type: {Type}</DisplayString>
 | 
				
			||||||
		<Expand>
 | 
							<Expand>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user