2023-07-24 14:45:27 -07:00
|
|
|
using LogFailType = sw(*)(char const*, ...);
|
|
|
|
|
|
|
|
// By default this library will either crash or exit if an error is detected while generating codes.
|
|
|
|
// Even if set to not use fatal, fatal will still be used for memory failures as the library is unusable when they occur.
|
|
|
|
#ifdef GEN_DONT_USE_FATAL
|
|
|
|
constexpr LogFailType log_failure = log_fmt;
|
|
|
|
#else
|
|
|
|
constexpr LogFailType log_failure = fatal;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace ECode
|
|
|
|
{
|
|
|
|
# define Define_Types \
|
|
|
|
Entry( Untyped ) \
|
|
|
|
Entry( Comment ) \
|
|
|
|
Entry( Access_Private ) \
|
|
|
|
Entry( Access_Protected ) \
|
|
|
|
Entry( Access_Public ) \
|
|
|
|
Entry( PlatformAttributes ) \
|
|
|
|
Entry( Class ) \
|
|
|
|
Entry( Class_Fwd ) \
|
|
|
|
Entry( Class_Body ) \
|
|
|
|
Entry( Enum ) \
|
|
|
|
Entry( Enum_Fwd ) \
|
|
|
|
Entry( Enum_Body ) \
|
|
|
|
Entry( Enum_Class ) \
|
|
|
|
Entry( Enum_Class_Fwd ) \
|
|
|
|
Entry( Execution ) \
|
|
|
|
Entry( Export_Body ) \
|
|
|
|
Entry( Extern_Linkage ) \
|
|
|
|
Entry( Extern_Linkage_Body ) \
|
|
|
|
Entry( Friend ) \
|
|
|
|
Entry( Function ) \
|
|
|
|
Entry( Function_Fwd ) \
|
|
|
|
Entry( Function_Body ) \
|
|
|
|
Entry( Global_Body ) \
|
|
|
|
Entry( Module ) \
|
|
|
|
Entry( Namespace ) \
|
|
|
|
Entry( Namespace_Body ) \
|
|
|
|
Entry( Operator ) \
|
|
|
|
Entry( Operator_Fwd ) \
|
|
|
|
Entry( Operator_Member ) \
|
|
|
|
Entry( Operator_Member_Fwd ) \
|
|
|
|
Entry( Operator_Cast ) \
|
|
|
|
Entry( Operator_Cast_Fwd ) \
|
|
|
|
Entry( Parameters ) \
|
|
|
|
Entry( Preprocessor_Include ) \
|
|
|
|
Entry( Specifiers ) \
|
|
|
|
Entry( Struct ) \
|
|
|
|
Entry( Struct_Fwd ) \
|
|
|
|
Entry( Struct_Body ) \
|
|
|
|
Entry( Template ) \
|
|
|
|
Entry( Typedef ) \
|
|
|
|
Entry( Typename ) \
|
|
|
|
Entry( Union ) \
|
|
|
|
Entry( Union_Body) \
|
|
|
|
Entry( Using ) \
|
|
|
|
Entry( Using_Namespace ) \
|
|
|
|
Entry( Variable )
|
|
|
|
|
|
|
|
enum Type : u32
|
|
|
|
{
|
|
|
|
# define Entry( Type ) Type,
|
|
|
|
Define_Types
|
|
|
|
# undef Entry
|
|
|
|
|
|
|
|
Num_Types,
|
|
|
|
Invalid
|
|
|
|
};
|
|
|
|
|
|
|
|
inline
|
|
|
|
StrC to_str( Type type )
|
|
|
|
{
|
|
|
|
static
|
|
|
|
StrC lookup[Num_Types] = {
|
|
|
|
# define Entry( Type ) { sizeof(stringize(Type)), stringize(Type) },
|
|
|
|
Define_Types
|
|
|
|
# undef Entry
|
|
|
|
};
|
|
|
|
|
|
|
|
return lookup[ type ];
|
|
|
|
}
|
|
|
|
|
|
|
|
# undef Define_Types
|
|
|
|
}
|
|
|
|
using CodeT = ECode::Type;
|
|
|
|
|
|
|
|
// Used to indicate if enum definitoin is an enum class or regular enum.
|
|
|
|
enum class EnumT : u8
|
|
|
|
{
|
|
|
|
Regular,
|
|
|
|
Class
|
|
|
|
};
|
|
|
|
|
|
|
|
constexpr EnumT EnumClass = EnumT::Class;
|
|
|
|
constexpr EnumT EnumRegular = EnumT::Regular;
|
|
|
|
|
|
|
|
namespace EOperator
|
|
|
|
{
|
|
|
|
# define Define_Operators \
|
|
|
|
Entry( Assign, = ) \
|
|
|
|
Entry( Assign_Add, += ) \
|
|
|
|
Entry( Assign_Subtract, -= ) \
|
|
|
|
Entry( Assign_Multiply, *= ) \
|
|
|
|
Entry( Assign_Divide, /= ) \
|
|
|
|
Entry( Assign_Modulo, %= ) \
|
|
|
|
Entry( Assign_BAnd, &= ) \
|
|
|
|
Entry( Assign_BOr, |= ) \
|
|
|
|
Entry( Assign_BXOr, ^= ) \
|
|
|
|
Entry( Assign_LShift, <<= ) \
|
|
|
|
Entry( Assign_RShift, >>= ) \
|
|
|
|
Entry( Increment, ++ ) \
|
|
|
|
Entry( Decrement, -- ) \
|
|
|
|
Entry( Unary_Plus, + ) \
|
|
|
|
Entry( Unary_Minus, - ) \
|
|
|
|
Entry( UnaryNot, ! ) \
|
|
|
|
Entry( Add, + ) \
|
|
|
|
Entry( Subtract, - ) \
|
|
|
|
Entry( Multiply, * ) \
|
|
|
|
Entry( Divide, / ) \
|
|
|
|
Entry( Modulo, % ) \
|
|
|
|
Entry( BNot, ~ ) \
|
|
|
|
Entry( BAnd, & ) \
|
|
|
|
Entry( BOr, | ) \
|
|
|
|
Entry( BXOr, ^ ) \
|
|
|
|
Entry( LShift, << ) \
|
|
|
|
Entry( RShift, >> ) \
|
|
|
|
Entry( LAnd, && ) \
|
|
|
|
Entry( LOr, || ) \
|
|
|
|
Entry( LEqual, == ) \
|
|
|
|
Entry( LNot, != ) \
|
|
|
|
Entry( Lesser, < ) \
|
|
|
|
Entry( Greater, > ) \
|
|
|
|
Entry( LesserEqual, <= ) \
|
|
|
|
Entry( GreaterEqual, >= ) \
|
|
|
|
Entry( Subscript, [] ) \
|
|
|
|
Entry( Indirection, * ) \
|
|
|
|
Entry( AddressOf, & ) \
|
|
|
|
Entry( MemberOfPointer, -> ) \
|
|
|
|
Entry( PtrToMemOfPtr, ->* ) \
|
|
|
|
Entry( FunctionCall, () )
|
|
|
|
|
|
|
|
enum Type : u32
|
|
|
|
{
|
|
|
|
# define Entry( Type_, Token_ ) Type_,
|
|
|
|
Define_Operators
|
|
|
|
# undef Entry
|
|
|
|
Comma,
|
|
|
|
|
|
|
|
Num_Ops,
|
|
|
|
Invalid
|
|
|
|
};
|
|
|
|
|
|
|
|
inline
|
|
|
|
char const* to_str( Type op )
|
|
|
|
{
|
|
|
|
local_persist
|
|
|
|
char const* lookup[ Num_Ops ] = {
|
|
|
|
# define Entry( Type_, Token_ ) stringize(Token_),
|
|
|
|
Define_Operators
|
|
|
|
# undef Entry
|
|
|
|
","
|
|
|
|
};
|
|
|
|
|
|
|
|
return lookup[ op ];
|
|
|
|
}
|
|
|
|
|
|
|
|
# undef Define_Operators
|
|
|
|
}
|
|
|
|
using OperatorT = EOperator::Type;
|
|
|
|
|
|
|
|
namespace ESpecifier
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Note: The following are handled separately:
|
|
|
|
attributes
|
|
|
|
alignas
|
|
|
|
*/
|
|
|
|
|
|
|
|
# define Define_Specifiers \
|
|
|
|
Entry( Invalid, INVALID ) \
|
|
|
|
Entry( Consteval, consteval ) \
|
|
|
|
Entry( Constexpr, constexpr ) \
|
|
|
|
Entry( Constinit, constinit ) \
|
|
|
|
Entry( Explicit, explicit ) \
|
|
|
|
Entry( External_Linkage, extern ) \
|
|
|
|
Entry( Global, global ) \
|
|
|
|
Entry( Inline, inline ) \
|
|
|
|
Entry( Internal_Linkage, internal ) \
|
|
|
|
Entry( Local_Persist, local_persist ) \
|
|
|
|
Entry( Mutable, mutable ) \
|
|
|
|
Entry( Ptr, * ) \
|
|
|
|
Entry( Ref, & ) \
|
|
|
|
Entry( Register, register ) \
|
|
|
|
Entry( RValue, && ) \
|
|
|
|
Entry( Static, static ) \
|
|
|
|
Entry( Thread_Local, thread_local ) \
|
|
|
|
Entry( Volatile, volatile ) \
|
|
|
|
Entry( Virtual, virtual ) \
|
|
|
|
Entry( Const, const ) \
|
|
|
|
Entry( Final, final ) \
|
|
|
|
Entry( Override, override )
|
|
|
|
|
|
|
|
enum Type : u32
|
|
|
|
{
|
|
|
|
# define Entry( Specifier, Code ) Specifier,
|
|
|
|
Define_Specifiers
|
|
|
|
# undef Entry
|
|
|
|
|
|
|
|
Num_Specifiers,
|
|
|
|
};
|
|
|
|
|
|
|
|
inline
|
|
|
|
bool is_trailing( Type specifier )
|
|
|
|
{
|
|
|
|
return specifier > Virtual;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Specifier to string
|
|
|
|
inline
|
|
|
|
StrC to_str( Type specifier )
|
|
|
|
{
|
|
|
|
local_persist
|
|
|
|
StrC lookup[ Num_Specifiers ] = {
|
|
|
|
# pragma push_macro( "global" )
|
|
|
|
# pragma push_macro( "internal" )
|
|
|
|
# pragma push_macro( "local_persist" )
|
|
|
|
# undef global
|
|
|
|
# undef internal
|
|
|
|
# undef local_persist
|
|
|
|
|
|
|
|
# define Entry( Spec_, Code_ ) { sizeof(stringize(Code_)), stringize(Code_) },
|
|
|
|
Define_Specifiers
|
|
|
|
# undef Entry
|
|
|
|
|
|
|
|
# pragma pop_macro( "global" )
|
|
|
|
# pragma pop_macro( "internal" )
|
|
|
|
# pragma pop_macro( "local_persist" )
|
|
|
|
};
|
|
|
|
|
|
|
|
return lookup[ specifier ];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline
|
|
|
|
Type to_type( StrC str )
|
|
|
|
{
|
|
|
|
local_persist
|
|
|
|
u32 keymap[ Num_Specifiers ];
|
|
|
|
do_once_start
|
|
|
|
for ( u32 index = 0; index < Num_Specifiers; index++ )
|
|
|
|
{
|
|
|
|
StrC enum_str = to_str( (Type)index );
|
|
|
|
|
|
|
|
// We subtract 1 to remove the null terminator
|
|
|
|
// This is because the tokens lexed are not null terminated.
|
|
|
|
keymap[index] = crc32( enum_str.Ptr, enum_str.Len - 1);
|
|
|
|
}
|
|
|
|
do_once_end
|
|
|
|
|
|
|
|
u32 hash = crc32( str.Ptr, str.Len );
|
|
|
|
|
|
|
|
for ( u32 index = 0; index < Num_Specifiers; index++ )
|
|
|
|
{
|
|
|
|
if ( keymap[index] == hash )
|
|
|
|
return (Type)index;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
# undef Define_Specifiers
|
|
|
|
}
|
|
|
|
using SpecifierT = ESpecifier::Type;
|
|
|
|
|
|
|
|
enum class AccessSpec : u32
|
|
|
|
{
|
|
|
|
Default,
|
|
|
|
Public,
|
|
|
|
Protected,
|
|
|
|
Private,
|
|
|
|
|
|
|
|
Num_AccessSpec,
|
|
|
|
Invalid,
|
|
|
|
};
|
|
|
|
|
|
|
|
inline
|
|
|
|
char const* to_str( AccessSpec type )
|
|
|
|
{
|
|
|
|
local_persist
|
|
|
|
char const* lookup[ (u32)AccessSpec::Num_AccessSpec ] = {
|
|
|
|
"",
|
|
|
|
"public",
|
|
|
|
"protected",
|
|
|
|
"private",
|
|
|
|
};
|
|
|
|
|
|
|
|
if ( type > AccessSpec::Public )
|
|
|
|
return "Invalid";
|
|
|
|
|
|
|
|
return lookup[ (u32)type ];
|
|
|
|
}
|
|
|
|
|
|
|
|
enum class ModuleFlag : u32
|
|
|
|
{
|
|
|
|
None = 0,
|
|
|
|
Export = bit(0),
|
|
|
|
Import = bit(1),
|
|
|
|
// Private = bit(2),
|
|
|
|
|
|
|
|
Num_ModuleFlags,
|
|
|
|
Invalid,
|
|
|
|
};
|
|
|
|
|
|
|
|
ModuleFlag operator|( ModuleFlag A, ModuleFlag B)
|
|
|
|
{
|
|
|
|
return (ModuleFlag)( (u32)A | (u32)B );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Predefined attributes
|
|
|
|
Used for the parser constructors to identify non-standard attributes
|
|
|
|
|
|
|
|
Override these to change the attribute to your own unique identifier convention.
|
|
|
|
|
|
|
|
The tokenizer identifies attribute defines with the GEN_Define_Attribute_Tokens macros.
|
|
|
|
See the example below and the Define_TokType macro used in gen.cpp to know the format.
|
|
|
|
While the library can parse raw attributes, most projects use defines to wrap them for compiler
|
|
|
|
platform indendence. The token define allows support for them without having to modify the library.
|
|
|
|
*/
|
|
|
|
#if defined(GEN_SYSTEM_WINDOWS) || defined( __CYGWIN__ )
|
|
|
|
#ifndef GEN_Attribute_Keyword
|
|
|
|
# define GEN_API_Export_Code __declspec(dllexport)
|
|
|
|
# define GEN_API_Import_Code __declspec(dllimport)
|
|
|
|
# define GEN_Attribute_Keyword __declspec
|
|
|
|
#endif
|
|
|
|
|
|
|
|
constexpr char const* Attribute_Keyword = stringize( GEN_Attribute_Keyword);
|
|
|
|
|
|
|
|
#elif GEN_HAS_ATTRIBUTE( visibility ) || GEN_GCC_VERSION_CHECK( 3, 3, 0 )
|
|
|
|
#ifndef GEN_Attribute_Keyword
|
|
|
|
# define GEN_API_Export_Code __attribute__ ((visibility ("default")))
|
|
|
|
# define GEN_API_Import_Code __attribute__ ((visibility ("default")))
|
|
|
|
# define GEN_Attribute_Keyword __attribute__
|
|
|
|
#endif
|
|
|
|
|
|
|
|
constexpr char const* Attribute_Keyword = stringize( GEN_Attribute_Keyword );
|
|
|
|
|
|
|
|
#else
|
|
|
|
#ifndef GEN_Attribute_Keyword
|
|
|
|
# define GEN_API_Export_Code
|
|
|
|
# define GEN_API_Import_Code
|
|
|
|
# define GEN_Attribute_Keyword
|
|
|
|
#endif
|
|
|
|
|
|
|
|
constexpr char const* Attribute_Keyword = "";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef GEN_Define_Attribute_Tokens
|
|
|
|
# define GEN_Define_Attribute_Tokens \
|
|
|
|
Entry( API_Export, "GEN_API_Export_Code" ) \
|
|
|
|
Entry( API_Import, "GEN_API_Import_Code" )
|
|
|
|
#endif
|
|
|
|
|