mirror of
https://github.com/Ed94/gencpp.git
synced 2024-12-22 15:54:45 -08:00
Started to implement context stack for parser.
This commit is contained in:
parent
3f0b7e7fc6
commit
31e1c38c18
30
Readme.md
30
Readme.md
@ -5,11 +5,6 @@ An attempt at simple staged metaprogramming for c/c++.
|
|||||||
The library API is a composition of code element constructors.
|
The library API is a composition of code element constructors.
|
||||||
These build up a code AST to then serialize with a file builder.
|
These build up a code AST to then serialize with a file builder.
|
||||||
|
|
||||||
General goal is to have a less than 15k sloc library that takes at most a couple of hours to learn and make use of.
|
|
||||||
|
|
||||||
*Why 15k ?* Assuming a seasoned coder of C++ can read and understand around 1000-2000 lines of code per hour, 15,000 could be understood in under 16-18 hours
|
|
||||||
and have confidence in modifying for their use case.
|
|
||||||
|
|
||||||
This code base attempts follow the [handmade philosophy](https://handmade.network/manifesto),
|
This code base attempts follow the [handmade philosophy](https://handmade.network/manifesto),
|
||||||
its not meant to be a black box metaprogramming utility, its meant for the user to extend for their project domain.
|
its not meant to be a black box metaprogramming utility, its meant for the user to extend for their project domain.
|
||||||
|
|
||||||
@ -30,17 +25,17 @@ The project has reached an *alpha* state, all the current functionality works fo
|
|||||||
|
|
||||||
The project has no external dependencies beyond:
|
The project has no external dependencies beyond:
|
||||||
|
|
||||||
* `errno.h` (gen.dep.cpp)
|
* `errno.h`
|
||||||
* `stat.h` (gen.dep.cpp)
|
* `stat.h`
|
||||||
* `stdarg.h` (gen.dep.hpp)
|
* `stdarg.h`
|
||||||
* `stddef.h` (gen.dep.hpp
|
* `stddef.h`
|
||||||
* `stdio.h` (gen.dep.cpp)
|
* `stdio.h`
|
||||||
* `copyfile.h` (Mac, gen.dep.cpp)
|
* `copyfile.h` (Mac)
|
||||||
* `types.h` (Linux, gen.dep.cpp)
|
* `types.h` (Linux)
|
||||||
* `unistd.h` (Linux/Mac, gen.dep.cpp)
|
* `unistd.h` (Linux/Mac)
|
||||||
* `intrin.h` (Windows, gen.dep.hpp)
|
* `intrin.h` (Windows)
|
||||||
* `io.h` (Windows with gcc, gen.dep.cpp)
|
* `io.h` (Windows with gcc)
|
||||||
* `windows.h` (Windows, gen.dep.cpp)
|
* `windows.h` (Windows)
|
||||||
|
|
||||||
Dependencies for the project are wrapped within `GENCPP_ROLL_OWN_DEPENDENCIES` (Defining it will disable them).
|
Dependencies for the project are wrapped within `GENCPP_ROLL_OWN_DEPENDENCIES` (Defining it will disable them).
|
||||||
The majority of the dependency's implementation was derived from the [c-zpl library](https://github.com/zpl-c/zpl).
|
The majority of the dependency's implementation was derived from the [c-zpl library](https://github.com/zpl-c/zpl).
|
||||||
@ -561,6 +556,7 @@ The following are provided predefined by the library as they are commonly used:
|
|||||||
* `access_private`
|
* `access_private`
|
||||||
* `module_global_fragment`
|
* `module_global_fragment`
|
||||||
* `module_private_fragment`
|
* `module_private_fragment`
|
||||||
|
* `param_varaidc` (Used for varadic definitions)
|
||||||
* `pragma_once`
|
* `pragma_once`
|
||||||
* `spec_const`
|
* `spec_const`
|
||||||
* `spec_consteval`
|
* `spec_consteval`
|
||||||
@ -586,7 +582,7 @@ The following are provided predefined by the library as they are commonly used:
|
|||||||
* `spec_type_unsigned`
|
* `spec_type_unsigned`
|
||||||
* `spec_type_short`
|
* `spec_type_short`
|
||||||
* `spec_type_long`
|
* `spec_type_long`
|
||||||
* `t_empty`
|
* `t_empty` (Used for varaidc macros)
|
||||||
* `t_auto`
|
* `t_auto`
|
||||||
* `t_void`
|
* `t_void`
|
||||||
* `t_int`
|
* `t_int`
|
||||||
|
@ -37,8 +37,12 @@ Module_Import, "import"
|
|||||||
Module_Export, "export"
|
Module_Export, "export"
|
||||||
Number, "number"
|
Number, "number"
|
||||||
Operator, "operator"
|
Operator, "operator"
|
||||||
Preprocessor_Directive, "#"
|
Preprocess_Define, "#define"
|
||||||
Preprocessor_Include, "include"
|
Preprocess_Include, "#include"
|
||||||
|
Preprocess_If, "#if"
|
||||||
|
Preprocess_ElIF, "#elif"
|
||||||
|
Preprocess_Else, "#else"
|
||||||
|
Preprocess_EndIf, "#endif"
|
||||||
Spec_Alignas, "alignas"
|
Spec_Alignas, "alignas"
|
||||||
Spec_Const, "const"
|
Spec_Const, "const"
|
||||||
Spec_Consteval, "consteval"
|
Spec_Consteval, "consteval"
|
||||||
|
|
@ -778,7 +778,7 @@ bool AST::validate_body()
|
|||||||
switch ( Type )
|
switch ( Type )
|
||||||
{
|
{
|
||||||
case Class_Body:
|
case Class_Body:
|
||||||
CheckEntries( AST_BODY_CLASS_UNALLOWED_TYPES );
|
CheckEntries( GEN_AST_BODY_CLASS_UNALLOWED_TYPES );
|
||||||
break;
|
break;
|
||||||
case Enum_Body:
|
case Enum_Body:
|
||||||
for ( Code entry : cast<CodeBody>() )
|
for ( Code entry : cast<CodeBody>() )
|
||||||
@ -791,22 +791,22 @@ bool AST::validate_body()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Export_Body:
|
case Export_Body:
|
||||||
CheckEntries( AST_BODY_CLASS_UNALLOWED_TYPES );
|
CheckEntries( GEN_AST_BODY_CLASS_UNALLOWED_TYPES );
|
||||||
break;
|
break;
|
||||||
case Extern_Linkage:
|
case Extern_Linkage:
|
||||||
CheckEntries( AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES );
|
CheckEntries( GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES );
|
||||||
break;
|
break;
|
||||||
case Function_Body:
|
case Function_Body:
|
||||||
CheckEntries( AST_BODY_FUNCTION_UNALLOWED_TYPES );
|
CheckEntries( GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES );
|
||||||
break;
|
break;
|
||||||
case Global_Body:
|
case Global_Body:
|
||||||
CheckEntries( AST_BODY_GLOBAL_UNALLOWED_TYPES );
|
CheckEntries( GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES );
|
||||||
break;
|
break;
|
||||||
case Namespace_Body:
|
case Namespace_Body:
|
||||||
CheckEntries( AST_BODY_NAMESPACE_UNALLOWED_TYPES );
|
CheckEntries( GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES );
|
||||||
break;
|
break;
|
||||||
case Struct_Body:
|
case Struct_Body:
|
||||||
CheckEntries( AST_BODY_STRUCT_UNALLOWED_TYPES );
|
CheckEntries( GEN_AST_BODY_STRUCT_UNALLOWED_TYPES );
|
||||||
break;
|
break;
|
||||||
case Union_Body:
|
case Union_Body:
|
||||||
for ( Code entry : Body->cast<CodeBody>() )
|
for ( Code entry : Body->cast<CodeBody>() )
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# define AST_BODY_CLASS_UNALLOWED_TYPES \
|
# define GEN_AST_BODY_CLASS_UNALLOWED_TYPES \
|
||||||
case PlatformAttributes: \
|
case PlatformAttributes: \
|
||||||
case Class_Body: \
|
case Class_Body: \
|
||||||
case Enum_Body: \
|
case Enum_Body: \
|
||||||
@ -14,8 +14,9 @@
|
|||||||
case Specifiers: \
|
case Specifiers: \
|
||||||
case Struct_Body: \
|
case Struct_Body: \
|
||||||
case Typename:
|
case Typename:
|
||||||
|
# define GEN_AST_BODY_STRUCT_UNALLOWED_TYPES GEN_AST_BODY_CLASS_UNALLOWED_TYPES
|
||||||
|
|
||||||
# define AST_BODY_FUNCTION_UNALLOWED_TYPES \
|
# define GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES \
|
||||||
case Access_Public: \
|
case Access_Public: \
|
||||||
case Access_Protected: \
|
case Access_Protected: \
|
||||||
case Access_Private: \
|
case Access_Private: \
|
||||||
@ -38,7 +39,7 @@
|
|||||||
case Struct_Body: \
|
case Struct_Body: \
|
||||||
case Typename:
|
case Typename:
|
||||||
|
|
||||||
# define AST_BODY_GLOBAL_UNALLOWED_TYPES \
|
# define GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES \
|
||||||
case Access_Public: \
|
case Access_Public: \
|
||||||
case Access_Protected: \
|
case Access_Protected: \
|
||||||
case Access_Private: \
|
case Access_Private: \
|
||||||
@ -56,9 +57,10 @@
|
|||||||
case Specifiers: \
|
case Specifiers: \
|
||||||
case Struct_Body: \
|
case Struct_Body: \
|
||||||
case Typename:
|
case Typename:
|
||||||
|
# define GEN_AST_BODY_EXPORT_UNALLOWED_TYPES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES
|
||||||
|
# define GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES
|
||||||
|
|
||||||
# define AST_BODY_EXPORT_UNALLOWED_TYPES AST_BODY_GLOBAL_UNALLOWED_TYPES
|
# define GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES \
|
||||||
# define AST_BODY_NAMESPACE_UNALLOWED_TYPES \
|
|
||||||
case Access_Public: \
|
case Access_Public: \
|
||||||
case Access_Protected: \
|
case Access_Protected: \
|
||||||
case Access_Private: \
|
case Access_Private: \
|
||||||
@ -75,7 +77,3 @@
|
|||||||
case Specifiers: \
|
case Specifiers: \
|
||||||
case Struct_Body: \
|
case Struct_Body: \
|
||||||
case Typename:
|
case Typename:
|
||||||
|
|
||||||
# define AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES AST_BODY_GLOBAL_UNALLOWED_TYPES
|
|
||||||
|
|
||||||
# define AST_BODY_STRUCT_UNALLOWED_TYPES AST_BODY_CLASS_UNALLOWED_TYPES
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#pragma region StaticData
|
#pragma region StaticData
|
||||||
|
|
||||||
// TODO : Convert global allocation strategy to use a slab allocation strategy.
|
// TODO : Convert global allocation strategy to use a slab allocation strategy.
|
||||||
global AllocatorInfo GlobalAllocator;
|
global AllocatorInfo GlobalAllocator;
|
||||||
global Array<Arena> Global_AllocatorBuckets;
|
global Array<Arena> Global_AllocatorBuckets;
|
||||||
@ -16,9 +17,11 @@ global AllocatorInfo Allocator_Lexer = heap();
|
|||||||
global AllocatorInfo Allocator_StringArena = heap();
|
global AllocatorInfo Allocator_StringArena = heap();
|
||||||
global AllocatorInfo Allocator_StringTable = heap();
|
global AllocatorInfo Allocator_StringTable = heap();
|
||||||
global AllocatorInfo Allocator_TypeTable = heap();
|
global AllocatorInfo Allocator_TypeTable = heap();
|
||||||
|
|
||||||
#pragma endregion StaticData
|
#pragma endregion StaticData
|
||||||
|
|
||||||
#pragma region Constants
|
#pragma region Constants
|
||||||
|
|
||||||
global CodeType t_empty;
|
global CodeType t_empty;
|
||||||
global CodeType t_auto;
|
global CodeType t_auto;
|
||||||
global CodeType t_void;
|
global CodeType t_void;
|
||||||
@ -83,4 +86,5 @@ global CodeSpecifiers spec_static_member;
|
|||||||
global CodeSpecifiers spec_thread_local;
|
global CodeSpecifiers spec_thread_local;
|
||||||
global CodeSpecifiers spec_virtual;
|
global CodeSpecifiers spec_virtual;
|
||||||
global CodeSpecifiers spec_volatile;
|
global CodeSpecifiers spec_volatile;
|
||||||
|
|
||||||
#pragma endregion Constants
|
#pragma endregion Constants
|
||||||
|
@ -9,6 +9,12 @@ namespace Parser
|
|||||||
Attributes_Start is only used to indicate the start of the user_defined attribute list.
|
Attributes_Start is only used to indicate the start of the user_defined attribute list.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
# define Define_TokType \
|
# define Define_TokType \
|
||||||
Entry( Invalid, "INVALID" ) \
|
Entry( Invalid, "INVALID" ) \
|
||||||
Entry( Access_Private, "private" ) \
|
Entry( Access_Private, "private" ) \
|
||||||
@ -49,8 +55,12 @@ namespace Parser
|
|||||||
Entry( Module_Export, "export" ) \
|
Entry( Module_Export, "export" ) \
|
||||||
Entry( Number, "number" ) \
|
Entry( Number, "number" ) \
|
||||||
Entry( Operator, "operator" ) \
|
Entry( Operator, "operator" ) \
|
||||||
Entry( Preprocessor_Directive, "#") \
|
Entry( Preprocess_Define, "#define") \
|
||||||
Entry( Preprocessor_Include, "include" ) \
|
Entry( Preproces_Include, "include" ) \
|
||||||
|
Entry( Preprocess_If, "#if") \
|
||||||
|
Entry( Preprocess_Elif, "#elif") \
|
||||||
|
Entry( Preprocess_Else, "#else") \
|
||||||
|
Entry( Preprocess_EndIf, "#endif") \
|
||||||
Entry( Spec_Alignas, "alignas" ) \
|
Entry( Spec_Alignas, "alignas" ) \
|
||||||
Entry( Spec_Const, "const" ) \
|
Entry( Spec_Const, "const" ) \
|
||||||
Entry( Spec_Consteval, "consteval" ) \
|
Entry( Spec_Consteval, "consteval" ) \
|
||||||
|
@ -84,6 +84,7 @@ Code& Code::operator ++()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#pragma region AST & Code Gen Common
|
#pragma region AST & Code Gen Common
|
||||||
|
|
||||||
#define Define_CodeImpl( Typename ) \
|
#define Define_CodeImpl( Typename ) \
|
||||||
char const* Typename::debug_str() \
|
char const* Typename::debug_str() \
|
||||||
{ \
|
{ \
|
||||||
@ -243,6 +244,7 @@ Define_CodeCast( Using );
|
|||||||
Define_CodeCast( Var );
|
Define_CodeCast( Var );
|
||||||
Define_CodeCast( Body);
|
Define_CodeCast( Body);
|
||||||
#undef Define_CodeCast
|
#undef Define_CodeCast
|
||||||
|
|
||||||
#pragma endregion AST & Code Gen Common
|
#pragma endregion AST & Code Gen Common
|
||||||
|
|
||||||
void CodeClass::add_interface( CodeType type )
|
void CodeClass::add_interface( CodeType type )
|
||||||
@ -361,9 +363,11 @@ StrC token_fmt_impl( sw num, ... )
|
|||||||
|
|
||||||
return { result, buf };
|
return { result, buf };
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion Inlines
|
#pragma endregion Inlines
|
||||||
|
|
||||||
#pragma region Constants
|
#pragma region Constants
|
||||||
|
|
||||||
#ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
#ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||||
// Predefined typename codes. Are set to readonly and are setup during gen::init()
|
// Predefined typename codes. Are set to readonly and are setup during gen::init()
|
||||||
|
|
||||||
@ -477,9 +481,11 @@ extern CodeSpecifiers spec_static_member;
|
|||||||
extern CodeSpecifiers spec_thread_local;
|
extern CodeSpecifiers spec_thread_local;
|
||||||
extern CodeSpecifiers spec_virtual;
|
extern CodeSpecifiers spec_virtual;
|
||||||
extern CodeSpecifiers spec_volatile;
|
extern CodeSpecifiers spec_volatile;
|
||||||
|
|
||||||
#pragma endregion Constants
|
#pragma endregion Constants
|
||||||
|
|
||||||
#pragma region Macros
|
#pragma region Macros
|
||||||
|
|
||||||
# define gen_main main
|
# define gen_main main
|
||||||
|
|
||||||
# define __ NoCode
|
# define __ NoCode
|
||||||
@ -498,9 +504,11 @@ extern CodeSpecifiers spec_volatile;
|
|||||||
|
|
||||||
// Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string.
|
// Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string.
|
||||||
# define token_fmt( ... ) gen::token_fmt_impl( (num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ )
|
# define token_fmt( ... ) gen::token_fmt_impl( (num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ )
|
||||||
|
|
||||||
#pragma endregion Macros
|
#pragma endregion Macros
|
||||||
|
|
||||||
#ifdef GEN_EXPOSE_BACKEND
|
#ifdef GEN_EXPOSE_BACKEND
|
||||||
|
|
||||||
// Global allocator used for data with process lifetime.
|
// Global allocator used for data with process lifetime.
|
||||||
extern AllocatorInfo GlobalAllocator;
|
extern AllocatorInfo GlobalAllocator;
|
||||||
extern Array< Arena > Global_AllocatorBuckets;
|
extern Array< Arena > Global_AllocatorBuckets;
|
||||||
@ -517,4 +525,5 @@ extern CodeSpecifiers spec_volatile;
|
|||||||
extern AllocatorInfo Allocator_StringArena;
|
extern AllocatorInfo Allocator_StringArena;
|
||||||
extern AllocatorInfo Allocator_StringTable;
|
extern AllocatorInfo Allocator_StringTable;
|
||||||
extern AllocatorInfo Allocator_TypeTable;
|
extern AllocatorInfo Allocator_TypeTable;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -4,13 +4,21 @@ These constructors are the most implementation intensive other than the editor o
|
|||||||
|
|
||||||
namespace Parser
|
namespace Parser
|
||||||
{
|
{
|
||||||
|
|
||||||
struct Token
|
struct Token
|
||||||
{
|
{
|
||||||
|
// TokType Type;
|
||||||
|
// s32 Start;
|
||||||
|
// s32 End;
|
||||||
|
// s32 Line;
|
||||||
|
// s32 Column;
|
||||||
|
// TokFlags Flags;
|
||||||
|
|
||||||
char const* Text;
|
char const* Text;
|
||||||
sptr Length;
|
sptr Length;
|
||||||
TokType Type;
|
TokType Type;
|
||||||
bool IsAssign;
|
bool IsAssign;
|
||||||
|
s32 Line;
|
||||||
|
s32 Column;
|
||||||
|
|
||||||
operator bool()
|
operator bool()
|
||||||
{
|
{
|
||||||
@ -21,60 +29,42 @@ namespace Parser
|
|||||||
{
|
{
|
||||||
return { Length, Text };
|
return { Length, Text };
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
internal inline
|
bool is_access_specifier()
|
||||||
bool tok_is_specifier( Token const& tok )
|
|
||||||
{
|
{
|
||||||
return (tok.Type <= TokType::Star && tok.Type >= TokType::Spec_Alignas)
|
return Type >= TokType::Access_Private && Type <= TokType::Access_Public;
|
||||||
|| tok.Type == TokType::Ampersand
|
}
|
||||||
|| tok.Type == TokType::Ampersand_DBL
|
|
||||||
|
bool is_attribute()
|
||||||
|
{
|
||||||
|
return Type > TokType::Attributes_Start;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_preprocessor()
|
||||||
|
{
|
||||||
|
return Type >= TokType::Preprocess_Define && Type <= TokType::Preprocess_EndIf;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_specifier()
|
||||||
|
{
|
||||||
|
return (Type <= TokType::Star && Type >= TokType::Spec_Alignas)
|
||||||
|
|| Type == TokType::Ampersand
|
||||||
|
|| Type == TokType::Ampersand_DBL
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal inline
|
AccessSpec to_access_specifier()
|
||||||
bool tok_is_access_specifier( Token const& tok )
|
|
||||||
{
|
{
|
||||||
return tok.Type >= TokType::Access_Private && tok.Type <= TokType::Access_Public;
|
return scast(AccessSpec, Type);
|
||||||
}
|
|
||||||
|
|
||||||
internal inline
|
|
||||||
AccessSpec tok_to_access_specifier( Token const& tok )
|
|
||||||
{
|
|
||||||
return scast(AccessSpec, tok.Type);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal inline
|
|
||||||
bool tok_is_attribute( Token const& tok )
|
|
||||||
{
|
|
||||||
return tok.Type > TokType::Attributes_Start;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct TokArray
|
struct TokArray
|
||||||
{
|
{
|
||||||
Array<Token> Arr;
|
Array<Token> Arr;
|
||||||
s32 Idx;
|
s32 Idx;
|
||||||
|
|
||||||
bool __eat( TokType type, char const* context )
|
bool __eat( TokType type );
|
||||||
{
|
|
||||||
if ( Arr.num() - Idx <= 0 )
|
|
||||||
{
|
|
||||||
log_failure( "gen::%s: No tokens left", context );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( Arr[Idx].Type != type )
|
|
||||||
{
|
|
||||||
String token_str = String::make( GlobalAllocator, { Arr[Idx].Length, Arr[Idx].Text } );
|
|
||||||
|
|
||||||
log_failure( "gen::%s: expected %s, got %s", context, ETokType::to_str(type), ETokType::to_str(Arr[Idx].Type) );
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Idx++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token& current()
|
Token& current()
|
||||||
{
|
{
|
||||||
@ -92,13 +82,87 @@ namespace Parser
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TokArray lex( StrC content, bool keep_preprocess_directives = false )
|
struct StackNode
|
||||||
|
{
|
||||||
|
StackNode* Prev;
|
||||||
|
|
||||||
|
Token Name; // The name of the AST node (if parsed)
|
||||||
|
StrC ProcName; // The name of the procedure
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParseContext
|
||||||
|
{
|
||||||
|
TokArray Tokens;
|
||||||
|
StackNode* Scope;
|
||||||
|
|
||||||
|
String to_string()
|
||||||
|
{
|
||||||
|
String result = String::make_reserve( GlobalAllocator, kilobytes(4) );
|
||||||
|
|
||||||
|
result.append_fmt("\tContext:\n");
|
||||||
|
|
||||||
|
StackNode* current = Scope;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
String name = String::make( GlobalAllocator, current->Name ? (StrC)current->Name : txt_StrC("Unresolved") );
|
||||||
|
|
||||||
|
result.append_fmt("\tProcedure: %s, AST Name: %s\n\t(%d, %d):", current->ProcName, name );
|
||||||
|
current = current->Prev;
|
||||||
|
|
||||||
|
name.free();
|
||||||
|
}
|
||||||
|
while ( current );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
global ParseContext Context;
|
||||||
|
|
||||||
|
bool TokArray::__eat( TokType type )
|
||||||
|
{
|
||||||
|
if ( Arr.num() - Idx <= 0 )
|
||||||
|
{
|
||||||
|
log_failure( "No tokens left\n", Context.Scope->ProcName );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Arr[Idx].Type != type )
|
||||||
|
{
|
||||||
|
String token_str = String::make( GlobalAllocator, { Arr[Idx].Length, Arr[Idx].Text } );
|
||||||
|
|
||||||
|
log_failure( "gen::%s: expected %s, got %s", Context.Scope->ProcName, ETokType::to_str(type), ETokType::to_str(Arr[Idx].Type) );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Idx++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TokFlags : u32
|
||||||
|
{
|
||||||
|
IsAssign = bit(0),
|
||||||
|
};
|
||||||
|
|
||||||
|
TokArray lex( StrC content, bool keep_preprocess_directives = true )
|
||||||
{
|
{
|
||||||
# define current ( * scanner )
|
# define current ( * scanner )
|
||||||
|
|
||||||
# define move_forward() \
|
# define move_forward() \
|
||||||
|
{ \
|
||||||
|
if ( current == '\n' ) \
|
||||||
|
{ \
|
||||||
|
line++; \
|
||||||
|
column = 0; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
column++; \
|
||||||
|
} \
|
||||||
left--; \
|
left--; \
|
||||||
scanner++
|
scanner++; \
|
||||||
|
}
|
||||||
|
|
||||||
# define SkipWhitespace() \
|
# define SkipWhitespace() \
|
||||||
while ( left && char_is_space( current ) ) \
|
while ( left && char_is_space( current ) ) \
|
||||||
@ -126,6 +190,9 @@ namespace Parser
|
|||||||
char const* word = scanner;
|
char const* word = scanner;
|
||||||
s32 word_length = 0;
|
s32 word_length = 0;
|
||||||
|
|
||||||
|
s32 line = 0;
|
||||||
|
s32 column = 0;
|
||||||
|
|
||||||
SkipWhitespace();
|
SkipWhitespace();
|
||||||
if ( left <= 0 )
|
if ( left <= 0 )
|
||||||
{
|
{
|
||||||
@ -142,7 +209,7 @@ namespace Parser
|
|||||||
|
|
||||||
while (left )
|
while (left )
|
||||||
{
|
{
|
||||||
Token token = { nullptr, 0, TokType::Invalid, false };
|
Token token = { nullptr, 0, TokType::Invalid, false, line, column };
|
||||||
|
|
||||||
SkipWhitespace();
|
SkipWhitespace();
|
||||||
if ( left <= 0 )
|
if ( left <= 0 )
|
||||||
@ -153,11 +220,15 @@ namespace Parser
|
|||||||
case '#':
|
case '#':
|
||||||
token.Text = scanner;
|
token.Text = scanner;
|
||||||
token.Length = 1;
|
token.Length = 1;
|
||||||
token.Type = TokType::Preprocessor_Directive;
|
|
||||||
move_forward();
|
move_forward();
|
||||||
|
|
||||||
while (left && current != '\n' )
|
while (left && current != '\n' )
|
||||||
{
|
{
|
||||||
|
if ( token.Type == ETokType::Invalid && current == ' ' )
|
||||||
|
{
|
||||||
|
token.Type = ETokType::to_type( token );
|
||||||
|
}
|
||||||
|
|
||||||
if ( current == '\\' )
|
if ( current == '\\' )
|
||||||
{
|
{
|
||||||
move_forward();
|
move_forward();
|
||||||
@ -178,8 +249,9 @@ namespace Parser
|
|||||||
token.Length = 1;
|
token.Length = 1;
|
||||||
token.Type = TokType::Access_MemberSymbol;
|
token.Type = TokType::Access_MemberSymbol;
|
||||||
|
|
||||||
if (left)
|
if (left) {
|
||||||
move_forward();
|
move_forward();
|
||||||
|
}
|
||||||
|
|
||||||
if ( current == '.' )
|
if ( current == '.' )
|
||||||
{
|
{
|
||||||
@ -577,7 +649,7 @@ namespace Parser
|
|||||||
|
|
||||||
if ( token.Type != TokType::Invalid )
|
if ( token.Type != TokType::Invalid )
|
||||||
{
|
{
|
||||||
if ( token.Type == TokType::Preprocessor_Directive && keep_preprocess_directives == false )
|
if ( token.is_preprocessor() && keep_preprocess_directives == false )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Tokens.append( token );
|
Tokens.append( token );
|
||||||
@ -608,6 +680,7 @@ namespace Parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
#pragma region Helper Macros
|
#pragma region Helper Macros
|
||||||
|
|
||||||
# define check_parse_args( func, def ) \
|
# define check_parse_args( func, def ) \
|
||||||
if ( def.Len <= 0 ) \
|
if ( def.Len <= 0 ) \
|
||||||
{ \
|
{ \
|
||||||
@ -620,13 +693,16 @@ if ( def.Ptr == nullptr ) \
|
|||||||
return CodeInvalid; \
|
return CodeInvalid; \
|
||||||
}
|
}
|
||||||
|
|
||||||
# define nexttok toks.next()
|
# define nexttok Context.Tokens.next()
|
||||||
# define currtok toks.current()
|
# define currtok Context.Tokens.current()
|
||||||
# define prevtok toks.previous()
|
# define prevtok Context.Tokens.previous()
|
||||||
# define eat( Type_ ) toks.__eat( Type_, context )
|
# define eat( Type_ ) Context.Tokens.__eat( Type_ )
|
||||||
# define left ( toks.Arr.num() - toks.Idx )
|
# define left ( Context.Tokens.Arr.num() - Context.Tokens.Idx )
|
||||||
|
|
||||||
# define check( Type_ ) ( left && currtok.Type == Type_ )
|
# define check( Type_ ) ( left && currtok.Type == Type_ )
|
||||||
|
|
||||||
|
// # define
|
||||||
|
|
||||||
#pragma endregion Helper Macros
|
#pragma endregion Helper Macros
|
||||||
|
|
||||||
struct ParseContext
|
struct ParseContext
|
||||||
@ -635,28 +711,28 @@ struct ParseContext
|
|||||||
char const* Fn;
|
char const* Fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
internal Code parse_function_body( Parser::TokArray& toks, char const* context );
|
internal Code parse_function_body();
|
||||||
internal Code parse_global_nspace( Parser::TokArray& toks, char const* context );
|
internal Code parse_global_nspace();
|
||||||
|
|
||||||
internal CodeClass parse_class ( Parser::TokArray& toks, char const* context );
|
internal CodeClass parse_class ();
|
||||||
internal CodeEnum parse_enum ( Parser::TokArray& toks, char const* context );
|
internal CodeEnum parse_enum ();
|
||||||
internal CodeBody parse_export_body ( Parser::TokArray& toks, char const* context );
|
internal CodeBody parse_export_body ();
|
||||||
internal CodeBody parse_extern_link_body( Parser::TokArray& toks, char const* context );
|
internal CodeBody parse_extern_link_body();
|
||||||
internal CodeExtern parse_exten_link ( Parser::TokArray& toks, char const* context );
|
internal CodeExtern parse_exten_link ();
|
||||||
internal CodeFriend parse_friend ( Parser::TokArray& toks, char const* context );
|
internal CodeFriend parse_friend ();
|
||||||
internal CodeFn parse_function ( Parser::TokArray& toks, char const* context );
|
internal CodeFn parse_function ();
|
||||||
internal CodeNamespace parse_namespace ( Parser::TokArray& toks, char const* context );
|
internal CodeNamespace parse_namespace ();
|
||||||
internal CodeOpCast parse_operator_cast ( Parser::TokArray& toks, char const* context );
|
internal CodeOpCast parse_operator_cast ();
|
||||||
internal CodeStruct parse_struct ( Parser::TokArray& toks, char const* context );
|
internal CodeStruct parse_struct ();
|
||||||
internal CodeVar parse_variable ( Parser::TokArray& toks, char const* context );
|
internal CodeVar parse_variable ();
|
||||||
internal CodeTemplate parse_template ( Parser::TokArray& toks, char const* context );
|
internal CodeTemplate parse_template ();
|
||||||
internal CodeType parse_type ( Parser::TokArray& toks, char const* context );
|
internal CodeType parse_type ();
|
||||||
internal CodeTypedef parse_typedef ( Parser::TokArray& toks, char const* context );
|
internal CodeTypedef parse_typedef ();
|
||||||
internal CodeUnion parse_union ( Parser::TokArray& toks, char const* context );
|
internal CodeUnion parse_union ();
|
||||||
internal CodeUsing parse_using ( Parser::TokArray& toks, char const* context );
|
internal CodeUsing parse_using ();
|
||||||
|
|
||||||
internal inline
|
internal inline
|
||||||
Code parse_array_decl( Parser::TokArray& toks, char const* context )
|
Code parse_array_decl()
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
|
||||||
@ -707,7 +783,7 @@ Code parse_array_decl( Parser::TokArray& toks, char const* context )
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal inline
|
internal inline
|
||||||
CodeAttributes parse_attributes( Parser::TokArray& toks, char const* context )
|
CodeAttributes parse_attributes()
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
|
||||||
@ -759,7 +835,7 @@ CodeAttributes parse_attributes( Parser::TokArray& toks, char const* context )
|
|||||||
s32 len = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)start.Text;
|
s32 len = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)start.Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( tok_is_attribute( currtok ) )
|
else if ( currtok.is_attribute() )
|
||||||
{
|
{
|
||||||
eat(currtok.Type);
|
eat(currtok.Type);
|
||||||
s32 len = start.Length;
|
s32 len = start.Length;
|
||||||
@ -775,7 +851,7 @@ CodeAttributes parse_attributes( Parser::TokArray& toks, char const* context )
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal inline
|
internal inline
|
||||||
Parser::Token parse_identifier( Parser::TokArray& toks, char const* context )
|
Parser::Token parse_identifier()
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
Token name = currtok;
|
Token name = currtok;
|
||||||
@ -788,7 +864,7 @@ Parser::Token parse_identifier( Parser::TokArray& toks, char const* context )
|
|||||||
|
|
||||||
if ( left == 0 )
|
if ( left == 0 )
|
||||||
{
|
{
|
||||||
log_failure( "%s: Error, unexpected end of type definition, expected identifier", context );
|
log_failure( "%s: Error, unexpected end of type definition, expected identifier", Context.to_string() );
|
||||||
return { nullptr, 0, TokType::Invalid };
|
return { nullptr, 0, TokType::Invalid };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -806,7 +882,7 @@ Parser::Token parse_identifier( Parser::TokArray& toks, char const* context )
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
CodeParam parse_params( Parser::TokArray& toks, char const* context, bool use_template_capture = false )
|
CodeParam parse_params( bool use_template_capture = false )
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
using namespace ECode;
|
using namespace ECode;
|
||||||
@ -973,15 +1049,13 @@ CodeFn parse_function_after_name(
|
|||||||
, CodeSpecifiers specifiers
|
, CodeSpecifiers specifiers
|
||||||
, CodeType ret_type
|
, CodeType ret_type
|
||||||
, StrC name
|
, StrC name
|
||||||
, Parser::TokArray& toks
|
|
||||||
, char const* context
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
|
||||||
CodeParam params = parse_params( toks, stringize(parse_function) );
|
CodeParam params = parse_params( toks, stringize(parse_function) );
|
||||||
|
|
||||||
while ( left && tok_is_specifier( currtok ) )
|
while ( left && currtok.is_specifier() )
|
||||||
{
|
{
|
||||||
specifiers.append( ESpecifier::to_type(currtok) );
|
specifiers.append( ESpecifier::to_type(currtok) );
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
@ -1041,12 +1115,12 @@ CodeFn parse_function_after_name(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal inline
|
internal inline
|
||||||
CodeOperator parse_operator_after_ret_type( ModuleFlag mflags
|
CodeOperator parse_operator_after_ret_type(
|
||||||
|
ModuleFlag mflags
|
||||||
, CodeAttributes attributes
|
, CodeAttributes attributes
|
||||||
, CodeSpecifiers specifiers
|
, CodeSpecifiers specifiers
|
||||||
, CodeType ret_type
|
, CodeType ret_type
|
||||||
, Parser::TokArray& toks
|
)
|
||||||
, char const* context )
|
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
using namespace EOperator;
|
using namespace EOperator;
|
||||||
@ -1251,7 +1325,7 @@ CodeOperator parse_operator_after_ret_type( ModuleFlag mflags
|
|||||||
// Parse Params
|
// Parse Params
|
||||||
CodeParam params = parse_params( toks, stringize(parse_operator) );
|
CodeParam params = parse_params( toks, stringize(parse_operator) );
|
||||||
|
|
||||||
while ( left && tok_is_specifier( currtok ) )
|
while ( left && currtok.is_specifier() )
|
||||||
{
|
{
|
||||||
specifiers.append( ESpecifier::to_type(currtok) );
|
specifiers.append( ESpecifier::to_type(currtok) );
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
@ -1341,7 +1415,7 @@ CodeVar parse_variable_after_name(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal inline
|
internal inline
|
||||||
Code parse_variable_assignment( Parser::TokArray& toks, char const* context )
|
Code parse_variable_assignment()
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
|
||||||
@ -1372,7 +1446,7 @@ Code parse_variable_assignment( Parser::TokArray& toks, char const* context )
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal inline
|
internal inline
|
||||||
Code parse_operator_function_or_variable( bool expects_function, CodeAttributes attributes, CodeSpecifiers specifiers, Parser::TokArray& toks, char const* context )
|
Code parse_operator_function_or_variable( bool expects_function, CodeAttributes attributes, CodeSpecifiers specifiers )
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
|
||||||
@ -1416,7 +1490,7 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
CodeBody parse_class_struct_body( Parser::TokType which, Parser::TokArray& toks, char const* context )
|
CodeBody parse_class_struct_body( Parser::TokType which )
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
using namespace ECode;
|
using namespace ECode;
|
||||||
@ -1508,7 +1582,7 @@ CodeBody parse_class_struct_body( Parser::TokType which, Parser::TokArray& toks,
|
|||||||
GEN_Define_Attribute_Tokens
|
GEN_Define_Attribute_Tokens
|
||||||
#undef Entry
|
#undef Entry
|
||||||
{
|
{
|
||||||
attributes = parse_attributes( toks, context );
|
attributes = parse_attributes();
|
||||||
}
|
}
|
||||||
//! Fallthrough intended
|
//! Fallthrough intended
|
||||||
case TokType::Spec_Consteval:
|
case TokType::Spec_Consteval:
|
||||||
@ -1522,7 +1596,7 @@ CodeBody parse_class_struct_body( Parser::TokType which, Parser::TokArray& toks,
|
|||||||
SpecifierT specs_found[16] { ESpecifier::NumSpecifiers };
|
SpecifierT specs_found[16] { ESpecifier::NumSpecifiers };
|
||||||
s32 NumSpecifiers = 0;
|
s32 NumSpecifiers = 0;
|
||||||
|
|
||||||
while ( left && tok_is_specifier( currtok ) )
|
while ( left && currtok.is_specifier() )
|
||||||
{
|
{
|
||||||
SpecifierT spec = ESpecifier::to_type( currtok );
|
SpecifierT spec = ESpecifier::to_type( currtok );
|
||||||
|
|
||||||
@ -1597,7 +1671,7 @@ CodeBody parse_class_struct_body( Parser::TokType which, Parser::TokArray& toks,
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char const* context )
|
Code parse_class_struct( Parser::TokType which )
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
|
||||||
@ -1625,7 +1699,7 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con
|
|||||||
|
|
||||||
eat( which );
|
eat( which );
|
||||||
|
|
||||||
attributes = parse_attributes( toks, context );
|
attributes = parse_attributes();
|
||||||
|
|
||||||
if ( check( TokType::Identifier ) )
|
if ( check( TokType::Identifier ) )
|
||||||
name = parse_identifier( toks, context );
|
name = parse_identifier( toks, context );
|
||||||
@ -1638,9 +1712,9 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con
|
|||||||
{
|
{
|
||||||
eat( TokType::Assign_Classifer );
|
eat( TokType::Assign_Classifer );
|
||||||
|
|
||||||
if ( tok_is_access_specifier( currtok ) )
|
if ( currtok.is_access_specifier() )
|
||||||
{
|
{
|
||||||
access = tok_to_access_specifier( currtok );
|
access = currtok.to_access_specifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
Token parent_tok = parse_identifier( toks, context );
|
Token parent_tok = parse_identifier( toks, context );
|
||||||
@ -1650,7 +1724,7 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con
|
|||||||
{
|
{
|
||||||
eat(TokType::Access_Public);
|
eat(TokType::Access_Public);
|
||||||
|
|
||||||
if ( tok_is_access_specifier( currtok ) )
|
if ( currtok.is_access_specifier() )
|
||||||
{
|
{
|
||||||
eat(currtok.Type);
|
eat(currtok.Type);
|
||||||
}
|
}
|
||||||
@ -1685,7 +1759,7 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
Code parse_function_body( Parser::TokArray& toks, char const* context )
|
Code parse_function_body()
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
using namespace ECode;
|
using namespace ECode;
|
||||||
@ -1724,7 +1798,7 @@ Code parse_function_body( Parser::TokArray& toks, char const* context )
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
CodeBody parse_global_nspace( CodeT which, Parser::TokArray& toks, char const* context )
|
CodeBody parse_global_nspace( CodeT which )
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
using namespace ECode;
|
using namespace ECode;
|
||||||
@ -1811,7 +1885,7 @@ CodeBody parse_global_nspace( CodeT which, Parser::TokArray& toks, char const* c
|
|||||||
GEN_Define_Attribute_Tokens
|
GEN_Define_Attribute_Tokens
|
||||||
#undef Entry
|
#undef Entry
|
||||||
{
|
{
|
||||||
attributes = parse_attributes( toks, context );
|
attributes = parse_attributes();
|
||||||
}
|
}
|
||||||
//! Fallthrough intentional
|
//! Fallthrough intentional
|
||||||
case TokType::Spec_Consteval:
|
case TokType::Spec_Consteval:
|
||||||
@ -1826,7 +1900,7 @@ CodeBody parse_global_nspace( CodeT which, Parser::TokArray& toks, char const* c
|
|||||||
SpecifierT specs_found[16] { ESpecifier::NumSpecifiers };
|
SpecifierT specs_found[16] { ESpecifier::NumSpecifiers };
|
||||||
s32 NumSpecifiers = 0;
|
s32 NumSpecifiers = 0;
|
||||||
|
|
||||||
while ( left && tok_is_specifier( currtok ) )
|
while ( left && currtok.is_specifier() )
|
||||||
{
|
{
|
||||||
SpecifierT spec = ESpecifier::to_type( currtok );
|
SpecifierT spec = ESpecifier::to_type( currtok );
|
||||||
|
|
||||||
@ -1890,7 +1964,7 @@ CodeBody parse_global_nspace( CodeT which, Parser::TokArray& toks, char const* c
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
CodeClass parse_class( Parser::TokArray& toks, char const* context )
|
CodeClass parse_class()
|
||||||
{
|
{
|
||||||
return (CodeClass) parse_class_struct( Parser::TokType::Decl_Class, toks, context );
|
return (CodeClass) parse_class_struct( Parser::TokType::Decl_Class, toks, context );
|
||||||
}
|
}
|
||||||
@ -1908,7 +1982,7 @@ CodeClass parse_class( StrC def )
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
CodeEnum parse_enum( Parser::TokArray& toks, char const* context )
|
CodeEnum parse_enum()
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
using namespace ECode;
|
using namespace ECode;
|
||||||
@ -2027,7 +2101,7 @@ CodeEnum parse_enum( StrC def )
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal inline
|
internal inline
|
||||||
CodeBody parse_export_body( Parser::TokArray& toks, char const* context )
|
CodeBody parse_export_body()
|
||||||
{
|
{
|
||||||
return parse_global_nspace( ECode::Export_Body, toks, context );
|
return parse_global_nspace( ECode::Export_Body, toks, context );
|
||||||
}
|
}
|
||||||
@ -2170,9 +2244,9 @@ CodeFn parse_functon( Parser::TokArray& toks, char const* context )
|
|||||||
eat( TokType::Module_Export );
|
eat( TokType::Module_Export );
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes = parse_attributes( toks, context );
|
attributes = parse_attributes();
|
||||||
|
|
||||||
while ( left && tok_is_specifier( currtok ) )
|
while ( left && currtok.is_specifier() )
|
||||||
{
|
{
|
||||||
SpecifierT spec = ESpecifier::to_type( currtok );
|
SpecifierT spec = ESpecifier::to_type( currtok );
|
||||||
|
|
||||||
@ -2294,9 +2368,9 @@ CodeOperator parse_operator( Parser::TokArray& toks, char const* context )
|
|||||||
eat( TokType::Module_Export );
|
eat( TokType::Module_Export );
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes = parse_attributes( toks, context );
|
attributes = parse_attributes();
|
||||||
|
|
||||||
while ( left && tok_is_specifier( currtok ) )
|
while ( left && currtok.is_specifier() )
|
||||||
{
|
{
|
||||||
SpecifierT spec = ESpecifier::to_type( currtok );
|
SpecifierT spec = ESpecifier::to_type( currtok );
|
||||||
|
|
||||||
@ -2492,9 +2566,9 @@ CodeTemplate parse_template( Parser::TokArray& toks, char const* context )
|
|||||||
SpecifierT specs_found[16] { ESpecifier::NumSpecifiers };
|
SpecifierT specs_found[16] { ESpecifier::NumSpecifiers };
|
||||||
s32 NumSpecifiers = 0;
|
s32 NumSpecifiers = 0;
|
||||||
|
|
||||||
attributes = parse_attributes( toks, stringize(parse_template) );
|
attributes = parse_attributes();
|
||||||
|
|
||||||
while ( left && tok_is_specifier( currtok ) )
|
while ( left && currtok.is_specifier() )
|
||||||
{
|
{
|
||||||
SpecifierT spec = ESpecifier::to_type( currtok );
|
SpecifierT spec = ESpecifier::to_type( currtok );
|
||||||
|
|
||||||
@ -2576,9 +2650,9 @@ CodeType parse_type( Parser::TokArray& toks, char const* context )
|
|||||||
Token name = { nullptr, 0, TokType::Invalid };
|
Token name = { nullptr, 0, TokType::Invalid };
|
||||||
Token brute_sig = { currtok.Text, 0, TokType::Invalid };
|
Token brute_sig = { currtok.Text, 0, TokType::Invalid };
|
||||||
|
|
||||||
CodeAttributes attributes = parse_attributes( toks, context );
|
CodeAttributes attributes = parse_attributes();
|
||||||
|
|
||||||
while ( left && tok_is_specifier( currtok ) )
|
while ( left && currtok.is_specifier() )
|
||||||
{
|
{
|
||||||
SpecifierT spec = ESpecifier::to_type( currtok );
|
SpecifierT spec = ESpecifier::to_type( currtok );
|
||||||
|
|
||||||
@ -2651,7 +2725,7 @@ CodeType parse_type( Parser::TokArray& toks, char const* context )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( left && tok_is_specifier( currtok ) )
|
while ( left && currtok.is_specifier() )
|
||||||
{
|
{
|
||||||
SpecifierT spec = ESpecifier::to_type( currtok );
|
SpecifierT spec = ESpecifier::to_type( currtok );
|
||||||
|
|
||||||
@ -2842,7 +2916,7 @@ CodeUnion parse_union( Parser::TokArray& toks, char const* context )
|
|||||||
|
|
||||||
eat( TokType::Decl_Union );
|
eat( TokType::Decl_Union );
|
||||||
|
|
||||||
CodeAttributes attributes = parse_attributes( toks, context );
|
CodeAttributes attributes = parse_attributes();
|
||||||
|
|
||||||
StrC name = { 0, nullptr };
|
StrC name = { 0, nullptr };
|
||||||
|
|
||||||
@ -2986,12 +3060,10 @@ CodeUsing parse_using( StrC def )
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
CodeVar parse_variable( Parser::TokArray& toks, char const* context )
|
CodeVar parse_variable()
|
||||||
{
|
{
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
|
||||||
Token name = { nullptr, 0, TokType::Invalid };
|
|
||||||
|
|
||||||
SpecifierT specs_found[16] { ESpecifier::NumSpecifiers };
|
SpecifierT specs_found[16] { ESpecifier::NumSpecifiers };
|
||||||
s32 NumSpecifiers = 0;
|
s32 NumSpecifiers = 0;
|
||||||
|
|
||||||
@ -3005,7 +3077,7 @@ CodeVar parse_variable( Parser::TokArray& toks, char const* context )
|
|||||||
eat( TokType::Module_Export );
|
eat( TokType::Module_Export );
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes = parse_attributes( toks, context );
|
attributes = parse_attributes();
|
||||||
|
|
||||||
while ( left && tok_is_specifier( currtok ) )
|
while ( left && tok_is_specifier( currtok ) )
|
||||||
{
|
{
|
||||||
@ -3050,24 +3122,32 @@ CodeVar parse_variable( Parser::TokArray& toks, char const* context )
|
|||||||
if ( type == Code::Invalid )
|
if ( type == Code::Invalid )
|
||||||
return CodeInvalid;
|
return CodeInvalid;
|
||||||
|
|
||||||
name = currtok;
|
Context.Scope->Name = current;
|
||||||
eat( TokType::Identifier );
|
eat( TokType::Identifier );
|
||||||
|
|
||||||
CodeVar result = parse_variable_after_name( mflags, attributes, specifiers, type, name, toks, context );
|
CodeVar result = parse_variable_after_name( mflags, attributes, specifiers, type, Context.Scope->Name, Context.Tokens, Context.Scope->ProcName );
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeVar parse_variable( StrC def )
|
CodeVar parse_variable( StrC def )
|
||||||
{
|
{
|
||||||
check_parse_args( parse_variable, def );
|
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
check_parse_args( parse_variable, def );
|
||||||
|
|
||||||
TokArray toks = lex( def );
|
TokArray toks = lex( def );
|
||||||
if ( toks.Arr == nullptr )
|
if ( toks.Arr == nullptr )
|
||||||
return CodeInvalid;
|
return CodeInvalid;
|
||||||
|
|
||||||
return parse_variable( toks, stringize(parse_variable) );
|
Context.Tokens = toks;
|
||||||
|
Parser::StackNode root
|
||||||
|
{
|
||||||
|
toks.current(),
|
||||||
|
{ nullptr, 0, TokType::Invalid },
|
||||||
|
name(parse_variable)
|
||||||
|
};
|
||||||
|
|
||||||
|
return parse_variable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Undef helper macros
|
// Undef helper macros
|
||||||
@ -3075,4 +3155,3 @@ CodeVar parse_variable( StrC def )
|
|||||||
# undef curr_tok
|
# undef curr_tok
|
||||||
# undef eat
|
# undef eat
|
||||||
# undef left
|
# undef left
|
||||||
|
|
||||||
|
@ -1338,7 +1338,7 @@ CodeBody def_class_body( s32 num, ... )
|
|||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, num);
|
va_start(va, num);
|
||||||
def_body_code_validation_start( def_class_body );
|
def_body_code_validation_start( def_class_body );
|
||||||
AST_BODY_CLASS_UNALLOWED_TYPES
|
GEN_AST_BODY_CLASS_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_class_body );
|
def_body_code_validation_end( def_class_body );
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
@ -1354,7 +1354,7 @@ CodeBody def_class_body( s32 num, Code* codes )
|
|||||||
result->Type = Function_Body;
|
result->Type = Function_Body;
|
||||||
|
|
||||||
def_body_code_array_validation_start( def_class_body );
|
def_body_code_array_validation_start( def_class_body );
|
||||||
AST_BODY_CLASS_UNALLOWED_TYPES
|
GEN_AST_BODY_CLASS_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_class_body );
|
def_body_code_validation_end( def_class_body );
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -1437,7 +1437,7 @@ CodeBody def_export_body( s32 num, ... )
|
|||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, num);
|
va_start(va, num);
|
||||||
def_body_code_validation_start( def_export_body );
|
def_body_code_validation_start( def_export_body );
|
||||||
AST_BODY_EXPORT_UNALLOWED_TYPES
|
GEN_AST_BODY_EXPORT_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_export_body );
|
def_body_code_validation_end( def_export_body );
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
@ -1453,7 +1453,7 @@ CodeBody def_export_body( s32 num, Code* codes )
|
|||||||
result->Type = Export_Body;
|
result->Type = Export_Body;
|
||||||
|
|
||||||
def_body_code_array_validation_start( def_export_body );
|
def_body_code_array_validation_start( def_export_body );
|
||||||
AST_BODY_EXPORT_UNALLOWED_TYPES
|
GEN_AST_BODY_EXPORT_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_export_body );
|
def_body_code_validation_end( def_export_body );
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -1470,7 +1470,7 @@ CodeBody def_extern_link_body( s32 num, ... )
|
|||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, num);
|
va_start(va, num);
|
||||||
def_body_code_validation_start( def_extern_linkage_body );
|
def_body_code_validation_start( def_extern_linkage_body );
|
||||||
AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES
|
GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_extern_linkage_body );
|
def_body_code_validation_end( def_extern_linkage_body );
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
@ -1486,7 +1486,7 @@ CodeBody def_extern_link_body( s32 num, Code* codes )
|
|||||||
result->Type = Extern_Linkage_Body;
|
result->Type = Extern_Linkage_Body;
|
||||||
|
|
||||||
def_body_code_array_validation_start( def_extern_linkage_body );
|
def_body_code_array_validation_start( def_extern_linkage_body );
|
||||||
AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES
|
GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_extern_linkage_body );
|
def_body_code_validation_end( def_extern_linkage_body );
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -1503,7 +1503,7 @@ CodeBody def_function_body( s32 num, ... )
|
|||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, num);
|
va_start(va, num);
|
||||||
def_body_code_validation_start( def_function_body );
|
def_body_code_validation_start( def_function_body );
|
||||||
AST_BODY_FUNCTION_UNALLOWED_TYPES
|
GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_function_body );
|
def_body_code_validation_end( def_function_body );
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
@ -1519,7 +1519,7 @@ CodeBody def_function_body( s32 num, Code* codes )
|
|||||||
result->Type = Function_Body;
|
result->Type = Function_Body;
|
||||||
|
|
||||||
def_body_code_array_validation_start( def_function_body );
|
def_body_code_array_validation_start( def_function_body );
|
||||||
AST_BODY_FUNCTION_UNALLOWED_TYPES
|
GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_function_body );
|
def_body_code_validation_end( def_function_body );
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -1536,7 +1536,7 @@ CodeBody def_global_body( s32 num, ... )
|
|||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, num);
|
va_start(va, num);
|
||||||
def_body_code_validation_start( def_global_body );
|
def_body_code_validation_start( def_global_body );
|
||||||
AST_BODY_GLOBAL_UNALLOWED_TYPES
|
GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_global_body );
|
def_body_code_validation_end( def_global_body );
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
@ -1552,7 +1552,7 @@ CodeBody def_global_body( s32 num, Code* codes )
|
|||||||
result->Type = Global_Body;
|
result->Type = Global_Body;
|
||||||
|
|
||||||
def_body_code_array_validation_start( def_global_body );
|
def_body_code_array_validation_start( def_global_body );
|
||||||
AST_BODY_GLOBAL_UNALLOWED_TYPES
|
GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_global_body );
|
def_body_code_validation_end( def_global_body );
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -1569,7 +1569,7 @@ CodeBody def_namespace_body( s32 num, ... )
|
|||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, num);
|
va_start(va, num);
|
||||||
def_body_code_validation_start( def_namespace_body );
|
def_body_code_validation_start( def_namespace_body );
|
||||||
AST_BODY_NAMESPACE_UNALLOWED_TYPES
|
GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_namespace_body );
|
def_body_code_validation_end( def_namespace_body );
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
@ -1585,7 +1585,7 @@ CodeBody def_namespace_body( s32 num, Code* codes )
|
|||||||
result->Type = Global_Body;
|
result->Type = Global_Body;
|
||||||
|
|
||||||
def_body_code_array_validation_start( def_namespace_body );
|
def_body_code_array_validation_start( def_namespace_body );
|
||||||
AST_BODY_NAMESPACE_UNALLOWED_TYPES
|
GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_namespace_body );
|
def_body_code_validation_end( def_namespace_body );
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -1737,7 +1737,7 @@ CodeBody def_struct_body( s32 num, ... )
|
|||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, num);
|
va_start(va, num);
|
||||||
def_body_code_validation_start( def_struct_body );
|
def_body_code_validation_start( def_struct_body );
|
||||||
AST_BODY_STRUCT_UNALLOWED_TYPES
|
GEN_AST_BODY_STRUCT_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_struct_body );
|
def_body_code_validation_end( def_struct_body );
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
@ -1753,7 +1753,7 @@ CodeBody def_struct_body( s32 num, Code* codes )
|
|||||||
result->Type = Struct_Body;
|
result->Type = Struct_Body;
|
||||||
|
|
||||||
def_body_code_array_validation_start( def_struct_body );
|
def_body_code_array_validation_start( def_struct_body );
|
||||||
AST_BODY_STRUCT_UNALLOWED_TYPES
|
GEN_AST_BODY_STRUCT_UNALLOWED_TYPES
|
||||||
def_body_code_validation_end( def_struct_body );
|
def_body_code_validation_end( def_struct_body );
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -100,10 +100,3 @@ constexpr char const* Attribute_Keyword = stringize( GEN_Attribute_Keyword );
|
|||||||
|
|
||||||
constexpr char const* Attribute_Keyword = "";
|
constexpr char const* Attribute_Keyword = "";
|
||||||
#endif
|
#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
|
|
||||||
|
|
||||||
|
@ -50,7 +50,6 @@ CodeBody gen_ecode( char const* path )
|
|||||||
#pragma pop_macro( "local_persist" )
|
#pragma pop_macro( "local_persist" )
|
||||||
|
|
||||||
CodeNamespace nspace = def_namespace( name(ECode), def_namespace_body( args( enum_code, to_str ) ) );
|
CodeNamespace nspace = def_namespace( name(ECode), def_namespace_body( args( enum_code, to_str ) ) );
|
||||||
|
|
||||||
CodeUsing code_t = def_using( name(CodeT), def_type( name(ECode::Type) ) );
|
CodeUsing code_t = def_using( name(CodeT), def_type( name(ECode::Type) ) );
|
||||||
|
|
||||||
return def_global_body( args( nspace, code_t ) );
|
return def_global_body( args( nspace, code_t ) );
|
||||||
@ -217,8 +216,6 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path )
|
|||||||
CSV_Object csv_enum_nodes;
|
CSV_Object csv_enum_nodes;
|
||||||
csv_parse( &csv_enum_nodes, rcast(char*, enum_content.data), GlobalAllocator, false );
|
csv_parse( &csv_enum_nodes, rcast(char*, enum_content.data), GlobalAllocator, false );
|
||||||
|
|
||||||
// memset( scratch_mem, 0, sizeof(scratch_mem) );
|
|
||||||
// scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) );
|
|
||||||
FileContents attrib_content = file_read_contents( scratch, zero_terminate, attr_path );
|
FileContents attrib_content = file_read_contents( scratch, zero_terminate, attr_path );
|
||||||
|
|
||||||
CSV_Object csv_attr_nodes;
|
CSV_Object csv_attr_nodes;
|
||||||
|
Loading…
Reference in New Issue
Block a user