mirror of
https://github.com/Ed94/gencpp.git
synced 2024-12-22 15:54:45 -08:00
Added extern linkage bodies to upfront constructors, more work on parsing constructors
- Made some more parsing helper functions - Got initial prototype of parse_friend done - getting ready to complete prototype of parse_function
This commit is contained in:
parent
e50e9e094e
commit
d541b33b22
537
project/gen.cpp
537
project/gen.cpp
@ -65,6 +65,7 @@ namespace gen
|
|||||||
# define AST_BODY_CLASS_UNALLOWED_TYPES \
|
# define AST_BODY_CLASS_UNALLOWED_TYPES \
|
||||||
case Class_Body: \
|
case Class_Body: \
|
||||||
case Enum_Body: \
|
case Enum_Body: \
|
||||||
|
case Extern_Linkage: \
|
||||||
case Friend: \
|
case Friend: \
|
||||||
case Function_Body: \
|
case Function_Body: \
|
||||||
case Function_Fwd: \
|
case Function_Fwd: \
|
||||||
@ -84,6 +85,7 @@ namespace gen
|
|||||||
case Access_Private: \
|
case Access_Private: \
|
||||||
case Class_Body: \
|
case Class_Body: \
|
||||||
case Enum_Body: \
|
case Enum_Body: \
|
||||||
|
case Extern_Linkage: \
|
||||||
case Friend: \
|
case Friend: \
|
||||||
case Function_Body: \
|
case Function_Body: \
|
||||||
case Function_Fwd: \
|
case Function_Fwd: \
|
||||||
@ -135,8 +137,27 @@ namespace gen
|
|||||||
case Struct_Body: \
|
case Struct_Body: \
|
||||||
case Typename:
|
case Typename:
|
||||||
|
|
||||||
|
# define AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES \
|
||||||
|
case Access_Public: \
|
||||||
|
case Access_Protected: \
|
||||||
|
case Access_Private: \
|
||||||
|
case Class_Body: \
|
||||||
|
case Enum_Body: \
|
||||||
|
case Execution: \
|
||||||
|
case Friend: \
|
||||||
|
case Function_Body: \
|
||||||
|
case Global_Body: \
|
||||||
|
case Namespace_Body: \
|
||||||
|
case Operator_Member: \
|
||||||
|
case Operator_Member_Fwd: \
|
||||||
|
case Parameters: \
|
||||||
|
case Specifiers: \
|
||||||
|
case Struct_Body: \
|
||||||
|
case Typename:
|
||||||
|
|
||||||
# define AST_BODY_STRUCT_UNALLOWED_TYPES \
|
# define AST_BODY_STRUCT_UNALLOWED_TYPES \
|
||||||
case Enum_Body: \
|
case Enum_Body: \
|
||||||
|
case Extern_Linkage: \
|
||||||
case Execution: \
|
case Execution: \
|
||||||
case Function_Body: \
|
case Function_Body: \
|
||||||
case Global_Body: \
|
case Global_Body: \
|
||||||
@ -206,7 +227,7 @@ namespace gen
|
|||||||
{
|
{
|
||||||
AST_BODY_CLASS_UNALLOWED_TYPES
|
AST_BODY_CLASS_UNALLOWED_TYPES
|
||||||
{
|
{
|
||||||
log_failure( "AST::add: Cannot add an AST to a class body." );
|
log_failure( "AST::add: Cannot add %s to a class body.", other->type_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,6 +244,23 @@ namespace gen
|
|||||||
log_failure( "AST::add: Cannot add an AST to an enum forward declaration." );
|
log_failure( "AST::add: Cannot add an AST to an enum forward declaration." );
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
case Extern_Linkage:
|
||||||
|
log_failure( "AST::add: Cannot add an AST to an extern linkage, only to its body." );
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case Extern_Linkage_Body:
|
||||||
|
switch ( other->Type )
|
||||||
|
{
|
||||||
|
AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES
|
||||||
|
{
|
||||||
|
log_failure( "AST::add: Cannot add %s to an extern linkage body.", other->type_str() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Enum_Body:
|
case Enum_Body:
|
||||||
if ( other->Type != Untyped )
|
if ( other->Type != Untyped )
|
||||||
{
|
{
|
||||||
@ -252,7 +290,7 @@ namespace gen
|
|||||||
{
|
{
|
||||||
AST_BODY_FUNCTION_UNALLOWED_TYPES
|
AST_BODY_FUNCTION_UNALLOWED_TYPES
|
||||||
{
|
{
|
||||||
log_failure( "AST::add: Cannot add an AST to a function body." );
|
log_failure( "AST::add: Cannot add %s to a function body.", other->type_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +308,7 @@ namespace gen
|
|||||||
{
|
{
|
||||||
AST_BODY_GLOBAL_UNALLOWED_TYPES
|
AST_BODY_GLOBAL_UNALLOWED_TYPES
|
||||||
{
|
{
|
||||||
log_failure( "AST::add: Cannot add an AST to a global body." );
|
log_failure( "AST::add: Cannot add %s to a global body.", other->type_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +317,6 @@ namespace gen
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case Namespace:
|
case Namespace:
|
||||||
if ( Type != Global_Body )
|
if ( Type != Global_Body )
|
||||||
{
|
{
|
||||||
@ -292,7 +329,7 @@ namespace gen
|
|||||||
{
|
{
|
||||||
AST_BODY_NAMESPACE_UNALLOWED_TYPES
|
AST_BODY_NAMESPACE_UNALLOWED_TYPES
|
||||||
{
|
{
|
||||||
log_failure( "AST::add: Cannot add an AST to a namespace body." );
|
log_failure( "AST::add: Cannot add %s to a namespace body.", other->type_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,7 +363,7 @@ namespace gen
|
|||||||
{
|
{
|
||||||
AST_BODY_STRUCT_UNALLOWED_TYPES
|
AST_BODY_STRUCT_UNALLOWED_TYPES
|
||||||
{
|
{
|
||||||
log_failure( "AST::add: Cannot add to a struct body." );
|
log_failure( "AST::add: Cannot add %s to a struct body.", other->type_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,10 +421,6 @@ namespace gen
|
|||||||
case Access_Public:
|
case Access_Public:
|
||||||
case Access_Protected:
|
case Access_Protected:
|
||||||
case Access_Private:
|
case Access_Private:
|
||||||
case Class_Fwd:
|
|
||||||
case Enum_Fwd:
|
|
||||||
case Function_Fwd:
|
|
||||||
case Specifiers:
|
|
||||||
// Can just be the same, as its a cached string.
|
// Can just be the same, as its a cached string.
|
||||||
result->Content = Content;
|
result->Content = Content;
|
||||||
return result;
|
return result;
|
||||||
@ -395,16 +428,28 @@ namespace gen
|
|||||||
// The main purpose of this is to make sure entires in the AST are unique,
|
// The main purpose of this is to make sure entires in the AST are unique,
|
||||||
// So that we can assign the new parent without corrupting the existing AST.
|
// So that we can assign the new parent without corrupting the existing AST.
|
||||||
case Class:
|
case Class:
|
||||||
|
case Class_Fwd:
|
||||||
case Class_Body:
|
case Class_Body:
|
||||||
case Enum:
|
case Enum:
|
||||||
|
case Enum_Fwd:
|
||||||
case Enum_Body:
|
case Enum_Body:
|
||||||
|
case Enum_Class:
|
||||||
|
case Enum_Class_Fwd:
|
||||||
|
case Extern_Linkage:
|
||||||
|
case Extern_Linkage_Body:
|
||||||
case Friend:
|
case Friend:
|
||||||
|
case Function:
|
||||||
|
case Function_Fwd:
|
||||||
|
case Function_Body:
|
||||||
case Global_Body:
|
case Global_Body:
|
||||||
case Namespace:
|
case Namespace:
|
||||||
case Namespace_Body:
|
case Namespace_Body:
|
||||||
|
case Operator:
|
||||||
|
case Operator_Fwd:
|
||||||
|
case Operator_Member:
|
||||||
|
case Operator_Member_Fwd:
|
||||||
case Parameters:
|
case Parameters:
|
||||||
case Function:
|
case Specifiers:
|
||||||
case Function_Body:
|
|
||||||
case Struct:
|
case Struct:
|
||||||
case Struct_Fwd:
|
case Struct_Fwd:
|
||||||
case Struct_Body:
|
case Struct_Body:
|
||||||
@ -412,6 +457,7 @@ namespace gen
|
|||||||
case Typedef:
|
case Typedef:
|
||||||
case Typename:
|
case Typename:
|
||||||
case Using:
|
case Using:
|
||||||
|
case Using_Namespace:
|
||||||
s32 index = 0;
|
s32 index = 0;
|
||||||
s32 left = num_entries();
|
s32 left = num_entries();
|
||||||
while ( left -- )
|
while ( left -- )
|
||||||
@ -532,6 +578,10 @@ namespace gen
|
|||||||
result = string_append_fmt( result, "enum class %s : %s;\n", Name, underlying_type()->to_string() );
|
result = string_append_fmt( result, "enum class %s : %s;\n", Name, underlying_type()->to_string() );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Extern_Linkage:
|
||||||
|
result = string_append_fmt( result, "extern %s\n{\n%s\n};\n", Name, body()->to_string() );
|
||||||
|
break;
|
||||||
|
|
||||||
case Friend:
|
case Friend:
|
||||||
result = string_append_fmt( result, "friend %s;\n", Entries[0]->to_string() );
|
result = string_append_fmt( result, "friend %s;\n", Entries[0]->to_string() );
|
||||||
break;
|
break;
|
||||||
@ -773,6 +823,7 @@ namespace gen
|
|||||||
|
|
||||||
case Class_Body:
|
case Class_Body:
|
||||||
case Enum_Body:
|
case Enum_Body:
|
||||||
|
case Extern_Linkage_Body:
|
||||||
case Function_Body:
|
case Function_Body:
|
||||||
case Global_Body:
|
case Global_Body:
|
||||||
case Namespace_Body:
|
case Namespace_Body:
|
||||||
@ -1581,6 +1632,32 @@ namespace gen
|
|||||||
result = make_code();
|
result = make_code();
|
||||||
result->Type = ECode::Execution;
|
result->Type = ECode::Execution;
|
||||||
|
|
||||||
|
result->add_entry( untyped_code );
|
||||||
|
|
||||||
|
result.lock();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code def_extern_linkage( s32 length, char const* name, Code body )
|
||||||
|
{
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
|
name_check( def_extern_linkage, length, name );
|
||||||
|
null_check( def_extern_linkage, body );
|
||||||
|
|
||||||
|
if ( body->Type != Extern_Linkage_Body || body->Type != Untyped )
|
||||||
|
{
|
||||||
|
log_failure("gen::def_extern_linkage: body is not of extern_linkage or untyped type %s", body->debug_str());
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code
|
||||||
|
result = make_code();
|
||||||
|
result->Type = Extern_Linkage;
|
||||||
|
result->Name = get_cached_string( name, length );
|
||||||
|
|
||||||
|
result->add_entry( body );
|
||||||
|
|
||||||
result.lock();
|
result.lock();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1697,18 +1774,18 @@ namespace gen
|
|||||||
name_check( def_namespace, length, name );
|
name_check( def_namespace, length, name );
|
||||||
null_check( def_namespace, body );
|
null_check( def_namespace, body );
|
||||||
|
|
||||||
Code
|
|
||||||
result = make_code();
|
|
||||||
result->Type = Namespace;
|
|
||||||
result->Name = get_cached_string( name, length );
|
|
||||||
result->Entries = make_code_entries();
|
|
||||||
|
|
||||||
if ( body->Type != Namespace_Body || body->Type != Untyped )
|
if ( body->Type != Namespace_Body || body->Type != Untyped )
|
||||||
{
|
{
|
||||||
log_failure("gen::def_namespace: body is not of namespace or untyped type %s", body->debug_str());
|
log_failure("gen::def_namespace: body is not of namespace or untyped type %s", body->debug_str());
|
||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Code
|
||||||
|
result = make_code();
|
||||||
|
result->Type = Namespace;
|
||||||
|
result->Name = get_cached_string( name, length );
|
||||||
|
result->Entries = make_code_entries();
|
||||||
|
|
||||||
result->add_entry( body );
|
result->add_entry( body );
|
||||||
|
|
||||||
result.lock();
|
result.lock();
|
||||||
@ -1763,7 +1840,7 @@ namespace gen
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Code def_param( Code type, s32 length, char const* name )
|
Code def_param( Code type, s32 length, char const* name, Code value )
|
||||||
{
|
{
|
||||||
using namespace ECode;
|
using namespace ECode;
|
||||||
|
|
||||||
@ -1776,6 +1853,12 @@ namespace gen
|
|||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( value && value->Type != Untyped )
|
||||||
|
{
|
||||||
|
log_failure( "gen::def_param: value is not untyped - %s", value->debug_str() );
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
Code
|
Code
|
||||||
result = make_code();
|
result = make_code();
|
||||||
result->Type = Parameters;
|
result->Type = Parameters;
|
||||||
@ -1783,6 +1866,9 @@ namespace gen
|
|||||||
|
|
||||||
result->add_entry( type );
|
result->add_entry( type );
|
||||||
|
|
||||||
|
if ( value )
|
||||||
|
result->add_entry( value );
|
||||||
|
|
||||||
result.lock();
|
result.lock();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2141,6 +2227,41 @@ namespace gen
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Code def_extern_linkage_body( s32 num, ... )
|
||||||
|
{
|
||||||
|
def_body_start( def_extern_linkage_body );
|
||||||
|
|
||||||
|
Code
|
||||||
|
result = make_code();
|
||||||
|
result->Type = Extern_Linkage_Body;
|
||||||
|
|
||||||
|
va_list va;
|
||||||
|
va_start(va, num);
|
||||||
|
def_body_code_validation_start( def_extern_linkage_body, va_arg(va, Code) );
|
||||||
|
AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES
|
||||||
|
def_body_code_validation_end( def_extern_linkage_body );
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
result.lock();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code def_extern_linkage_body( s32 num, Code* codes )
|
||||||
|
{
|
||||||
|
def_body_code_array_start( def_extern_linkage_body );
|
||||||
|
|
||||||
|
Code
|
||||||
|
result = make_code();
|
||||||
|
result->Type = Extern_Linkage_Body;
|
||||||
|
|
||||||
|
def_body_code_validation_start( def_extern_linkage_body, *codes; codes++ );
|
||||||
|
AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES
|
||||||
|
def_body_code_validation_end( def_extern_linkage_body );
|
||||||
|
|
||||||
|
result.lock();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Code def_function_body( s32 num, ... )
|
Code def_function_body( s32 num, ... )
|
||||||
{
|
{
|
||||||
def_body_start( def_function_body );
|
def_body_start( def_function_body );
|
||||||
@ -2268,7 +2389,6 @@ namespace gen
|
|||||||
char const* name = va_arg(va, char const*);
|
char const* name = va_arg(va, char const*);
|
||||||
|
|
||||||
result->Name = get_cached_string( name, name_length );
|
result->Name = get_cached_string( name, name_length );
|
||||||
result->Entries = make_code_entries();
|
|
||||||
|
|
||||||
if ( type->Type != Typename )
|
if ( type->Type != Typename )
|
||||||
{
|
{
|
||||||
@ -2531,15 +2651,19 @@ namespace gen
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Code make_global_body( s32 length, char const* name, s32 num, ... )
|
Code make_global_body( s32 length, char const* name )
|
||||||
{
|
{
|
||||||
name_check( make_global_body, length, name );
|
name_check( make_global_body, length, name );
|
||||||
|
|
||||||
Code
|
Code
|
||||||
result = make_code();
|
result = make_code();
|
||||||
result->Type = ECode::Global_Body;
|
result->Type = ECode::Global_Body;
|
||||||
|
|
||||||
|
if ( length > 0 )
|
||||||
result->Name = get_cached_string( name, length );
|
result->Name = get_cached_string( name, length );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2744,6 +2868,11 @@ namespace gen
|
|||||||
sptr Length;
|
sptr Length;
|
||||||
TokType Type;
|
TokType Type;
|
||||||
bool IsAssign;
|
bool IsAssign;
|
||||||
|
|
||||||
|
operator bool()
|
||||||
|
{
|
||||||
|
return Text && Length && Type != TokType::Invalid;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TokType get_tok_type( char const* word, s32 length )
|
TokType get_tok_type( char const* word, s32 length )
|
||||||
@ -3266,6 +3395,160 @@ namespace gen
|
|||||||
# define check( Type_ ) left && currtok.Type == Type_
|
# define check( Type_ ) left && currtok.Type == Type_
|
||||||
#pragma endregion Helper Macros
|
#pragma endregion Helper Macros
|
||||||
|
|
||||||
|
Code parse_type( Parser::TokArray& toks, char const* func_name );
|
||||||
|
|
||||||
|
inline
|
||||||
|
Code parse_array_decl( Parser::TokArray& toks, char const* func_name )
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
|
||||||
|
if ( check( TokType::BraceSquare_Open ) )
|
||||||
|
{
|
||||||
|
eat( TokType::BraceSquare_Open );
|
||||||
|
|
||||||
|
if ( left == 0 )
|
||||||
|
{
|
||||||
|
log_failure( "%s: Error, unexpected end of typedef definition ( '[]' scope started )", txt(parse_typedef) );
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( currtok.Type == TokType::BraceSquare_Close )
|
||||||
|
{
|
||||||
|
log_failure( "%s: Error, empty array expression in typedef definition", txt(parse_typedef) );
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token untyped_tok = currtok;
|
||||||
|
|
||||||
|
while ( left && currtok.Type != TokType::BraceSquare_Close )
|
||||||
|
{
|
||||||
|
untyped_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)untyped_tok.Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code array_expr = untyped_str( untyped_tok.Length, untyped_tok.Text );
|
||||||
|
|
||||||
|
if ( left == 0 )
|
||||||
|
{
|
||||||
|
log_failure( "%s: Error, unexpected end of type definition, expected ]", txt(parse_typedef) );
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( currtok.Type != TokType::BraceSquare_Close )
|
||||||
|
{
|
||||||
|
log_failure( "%s: Error, expected ] in type definition, not %s", txt(parse_typedef), str_tok_type( currtok.Type ) );
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
eat( TokType::BraceSquare_Close );
|
||||||
|
return array_expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
Parser::Token parse_identifier( Parser::TokArray& toks, char const* func_name )
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
Token name = currtok;
|
||||||
|
|
||||||
|
eat( TokType::Identifier );
|
||||||
|
|
||||||
|
while ( left && currtok.Type == TokType::Access_StaticSymbol )
|
||||||
|
{
|
||||||
|
eat( TokType::Access_StaticSymbol );
|
||||||
|
|
||||||
|
if ( left == 0 )
|
||||||
|
{
|
||||||
|
log_failure( "%s: Error, unexpected end of type definition, expected identifier", func_name );
|
||||||
|
return { nullptr, 0, TokType::Invalid };
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( currtok.Type != TokType::Identifier )
|
||||||
|
{
|
||||||
|
log_failure( "%s: Error, expected identifier in type definition, not %s", func_name, str_tok_type( currtok.Type ) );
|
||||||
|
return { nullptr, 0, TokType::Invalid };
|
||||||
|
}
|
||||||
|
|
||||||
|
name.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)name.Text;
|
||||||
|
eat( TokType::Identifier );
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code parse_params( Parser::TokArray& toks, char const* context )
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
|
eat( TokType::Capture_Start );
|
||||||
|
|
||||||
|
if ( check(TokType::Capture_End) )
|
||||||
|
{
|
||||||
|
eat( TokType::Capture_End );
|
||||||
|
return { nullptr };
|
||||||
|
}
|
||||||
|
|
||||||
|
Code
|
||||||
|
result = make_code();
|
||||||
|
result->Type = Parameters;
|
||||||
|
|
||||||
|
while ( left && currtok.Type != TokType::Capture_End)
|
||||||
|
{
|
||||||
|
Code type = { nullptr };
|
||||||
|
Code value = { nullptr };
|
||||||
|
|
||||||
|
type = parse_type( toks, context );
|
||||||
|
if ( type == Code::Invalid )
|
||||||
|
return Code::Invalid;
|
||||||
|
|
||||||
|
Token name = currtok;
|
||||||
|
eat( TokType::Identifier );
|
||||||
|
|
||||||
|
if ( currtok.IsAssign )
|
||||||
|
{
|
||||||
|
eat( TokType::Operator );
|
||||||
|
|
||||||
|
Token value_tok = currtok;
|
||||||
|
|
||||||
|
if ( currtok.Type == TokType::Statement_End )
|
||||||
|
{
|
||||||
|
log_failure( "gen::%s: Expected value after assignment operator", context );
|
||||||
|
return Code::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( left && currtok.Type != TokType::Statement_End )
|
||||||
|
{
|
||||||
|
value_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)value_tok.Text;
|
||||||
|
eat( currtok.Type );
|
||||||
|
}
|
||||||
|
|
||||||
|
value = parse_type( toks, context );
|
||||||
|
}
|
||||||
|
|
||||||
|
Code
|
||||||
|
param = make_code();
|
||||||
|
param->Type = Parameters;
|
||||||
|
param->Name = get_cached_string( name.Text, name.Length );
|
||||||
|
|
||||||
|
param->add_entry( type );
|
||||||
|
|
||||||
|
if ( value )
|
||||||
|
param->add_entry( value );
|
||||||
|
|
||||||
|
param.lock();
|
||||||
|
|
||||||
|
result->add_entry( param );
|
||||||
|
eat( TokType::Comma );
|
||||||
|
}
|
||||||
|
eat( TokType::Capture_End );
|
||||||
|
|
||||||
|
result.lock();
|
||||||
|
return result;
|
||||||
|
# undef context
|
||||||
|
}
|
||||||
|
|
||||||
Code parse_class( s32 length, char const* def )
|
Code parse_class( s32 length, char const* def )
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
@ -3391,14 +3674,10 @@ namespace gen
|
|||||||
# undef context
|
# undef context
|
||||||
}
|
}
|
||||||
|
|
||||||
Code parse_execution( s32 length, char const* exec_def )
|
|
||||||
{
|
|
||||||
not_implemented( parse_execution );
|
|
||||||
}
|
|
||||||
|
|
||||||
Code parse_friend( s32 length, char const* def )
|
Code parse_friend( s32 length, char const* def )
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
# define context parse_friend
|
# define context parse_friend
|
||||||
check_parse_args( parse_friend, length, def );
|
check_parse_args( parse_friend, length, def );
|
||||||
@ -3409,19 +3688,46 @@ namespace gen
|
|||||||
|
|
||||||
eat( TokType::Decl_Friend );
|
eat( TokType::Decl_Friend );
|
||||||
|
|
||||||
// This can either be a simple type, or a function declaration.
|
Code function = { nullptr };
|
||||||
// If its a function declaration, it will have a return type, followed by a name, followed by a parameter list.
|
|
||||||
// If its a simple type, it will have a type, followed by a name.
|
|
||||||
|
|
||||||
|
// Type declaration or return type
|
||||||
|
Code type = parse_type( toks, txt(parse_friend) );
|
||||||
|
if ( type == Code::Invalid )
|
||||||
|
return Code::Invalid;
|
||||||
|
|
||||||
|
// Funciton declaration
|
||||||
|
if ( currtok.Type == TokType::Identifier )
|
||||||
|
{
|
||||||
|
// Name
|
||||||
|
Token name = parse_identifier( toks, txt(parse_friend) );
|
||||||
|
|
||||||
|
// Parameter list
|
||||||
|
Code params = parse_params( toks, txt(parse_friend) );
|
||||||
|
|
||||||
using namespace ECode;
|
function = make_code();
|
||||||
|
function->Type = Function_Fwd;
|
||||||
|
function->Name = get_cached_string( name.Text, name.Length );
|
||||||
|
function->add_entry( type );
|
||||||
|
|
||||||
Code result = make_code();
|
if ( params )
|
||||||
|
function->add_entry( params );
|
||||||
|
|
||||||
|
function.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
eat( TokType::Statement_End );
|
||||||
|
|
||||||
|
Code
|
||||||
|
result = make_code();
|
||||||
|
result->Type = Friend;
|
||||||
|
|
||||||
|
if ( function )
|
||||||
|
result->add_entry( function );
|
||||||
|
|
||||||
|
else
|
||||||
|
result->add_entry( type );
|
||||||
|
|
||||||
|
result.lock();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3441,48 +3747,12 @@ namespace gen
|
|||||||
arena_init_from_allocator( & mem, heap(), kilobytes( 10 ) );
|
arena_init_from_allocator( & mem, heap(), kilobytes( 10 ) );
|
||||||
do_once_end
|
do_once_end
|
||||||
|
|
||||||
// Pretty sure its impossible to have more than this.
|
|
||||||
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
|
|
||||||
|
|
||||||
u8 num_specifiers;
|
|
||||||
|
|
||||||
// Making all significant tokens have a max length of 128 for this parser.
|
|
||||||
constexpr sw LengthID = 128;
|
|
||||||
|
|
||||||
struct Param
|
|
||||||
{
|
|
||||||
char const Type[LengthID];
|
|
||||||
char const Name[LengthID];
|
|
||||||
};
|
|
||||||
|
|
||||||
static
|
|
||||||
Param Params[ 64 ] { 0 };
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using namespace ECode;
|
|
||||||
|
|
||||||
Code specifiers = def_specifiers( num_specifiers, specs_found );
|
|
||||||
|
|
||||||
Code params = make_code();
|
|
||||||
// Code ret_type = def_type( ret_length, ret_type_str );
|
|
||||||
// Code body = untyped_str( body_length, body_str );
|
|
||||||
|
|
||||||
Code
|
Code
|
||||||
result = make_code();
|
result = make_code();
|
||||||
// result->Name = get_cached_string( name, name_length );
|
|
||||||
result->Type = Function;
|
|
||||||
|
|
||||||
// result->add_entry( body );
|
|
||||||
|
|
||||||
if ( specifiers )
|
|
||||||
result->add_entry( specifiers );
|
|
||||||
|
|
||||||
// result->add_entry( ret_type );
|
|
||||||
|
|
||||||
if ( params )
|
|
||||||
result->add_entry( params );
|
|
||||||
|
|
||||||
result.lock();
|
result.lock();
|
||||||
return result;
|
return result;
|
||||||
@ -3530,7 +3800,7 @@ namespace gen
|
|||||||
if ( toks.Arr == nullptr )
|
if ( toks.Arr == nullptr )
|
||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
|
|
||||||
Token* name = nullptr;
|
Token name = { nullptr, 0, TokType::Invalid };
|
||||||
|
|
||||||
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
|
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
|
||||||
s32 num_specifiers = 0;
|
s32 num_specifiers = 0;
|
||||||
@ -3613,7 +3883,7 @@ namespace gen
|
|||||||
return Code::Invalid;
|
return Code::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = & currtok;
|
name = currtok;
|
||||||
eat( TokType::Identifier );
|
eat( TokType::Identifier );
|
||||||
|
|
||||||
Code expr = { nullptr };
|
Code expr = { nullptr };
|
||||||
@ -3639,46 +3909,7 @@ namespace gen
|
|||||||
expr = untyped_str( expr_tok.Length, expr_tok.Text );
|
expr = untyped_str( expr_tok.Length, expr_tok.Text );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( check( TokType::BraceSquare_Open ) )
|
array_expr = parse_array_decl( toks, txt(parse_variable) );
|
||||||
{
|
|
||||||
eat( TokType::BraceSquare_Open );
|
|
||||||
|
|
||||||
if ( left == 0 )
|
|
||||||
{
|
|
||||||
log_failure( "%s: Error, unexpected end of typedef definition ( '[]' scope started )", txt(parse_typedef) );
|
|
||||||
return Code::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( currtok.Type == TokType::BraceSquare_Close )
|
|
||||||
{
|
|
||||||
log_failure( "%s: Error, empty array expression in typedef definition", txt(parse_typedef) );
|
|
||||||
return Code::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token
|
|
||||||
untyped_tok = currtok;
|
|
||||||
|
|
||||||
while ( left && currtok.Type != TokType::BraceSquare_Close )
|
|
||||||
{
|
|
||||||
untyped_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)untyped_tok.Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
array_expr = untyped_str( untyped_tok.Length, untyped_tok.Text );
|
|
||||||
|
|
||||||
if ( left == 0 )
|
|
||||||
{
|
|
||||||
log_failure( "%s: Error, unexpected end of type definition, expected ]", txt(parse_typedef) );
|
|
||||||
return Code::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( currtok.Type != TokType::BraceSquare_Close )
|
|
||||||
{
|
|
||||||
log_failure( "%s: Error, expected ] in type definition, not %s", txt(parse_typedef), str_tok_type( currtok.Type ) );
|
|
||||||
return Code::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
eat( TokType::BraceSquare_Close );
|
|
||||||
}
|
|
||||||
|
|
||||||
eat( TokType::Statement_End );
|
eat( TokType::Statement_End );
|
||||||
|
|
||||||
@ -3686,7 +3917,7 @@ namespace gen
|
|||||||
|
|
||||||
Code result = make_code();
|
Code result = make_code();
|
||||||
result->Type = Variable;
|
result->Type = Variable;
|
||||||
result->Name = get_cached_string( name->Text, name->Length );
|
result->Name = get_cached_string( name.Text, name.Length );
|
||||||
|
|
||||||
result->add_entry( type );
|
result->add_entry( type );
|
||||||
|
|
||||||
@ -3747,8 +3978,9 @@ namespace gen
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
name = currtok;
|
name = parse_identifier( toks, func_name );
|
||||||
eat( TokType::Identifier );
|
if ( ! name )
|
||||||
|
return Code::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( left && tok_is_specifier( currtok ) )
|
while ( left && tok_is_specifier( currtok ) )
|
||||||
@ -3836,45 +4068,7 @@ namespace gen
|
|||||||
name = currtok;
|
name = currtok;
|
||||||
eat( TokType::Identifier );
|
eat( TokType::Identifier );
|
||||||
|
|
||||||
if ( check( TokType::BraceSquare_Open ) )
|
array_expr = parse_array_decl( toks, txt(parse_typedef) );
|
||||||
{
|
|
||||||
eat( TokType::BraceSquare_Open );
|
|
||||||
|
|
||||||
if ( left == 0 )
|
|
||||||
{
|
|
||||||
log_failure( "%s: Error, unexpected end of typedef definition ( '[]' scope started )", txt(parse_typedef) );
|
|
||||||
return Code::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( currtok.Type == TokType::BraceSquare_Close )
|
|
||||||
{
|
|
||||||
log_failure( "%s: Error, empty array expression in typedef definition", txt(parse_typedef) );
|
|
||||||
return Code::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token untyped_tok = currtok;
|
|
||||||
|
|
||||||
while ( left && currtok.Type != TokType::BraceSquare_Close )
|
|
||||||
{
|
|
||||||
untyped_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)untyped_tok.Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
array_expr = untyped_str( untyped_tok.Length, untyped_tok.Text );
|
|
||||||
|
|
||||||
if ( left == 0 )
|
|
||||||
{
|
|
||||||
log_failure( "%s: Error, unexpected end of type definition, expected ]", txt(parse_typedef) );
|
|
||||||
return Code::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( currtok.Type != TokType::BraceSquare_Close )
|
|
||||||
{
|
|
||||||
log_failure( "%s: Error, expected ] in type definition, not %s", txt(parse_typedef), str_tok_type( currtok.Type ) );
|
|
||||||
return Code::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
eat( TokType::BraceSquare_Close );
|
|
||||||
}
|
|
||||||
|
|
||||||
eat( TokType::Statement_End );
|
eat( TokType::Statement_End );
|
||||||
|
|
||||||
@ -3932,46 +4126,7 @@ namespace gen
|
|||||||
type = parse_type( toks, txt(parse_typedef) );
|
type = parse_type( toks, txt(parse_typedef) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! is_namespace && check( TokType::BraceSquare_Open ) )
|
array_expr = parse_array_decl( toks, txt(parse_typedef) );
|
||||||
{
|
|
||||||
eat( TokType::BraceSquare_Open );
|
|
||||||
|
|
||||||
if ( left == 0 )
|
|
||||||
{
|
|
||||||
log_failure( "%s: Error, unexpected end of typedef definition ( '[]' scope started )", txt(parse_typedef) );
|
|
||||||
return Code::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( currtok.Type == TokType::BraceSquare_Close )
|
|
||||||
{
|
|
||||||
log_failure( "%s: Error, empty array expression in typedef definition", txt(parse_typedef) );
|
|
||||||
return Code::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token
|
|
||||||
untyped_tok = currtok;
|
|
||||||
|
|
||||||
while ( left && currtok.Type != TokType::BraceSquare_Close )
|
|
||||||
{
|
|
||||||
untyped_tok.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)untyped_tok.Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
array_expr = untyped_str( untyped_tok.Length, untyped_tok.Text );
|
|
||||||
|
|
||||||
if ( left == 0 )
|
|
||||||
{
|
|
||||||
log_failure( "%s: Error, unexpected end of type definition, expected ]", txt(parse_typedef) );
|
|
||||||
return Code::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( currtok.Type != TokType::BraceSquare_Close )
|
|
||||||
{
|
|
||||||
log_failure( "%s: Error, expected ] in type definition, not %s", txt(parse_typedef), str_tok_type( currtok.Type ) );
|
|
||||||
return Code::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
eat( TokType::BraceSquare_Close );
|
|
||||||
}
|
|
||||||
|
|
||||||
eat( TokType::Statement_End );
|
eat( TokType::Statement_End );
|
||||||
|
|
||||||
|
@ -51,6 +51,8 @@ namespace gen
|
|||||||
Entry( Enum_Class ) \
|
Entry( Enum_Class ) \
|
||||||
Entry( Enum_Class_Fwd ) \
|
Entry( Enum_Class_Fwd ) \
|
||||||
Entry( Execution ) \
|
Entry( Execution ) \
|
||||||
|
Entry( Extern_Linkage ) \
|
||||||
|
Entry( Extern_Linkage_Body ) \
|
||||||
Entry( Friend ) \
|
Entry( Friend ) \
|
||||||
Entry( Function ) \
|
Entry( Function ) \
|
||||||
Entry( Function_Fwd ) \
|
Entry( Function_Fwd ) \
|
||||||
@ -214,7 +216,6 @@ namespace gen
|
|||||||
Entry( API_Export, API_Import_Code ) \
|
Entry( API_Export, API_Import_Code ) \
|
||||||
Entry( Alignas, alignas ) \
|
Entry( Alignas, alignas ) \
|
||||||
Entry( Array_Decl, "You cannot stringize an array declare this way" ) \
|
Entry( Array_Decl, "You cannot stringize an array declare this way" ) \
|
||||||
Entry( C_Linkage, extern "C" ) \
|
|
||||||
Entry( Const, const ) \
|
Entry( Const, const ) \
|
||||||
Entry( Consteval, consteval ) \
|
Entry( Consteval, consteval ) \
|
||||||
Entry( Constexpr, constexpr ) \
|
Entry( Constexpr, constexpr ) \
|
||||||
@ -714,10 +715,11 @@ namespace gen
|
|||||||
|
|
||||||
Code def_friend ( Code symbol );
|
Code def_friend ( Code symbol );
|
||||||
Code def_function ( s32 length, char const* name, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode, Code body = NoCode );
|
Code def_function ( s32 length, char const* name, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode, Code body = NoCode );
|
||||||
|
Code def_extern_linkage ( s32 length, char const* name, Code body );
|
||||||
Code def_namespace ( s32 length, char const* name, Code body );
|
Code def_namespace ( s32 length, char const* name, Code body );
|
||||||
Code def_operator ( OperatorT op, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode, Code body = NoCode );
|
Code def_operator ( OperatorT op, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode, Code body = NoCode );
|
||||||
|
|
||||||
Code def_param ( Code type, s32 length, char const* name );
|
Code def_param ( Code type, s32 length, char const* name, Code value = NoCode );
|
||||||
|
|
||||||
Code def_specifier ( SpecifierT specifier );
|
Code def_specifier ( SpecifierT specifier );
|
||||||
|
|
||||||
@ -729,8 +731,10 @@ namespace gen
|
|||||||
Code def_variable ( Code type, s32 length, char const* name, Code value = NoCode, Code specifiers = NoCode );
|
Code def_variable ( Code type, s32 length, char const* name, Code value = NoCode, Code specifiers = NoCode );
|
||||||
|
|
||||||
Code def_class_body ( s32 num, ... );
|
Code def_class_body ( s32 num, ... );
|
||||||
Code def_enum_body ( u32 num, ... );
|
Code def_enum_body ( s32 num, ... );
|
||||||
Code def_enum_body ( u32 num, Code* codes );
|
Code def_enum_body ( s32 num, Code* codes );
|
||||||
|
Code def_extern_linkage_body( s32 num, ... );
|
||||||
|
Code def_extern_linkage_body( s32 num, Code* codes );
|
||||||
Code def_global_body ( s32 num, ... );
|
Code def_global_body ( s32 num, ... );
|
||||||
Code def_global_body ( s32 num, Code* codes );
|
Code def_global_body ( s32 num, Code* codes );
|
||||||
Code def_function_body ( s32 num, ... );
|
Code def_function_body ( s32 num, ... );
|
||||||
@ -749,8 +753,9 @@ namespace gen
|
|||||||
# ifdef GEN_FEATURE_INCREMENTAL
|
# ifdef GEN_FEATURE_INCREMENTAL
|
||||||
Code make_class ( s32 length, char const* name, Code parent = NoCode, Code specifiers = NoCode );
|
Code make_class ( s32 length, char const* name, Code parent = NoCode, Code specifiers = NoCode );
|
||||||
Code make_enum ( s32 length, char const* name, Code type = NoCode, EnumT specifier = EnumRegular );
|
Code make_enum ( s32 length, char const* name, Code type = NoCode, EnumT specifier = EnumRegular );
|
||||||
|
Code make_extern_linkage( s32 length, char const* name );
|
||||||
Code make_function ( s32 length, char const* name, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode );
|
Code make_function ( s32 length, char const* name, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode );
|
||||||
Code make_global_body ( s32 length = 1, char const* name = "", s32 num = 0, ... );
|
Code make_global_body ( s32 length = 1, char const* name = "" );
|
||||||
Code make_namespace ( s32 length, char const* name );
|
Code make_namespace ( s32 length, char const* name );
|
||||||
Code make_operator ( OperatorT op, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode );
|
Code make_operator ( OperatorT op, Code params = NoCode, Code ret_type = NoCode, Code specifiers = NoCode );
|
||||||
Code make_params ();
|
Code make_params ();
|
||||||
@ -763,7 +768,6 @@ namespace gen
|
|||||||
#ifdef GEN_FEATURE_PARSING
|
#ifdef GEN_FEATURE_PARSING
|
||||||
Code parse_class ( s32 length, char const* class_def );
|
Code parse_class ( s32 length, char const* class_def );
|
||||||
Code parse_enum ( s32 length, char const* enum_def );
|
Code parse_enum ( s32 length, char const* enum_def );
|
||||||
Code parse_execution ( s32 length, char const* exec_def );
|
|
||||||
Code parse_friend ( s32 length, char const* friend_def );
|
Code parse_friend ( s32 length, char const* friend_def );
|
||||||
Code parse_function ( s32 length, char const* fn_def );
|
Code parse_function ( s32 length, char const* fn_def );
|
||||||
Code parse_global_body( s32 length, char const* body_def );
|
Code parse_global_body( s32 length, char const* body_def );
|
||||||
@ -1010,6 +1014,7 @@ namespace gen
|
|||||||
# define class( Name_, ... ) gen::def_class( txt_n_len(Name_), __VA_ARGS__ )
|
# define class( Name_, ... ) gen::def_class( txt_n_len(Name_), __VA_ARGS__ )
|
||||||
# define enum( Name_, Type_, Body_ ) gen::def_enum ( txt_n_len(Name_), type_ns(Type_), Body_ )
|
# define enum( Name_, Type_, Body_ ) gen::def_enum ( txt_n_len(Name_), type_ns(Type_), Body_ )
|
||||||
|
|
||||||
|
# define extern_linkage( Name_, Body_ ) gen::def_extern_linkage( txt_n_len(Name_), Body_ )
|
||||||
# define function( ... ) macrofn_polymorphic( function, __VA_ARGS__ )
|
# define function( ... ) macrofn_polymorphic( function, __VA_ARGS__ )
|
||||||
# define namespace( Name_, Body_ ) gen::def_namespace ( txt_n_len(Name_), Body_ )
|
# define namespace( Name_, Body_ ) gen::def_namespace ( txt_n_len(Name_), Body_ )
|
||||||
# define operator( Op_, ... ) macrofn_polymorphic( operator, __VA_ARGS__ )
|
# define operator( Op_, ... ) macrofn_polymorphic( operator, __VA_ARGS__ )
|
||||||
|
Loading…
Reference in New Issue
Block a user