Can parse AActor with gencpp
This commit is contained in:
parent
48d21ddd15
commit
6e3dfb70be
@ -9,7 +9,7 @@ UGasaAttributeSet::UGasaAttributeSet()
|
||||
{
|
||||
InitHealth( 100.f );
|
||||
InitMaxHealth( 100.f );
|
||||
InitMana( ( 50.f ) );
|
||||
InitMana( 50.f );
|
||||
InitMaxMana( 50.f );
|
||||
}
|
||||
|
||||
|
@ -26,16 +26,12 @@ int gen_main()
|
||||
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_ue_deprecated = txt("UE_DEPRECATED(");
|
||||
StrC str_ufunction = txt("UFUNCTION(");
|
||||
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_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_core_object_api = txt("COREUOBJECT_API");
|
||||
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(");
|
||||
@ -45,20 +41,36 @@ int gen_main()
|
||||
StrC str_result_decl = txt("RESULT_DECL");
|
||||
StrC str_property_binding_implementation = txt("PROPERTY_BINDING_IMPLEMENTATION(");
|
||||
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_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_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_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_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));
|
||||
@ -68,11 +80,31 @@ int gen_main()
|
||||
PreprocessorDefines.append( get_cached_string(str_result_decl));
|
||||
PreprocessorDefines.append( get_cached_string(str_property_binding_implementation));
|
||||
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 \
|
||||
"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 });
|
||||
|
||||
log_fmt("\n\n");
|
||||
@ -93,22 +125,63 @@ int gen_main()
|
||||
case CodeT::Function_Fwd:
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define path_UObject \
|
||||
R"(C:\projects\Unreal\Surgo\UE\Engine\Source\Runtime\CoreUObject\Public\UObject\Object.h)"
|
||||
|
||||
#if 0
|
||||
content = file_read_contents( GlobalAllocator, true, path_UObject );
|
||||
CodeBody parsed_uobject = parse_global_body( StrC { content.size, (char const*)content.data });
|
||||
|
||||
log_fmt("\n\n");
|
||||
for ( Code gcode : parsed_uobject )
|
||||
{
|
||||
if ( gcode->Type == CodeT::Class )
|
||||
{
|
||||
log_fmt("Class %S - Definitions:\n", gcode->Name);
|
||||
// log_fmt("%s\n", gcode->to_string() );
|
||||
|
||||
if (gcode->Body->Type != CodeT::Class_Body)
|
||||
continue;
|
||||
for ( Code class_code : gcode->Body->cast<CodeBody>() )
|
||||
{
|
||||
switch ( class_code->Type )
|
||||
{
|
||||
case CodeT::Constructor:
|
||||
case CodeT::Constructor_Fwd:
|
||||
case CodeT::Variable:
|
||||
case CodeT::Function:
|
||||
case CodeT::Function_Fwd:
|
||||
if ( class_code->Name )
|
||||
{
|
||||
log_fmt("%s\n", class_code->Name );
|
||||
// log_fmt("%s\n", class_code->to_string() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define path_AActor \
|
||||
R"(C:\projects\Unreal\Surgo\UE\Engine\Source\Runtime\Engine\Classes\GameFramework\Actor.h)"
|
||||
|
||||
#if 0
|
||||
content = file_read_contents( GlobalAllocator, true, path_AActor );
|
||||
CodeBody parsed_aactor = parse_global_body( StrC { content.size, (char const*)content.data });
|
||||
|
||||
log_fmt("\n\n");
|
||||
for ( Code gcode : parsed_aactor )
|
||||
{
|
||||
if ( gcode->Type == CodeT::Class )
|
||||
{
|
||||
@ -121,8 +194,8 @@ int gen_main()
|
||||
switch ( class_code->Type )
|
||||
{
|
||||
case CodeT::Variable:
|
||||
case CodeT::Function:
|
||||
case CodeT::Function_Fwd:
|
||||
// case CodeT::Function:
|
||||
// case CodeT::Function_Fwd:
|
||||
if ( 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();
|
||||
return 0;
|
||||
|
@ -114,7 +114,7 @@ void gen_UGasaAttributeSet()
|
||||
{
|
||||
InitHealth( 100.f );
|
||||
InitMaxHealth( 100.f );
|
||||
InitMana(( 50.f ));
|
||||
InitMana( 50.f );
|
||||
InitMaxMana( 50.f );
|
||||
}
|
||||
));
|
||||
|
@ -1588,7 +1588,12 @@ void CodeConstructor::to_string_def( String& result )
|
||||
void CodeConstructor::to_string_fwd( String& result )
|
||||
{
|
||||
AST* ClassStructParent = ast->Parent->Parent;
|
||||
if (ClassStructParent) {
|
||||
result.append( ClassStructParent->Name );
|
||||
}
|
||||
else {
|
||||
result.append( ast->Name );
|
||||
}
|
||||
|
||||
if ( ast->Params )
|
||||
result.append_fmt( "( %S )", ast->Params.to_string() );
|
||||
@ -2273,10 +2278,9 @@ void CodeParam::to_string( String& result )
|
||||
{
|
||||
if ( ast->Macro )
|
||||
{
|
||||
// Were using the convention that if the value type is a macro we ignore everything else
|
||||
// Related to parsing: ( <macro>, ... )
|
||||
result.append( ast->Macro.ast->Content );
|
||||
return;
|
||||
// Could also be: ( <macro> <type <name>, ... )
|
||||
}
|
||||
|
||||
if ( ast->Name )
|
||||
@ -2285,8 +2289,9 @@ void CodeParam::to_string( String& result )
|
||||
result.append_fmt( " %S", ast->Name );
|
||||
else
|
||||
result.append_fmt( " %S %S", ast->ValueType.to_string(), ast->Name );
|
||||
|
||||
}
|
||||
else
|
||||
else if ( ast->ValueType )
|
||||
result.append_fmt( " %S", ast->ValueType.to_string() );
|
||||
|
||||
if ( ast->Value )
|
||||
@ -5599,7 +5604,14 @@ namespace parser
|
||||
{
|
||||
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
|
||||
{
|
||||
@ -5700,6 +5712,11 @@ namespace parser
|
||||
__Attributes_Start,
|
||||
API_Export,
|
||||
API_Import,
|
||||
UE_DEPRECATED,
|
||||
UMG_API,
|
||||
COREUOBJECT_API,
|
||||
ENGINE_API,
|
||||
GASA_API,
|
||||
NumTokens
|
||||
};
|
||||
|
||||
@ -5803,6 +5820,11 @@ namespace parser
|
||||
{ sizeof( "__attrib_start__" ), "__attrib_start__" },
|
||||
{ sizeof( "GEN_API_Export_Code" ), "GEN_API_Export_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 ];
|
||||
}
|
||||
@ -5982,7 +6004,7 @@ namespace parser
|
||||
}
|
||||
};
|
||||
|
||||
global Arena_64KB defines_map_arena;
|
||||
global Arena_128KB defines_map_arena;
|
||||
global HashTable< StrC > defines;
|
||||
global Array< Token > Tokens;
|
||||
|
||||
@ -6283,6 +6305,11 @@ namespace parser
|
||||
token.Flags |= TF_AccessSpecifier;
|
||||
}
|
||||
|
||||
if ( type > TokType::__Attributes_Start )
|
||||
{
|
||||
token.Flags |= TF_Attribute;
|
||||
}
|
||||
|
||||
if ( type == ETokType::Decl_Extern_Linkage )
|
||||
{
|
||||
SkipWhitespace();
|
||||
@ -7174,7 +7201,7 @@ namespace parser
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
@ -7256,7 +7283,7 @@ namespace parser
|
||||
internal CodeStruct parse_struct( bool inplace_def = false );
|
||||
internal CodeVar parse_variable();
|
||||
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 CodeUnion parse_union( bool inplace_def = false );
|
||||
internal CodeUsing parse_using();
|
||||
@ -7594,15 +7621,18 @@ namespace parser
|
||||
{
|
||||
push_scope();
|
||||
|
||||
Token start = NullToken;
|
||||
Token start = currtok;
|
||||
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 ) )
|
||||
{
|
||||
eat( TokType::Attribute_Open );
|
||||
// [[
|
||||
|
||||
start = currtok;
|
||||
while ( left && currtok.Type != TokType::Attribute_Close )
|
||||
{
|
||||
eat( currtok.Type );
|
||||
@ -7612,9 +7642,8 @@ namespace parser
|
||||
eat( TokType::Attribute_Close );
|
||||
// [[ <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 ) )
|
||||
{
|
||||
eat( TokType::Decl_GNU_Attribute );
|
||||
@ -7622,7 +7651,6 @@ namespace parser
|
||||
eat( TokType::Capture_Start );
|
||||
// __attribute__((
|
||||
|
||||
start = currtok;
|
||||
while ( left && currtok.Type != TokType::Capture_End )
|
||||
{
|
||||
eat( currtok.Type );
|
||||
@ -7633,16 +7661,14 @@ namespace parser
|
||||
eat( TokType::Capture_End );
|
||||
// __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 ) )
|
||||
{
|
||||
eat( TokType::Decl_MSVC_Attribute );
|
||||
eat( TokType::Capture_Start );
|
||||
// __declspec(
|
||||
|
||||
start = currtok;
|
||||
while ( left && currtok.Type != TokType::Capture_End )
|
||||
{
|
||||
eat( currtok.Type );
|
||||
@ -7652,14 +7678,33 @@ namespace parser
|
||||
eat( TokType::Capture_End );
|
||||
// __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() )
|
||||
{
|
||||
eat( currtok.Type );
|
||||
s32 len = start.Length;
|
||||
// <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 )
|
||||
@ -8036,6 +8081,24 @@ namespace parser
|
||||
}
|
||||
// <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 ] == '~' )
|
||||
{
|
||||
member = parse_destructor( specifiers );
|
||||
@ -8451,6 +8514,9 @@ namespace parser
|
||||
result->Type = Function_Fwd;
|
||||
}
|
||||
|
||||
if ( attributes )
|
||||
result->Attributes = attributes;
|
||||
|
||||
if ( specifiers )
|
||||
result->Specs = specifiers;
|
||||
|
||||
@ -9339,30 +9405,42 @@ namespace parser
|
||||
// or < ... >
|
||||
}
|
||||
|
||||
// Ex: Unreal has this type of macro: vvvvvvvv
|
||||
// COREUOBJECT_API void CallFunction( FFrame& Stack, RESULT_DECL, UFunction* Function );
|
||||
// This is so that a 'ValueType for the param is a preprocesor macro to support this nasty macro usage'
|
||||
#define CheckEndParams() \
|
||||
(use_template_capture ? (currtok.Text[ 0 ] != '>') : (currtok.Type != TokType::Capture_End))
|
||||
|
||||
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 )
|
||||
{
|
||||
Context.pop();
|
||||
return CodeInvalid;
|
||||
}
|
||||
// ( <ValueType>
|
||||
// ( <Macro> <ValueType>
|
||||
|
||||
if ( check( TokType::Identifier ) )
|
||||
{
|
||||
name = currtok;
|
||||
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 );
|
||||
// ( <ValueType> <Name> =
|
||||
// ( <Macro> <ValueType> <Name> =
|
||||
|
||||
Token value_tok = currtok;
|
||||
|
||||
@ -9373,21 +9451,32 @@ namespace parser
|
||||
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;
|
||||
eat( currtok.Type );
|
||||
}
|
||||
|
||||
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();
|
||||
result->Type = Parameters;
|
||||
@ -9404,10 +9493,10 @@ namespace parser
|
||||
|
||||
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 );
|
||||
// ( <ValueType> <Name> = <Expression>,
|
||||
// ( <Macro> <ValueType> <Name> = <Expression>,
|
||||
|
||||
Code type = { nullptr };
|
||||
Code value = { nullptr };
|
||||
@ -9417,18 +9506,27 @@ namespace parser
|
||||
eat( TokType::Varadic_Argument );
|
||||
result.append( param_varadic );
|
||||
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 )
|
||||
{
|
||||
Context.pop();
|
||||
return CodeInvalid;
|
||||
}
|
||||
// ( <ValueType> <Name> = <Expression>, <ValueType>
|
||||
// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType>
|
||||
|
||||
name = { nullptr, 0, TokType::Invalid, false };
|
||||
|
||||
@ -9436,12 +9534,16 @@ namespace parser
|
||||
{
|
||||
name = currtok;
|
||||
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 );
|
||||
// ( <ValueType> <Name> = <Expression>, <ValueType> <Name> =
|
||||
// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> =
|
||||
|
||||
Token value_tok = currtok;
|
||||
|
||||
@ -9452,21 +9554,36 @@ namespace parser
|
||||
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;
|
||||
eat( currtok.Type );
|
||||
}
|
||||
|
||||
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>
|
||||
}
|
||||
}
|
||||
// ( <ValueType> <Name> = <Expression>, <ValueType> <Name> = <Expression>, ..
|
||||
}
|
||||
else {
|
||||
macro = parse_simple_preprocess(ETokType::Preprocess_Macro);
|
||||
// ( ..., <Macro>
|
||||
// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression>, ..
|
||||
}
|
||||
|
||||
CodeParam param = ( CodeParam )make_code();
|
||||
@ -9487,7 +9604,7 @@ namespace parser
|
||||
|
||||
if ( ! use_template_capture )
|
||||
eat( TokType::Capture_End );
|
||||
// ( <ValueType> <Name> = <Expression>, <ValueType> <Name> = <Expression>, .. )
|
||||
// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression>, .. )
|
||||
|
||||
else
|
||||
{
|
||||
@ -9498,7 +9615,7 @@ namespace parser
|
||||
return CodeInvalid;
|
||||
}
|
||||
eat( TokType::Operator );
|
||||
// < <ValueType> <Name> = <Expression>, <ValueType> <Name> = <Expression>, .. >
|
||||
// < <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression>, .. >
|
||||
}
|
||||
|
||||
Context.pop();
|
||||
@ -9669,18 +9786,22 @@ namespace parser
|
||||
// <
|
||||
|
||||
s32 level = 0;
|
||||
while ( left && ( currtok.Text[ 0 ] != '>' || level > 0 ) )
|
||||
while ( left && level >= 0 && ( currtok.Text[ 0 ] != '>' || level > 0 ) )
|
||||
{
|
||||
if ( currtok.Text[ 0 ] == '<' )
|
||||
level++;
|
||||
|
||||
if ( currtok.Text[ 0 ] == '>' )
|
||||
level--;
|
||||
if ( currtok.Type == TokType::Operator && currtok.Text[1] == '>')
|
||||
level--;
|
||||
|
||||
eat( currtok.Type );
|
||||
}
|
||||
// < <Content>
|
||||
|
||||
// Due to the >> token, this could have been eaten early...
|
||||
if (level == 0)
|
||||
eat( TokType::Operator );
|
||||
// < <Content> >
|
||||
|
||||
@ -9955,6 +10076,9 @@ namespace parser
|
||||
// <Name> ( <Parameters> ) : <InitializerList>
|
||||
|
||||
initializer_list = untyped_str( initializer_list_tok );
|
||||
|
||||
// TODO(Ed): Constructors can have post-fix specifiers
|
||||
|
||||
body = parse_function_body();
|
||||
// <Name> ( <Parameters> ) : <InitializerList> { <Body> }
|
||||
}
|
||||
@ -9978,8 +10102,6 @@ namespace parser
|
||||
// <Name> ( <Parameters> ); <InlineCmt>
|
||||
}
|
||||
|
||||
// TODO(Ed): Constructors can have post-fix specifiers
|
||||
|
||||
CodeConstructor result = ( CodeConstructor )make_code();
|
||||
|
||||
result->Name = get_cached_string(identifier);
|
||||
@ -10243,10 +10365,18 @@ namespace parser
|
||||
}
|
||||
// <Name> = <Expression>
|
||||
|
||||
|
||||
// Unreal UMETA macro support
|
||||
if ( currtok.Type == TokType::Preprocess_Macro )
|
||||
{
|
||||
eat( TokType::Preprocess_Macro );
|
||||
// <Name> = <Expression> <Macro>
|
||||
}
|
||||
|
||||
if ( currtok.Type == TokType::Comma )
|
||||
{
|
||||
eat( TokType::Comma );
|
||||
// <Name> = <Expression>,
|
||||
// <Name> = <Expression> <Macro>,
|
||||
}
|
||||
|
||||
entry.Length = ( ( sptr )prevtok.Text + prevtok.Length ) - ( sptr )entry.Text;
|
||||
@ -10800,7 +10930,7 @@ namespace parser
|
||||
s32 NumSpecifiers = 0;
|
||||
|
||||
attributes = parse_attributes();
|
||||
// <export> template< <Parameters> > <Attributes> <specifiers.
|
||||
// <export> template< <Parameters> > <Attributes>
|
||||
|
||||
// Specifiers Parsing
|
||||
{
|
||||
@ -10850,8 +10980,121 @@ namespace parser
|
||||
// <export> template< <Parameters> > <Attributes> <Specifiers>
|
||||
}
|
||||
|
||||
// TODO(Ed) : Port over user-defined operator cast detection from
|
||||
//parse_global_nspace (which is a source defintion version) or parse_class_struct_body (which is an inline class definition)
|
||||
// Possible constructor implemented at global file scope.
|
||||
{
|
||||
/*
|
||||
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 );
|
||||
// <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.
|
||||
*/
|
||||
internal CodeType parse_type( bool* typedef_is_function )
|
||||
internal CodeType parse_type( bool from_template, bool* typedef_is_function )
|
||||
{
|
||||
push_scope();
|
||||
|
||||
@ -10921,8 +11164,16 @@ namespace parser
|
||||
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
|
||||
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 )
|
||||
{
|
||||
eat( currtok.Type );
|
||||
@ -11429,7 +11680,7 @@ namespace parser
|
||||
}
|
||||
}
|
||||
else
|
||||
type = parse_type( &is_function );
|
||||
type = parse_type( false, &is_function );
|
||||
// <ModuleFalgs> typedef <UnderlyingType>
|
||||
|
||||
if ( check( TokType::Identifier ) )
|
||||
|
@ -121,6 +121,20 @@
|
||||
</Expand>
|
||||
</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">
|
||||
<DisplayString>{Name} Type: {Type}</DisplayString>
|
||||
<Expand>
|
||||
|
Loading…
Reference in New Issue
Block a user