mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-30 14:30:53 -07:00 
			
		
		
		
	Started to implement context stack for parser.
This commit is contained in:
		
							
								
								
									
										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.   | ||||
| 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),   | ||||
| 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: | ||||
|  | ||||
| * `errno.h`    (gen.dep.cpp) | ||||
| * `stat.h`     (gen.dep.cpp) | ||||
| * `stdarg.h`   (gen.dep.hpp) | ||||
| * `stddef.h`   (gen.dep.hpp | ||||
| * `stdio.h`    (gen.dep.cpp) | ||||
| * `copyfile.h` (Mac, gen.dep.cpp) | ||||
| * `types.h`    (Linux, gen.dep.cpp) | ||||
| * `unistd.h`   (Linux/Mac, gen.dep.cpp) | ||||
| * `intrin.h`   (Windows, gen.dep.hpp) | ||||
| * `io.h`       (Windows with gcc, gen.dep.cpp) | ||||
| * `windows.h`  (Windows, gen.dep.cpp) | ||||
| * `errno.h` | ||||
| * `stat.h` | ||||
| * `stdarg.h` | ||||
| * `stddef.h` | ||||
| * `stdio.h` | ||||
| * `copyfile.h` (Mac) | ||||
| * `types.h`    (Linux) | ||||
| * `unistd.h`   (Linux/Mac) | ||||
| * `intrin.h`   (Windows) | ||||
| * `io.h`       (Windows with gcc) | ||||
| * `windows.h`  (Windows) | ||||
|  | ||||
| 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). | ||||
| @@ -561,6 +556,7 @@ The following are provided predefined by the library as they are commonly used: | ||||
| * `access_private` | ||||
| * `module_global_fragment` | ||||
| * `module_private_fragment` | ||||
| * `param_varaidc` (Used for varadic definitions) | ||||
| * `pragma_once` | ||||
| * `spec_const` | ||||
| * `spec_consteval` | ||||
| @@ -586,7 +582,7 @@ The following are provided predefined by the library as they are commonly used: | ||||
| * `spec_type_unsigned` | ||||
| * `spec_type_short` | ||||
| * `spec_type_long` | ||||
| * `t_empty` | ||||
| * `t_empty` (Used for varaidc macros) | ||||
| * `t_auto` | ||||
| * `t_void` | ||||
| * `t_int` | ||||
|   | ||||
| @@ -37,8 +37,12 @@ Module_Import,          "import" | ||||
| Module_Export,          "export" | ||||
| Number,                 "number" | ||||
| Operator,               "operator" | ||||
| Preprocessor_Directive, "#" | ||||
| Preprocessor_Include,   "include" | ||||
| Preprocess_Define,      "#define" | ||||
| Preprocess_Include,     "#include" | ||||
| Preprocess_If,          "#if" | ||||
| Preprocess_ElIF,		"#elif" | ||||
| Preprocess_Else,        "#else" | ||||
| Preprocess_EndIf,       "#endif" | ||||
| Spec_Alignas,           "alignas" | ||||
| Spec_Const,             "const" | ||||
| Spec_Consteval,         "consteval" | ||||
|   | ||||
| 
 | 
| @@ -778,7 +778,7 @@ bool AST::validate_body() | ||||
| 	switch ( Type ) | ||||
| 	{ | ||||
| 		case Class_Body: | ||||
| 			CheckEntries( AST_BODY_CLASS_UNALLOWED_TYPES ); | ||||
| 			CheckEntries( GEN_AST_BODY_CLASS_UNALLOWED_TYPES ); | ||||
| 		break; | ||||
| 		case Enum_Body: | ||||
| 			for ( Code entry : cast<CodeBody>() ) | ||||
| @@ -791,22 +791,22 @@ bool AST::validate_body() | ||||
| 			} | ||||
| 		break; | ||||
| 		case Export_Body: | ||||
| 			CheckEntries( AST_BODY_CLASS_UNALLOWED_TYPES ); | ||||
| 			CheckEntries( GEN_AST_BODY_CLASS_UNALLOWED_TYPES ); | ||||
| 		break; | ||||
| 		case Extern_Linkage: | ||||
| 			CheckEntries( AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES ); | ||||
| 			CheckEntries( GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES ); | ||||
| 		break; | ||||
| 		case Function_Body: | ||||
| 			CheckEntries( AST_BODY_FUNCTION_UNALLOWED_TYPES ); | ||||
| 			CheckEntries( GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES ); | ||||
| 		break; | ||||
| 		case Global_Body: | ||||
| 			CheckEntries( AST_BODY_GLOBAL_UNALLOWED_TYPES ); | ||||
| 			CheckEntries( GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES ); | ||||
| 		break; | ||||
| 		case Namespace_Body: | ||||
| 			CheckEntries( AST_BODY_NAMESPACE_UNALLOWED_TYPES ); | ||||
| 			CheckEntries( GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES ); | ||||
| 		break; | ||||
| 		case Struct_Body: | ||||
| 			CheckEntries( AST_BODY_STRUCT_UNALLOWED_TYPES ); | ||||
| 			CheckEntries( GEN_AST_BODY_STRUCT_UNALLOWED_TYPES ); | ||||
| 		break; | ||||
| 		case Union_Body: | ||||
| 			for ( Code entry : Body->cast<CodeBody>() ) | ||||
|   | ||||
| @@ -1,81 +1,79 @@ | ||||
| #	define AST_BODY_CLASS_UNALLOWED_TYPES \ | ||||
| 	case PlatformAttributes:              \ | ||||
| 	case Class_Body:                      \ | ||||
| 	case Enum_Body:                       \ | ||||
| 	case Extern_Linkage:                  \ | ||||
| 	case Function_Body:                   \ | ||||
| 	case Function_Fwd:                    \ | ||||
| 	case Global_Body:                     \ | ||||
| 	case Namespace:                       \ | ||||
| 	case Namespace_Body:                  \ | ||||
| 	case Operator:                        \ | ||||
| 	case Operator_Fwd:                    \ | ||||
| 	case Parameters:                      \ | ||||
| 	case Specifiers:                      \ | ||||
| 	case Struct_Body:                     \ | ||||
| 	case Typename: | ||||
|  | ||||
| #	define AST_BODY_FUNCTION_UNALLOWED_TYPES \ | ||||
| 	case Access_Public:                      \ | ||||
| 	case Access_Protected:                   \ | ||||
| 	case Access_Private:                     \ | ||||
| 	case PlatformAttributes:                 \ | ||||
| 	case Class_Body:                         \ | ||||
| 	case Enum_Body:                          \ | ||||
| 	case Extern_Linkage:                     \ | ||||
| 	case Friend:                             \ | ||||
| 	case Function_Body:                      \ | ||||
| 	case Function_Fwd:                       \ | ||||
| 	case Global_Body:                        \ | ||||
| 	case Namespace:                          \ | ||||
| 	case Namespace_Body:                     \ | ||||
| 	case Operator:                           \ | ||||
| 	case Operator_Fwd:                       \ | ||||
| 	case Operator_Member:                    \ | ||||
| 	case Operator_Member_Fwd:                \ | ||||
| 	case Parameters:                         \ | ||||
| 	case Specifiers:                         \ | ||||
| 	case Struct_Body:                        \ | ||||
| 	case Typename: | ||||
|  | ||||
| #	define AST_BODY_GLOBAL_UNALLOWED_TYPES \ | ||||
| 	case Access_Public: 				   \ | ||||
| 	case Access_Protected: 				   \ | ||||
| 	case Access_Private: 				   \ | ||||
| 	case PlatformAttributes:               \ | ||||
| 	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_EXPORT_UNALLOWED_TYPES         AST_BODY_GLOBAL_UNALLOWED_TYPES | ||||
| #	define AST_BODY_NAMESPACE_UNALLOWED_TYPES \ | ||||
| 	case Access_Public: 				      \ | ||||
| 	case Access_Protected: 				      \ | ||||
| 	case Access_Private: 				      \ | ||||
| #	define GEN_AST_BODY_CLASS_UNALLOWED_TYPES \ | ||||
| 	case PlatformAttributes:                  \ | ||||
| 	case Class_Body: 					      \ | ||||
| 	case Enum_Body: 					      \ | ||||
| 	case Execution: 					      \ | ||||
| 	case Friend: 						      \ | ||||
| 	case Function_Body: 				      \ | ||||
| 	case Namespace_Body: 				      \ | ||||
| 	case Operator_Member: 				      \ | ||||
| 	case Operator_Member_Fwd: 			      \ | ||||
| 	case Parameters: 					      \ | ||||
| 	case Specifiers: 					      \ | ||||
| 	case Struct_Body: 					      \ | ||||
| 	case Class_Body:                          \ | ||||
| 	case Enum_Body:                           \ | ||||
| 	case Extern_Linkage:                      \ | ||||
| 	case Function_Body:                       \ | ||||
| 	case Function_Fwd:                        \ | ||||
| 	case Global_Body:                         \ | ||||
| 	case Namespace:                           \ | ||||
| 	case Namespace_Body:                      \ | ||||
| 	case Operator:                            \ | ||||
| 	case Operator_Fwd:                        \ | ||||
| 	case Parameters:                          \ | ||||
| 	case Specifiers:                          \ | ||||
| 	case Struct_Body:                         \ | ||||
| 	case Typename: | ||||
| #	define GEN_AST_BODY_STRUCT_UNALLOWED_TYPES GEN_AST_BODY_CLASS_UNALLOWED_TYPES | ||||
|  | ||||
| #	define GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES \ | ||||
| 	case Access_Public:                          \ | ||||
| 	case Access_Protected:                       \ | ||||
| 	case Access_Private:                         \ | ||||
| 	case PlatformAttributes:                     \ | ||||
| 	case Class_Body:                             \ | ||||
| 	case Enum_Body:                              \ | ||||
| 	case Extern_Linkage:                         \ | ||||
| 	case Friend:                                 \ | ||||
| 	case Function_Body:                          \ | ||||
| 	case Function_Fwd:                           \ | ||||
| 	case Global_Body:                            \ | ||||
| 	case Namespace:                              \ | ||||
| 	case Namespace_Body:                         \ | ||||
| 	case Operator:                               \ | ||||
| 	case Operator_Fwd:                           \ | ||||
| 	case Operator_Member:                        \ | ||||
| 	case Operator_Member_Fwd:                    \ | ||||
| 	case Parameters:                             \ | ||||
| 	case Specifiers:                             \ | ||||
| 	case Struct_Body:                            \ | ||||
| 	case Typename: | ||||
|  | ||||
| #	define AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES AST_BODY_GLOBAL_UNALLOWED_TYPES | ||||
| #	define GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES \ | ||||
| 	case Access_Public: 				       \ | ||||
| 	case Access_Protected: 				       \ | ||||
| 	case Access_Private: 				       \ | ||||
| 	case PlatformAttributes:                   \ | ||||
| 	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 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_STRUCT_UNALLOWED_TYPES         AST_BODY_CLASS_UNALLOWED_TYPES | ||||
| #	define GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES \ | ||||
| 	case Access_Public: 				          \ | ||||
| 	case Access_Protected: 				          \ | ||||
| 	case Access_Private: 				          \ | ||||
| 	case PlatformAttributes:                      \ | ||||
| 	case Class_Body: 					          \ | ||||
| 	case Enum_Body: 					          \ | ||||
| 	case Execution: 					          \ | ||||
| 	case Friend: 						          \ | ||||
| 	case Function_Body: 				          \ | ||||
| 	case Namespace_Body: 				          \ | ||||
| 	case Operator_Member: 				          \ | ||||
| 	case Operator_Member_Fwd: 			          \ | ||||
| 	case Parameters: 					          \ | ||||
| 	case Specifiers: 					          \ | ||||
| 	case Struct_Body: 					          \ | ||||
| 	case Typename: | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| #pragma region StaticData | ||||
|  | ||||
| // TODO : Convert global allocation strategy to use a slab allocation strategy. | ||||
| global AllocatorInfo  GlobalAllocator; | ||||
| global Array<Arena>   Global_AllocatorBuckets; | ||||
| @@ -16,9 +17,11 @@ global AllocatorInfo Allocator_Lexer       = heap(); | ||||
| global AllocatorInfo Allocator_StringArena = heap(); | ||||
| global AllocatorInfo Allocator_StringTable = heap(); | ||||
| global AllocatorInfo Allocator_TypeTable   = heap(); | ||||
|  | ||||
| #pragma endregion StaticData | ||||
|  | ||||
| #pragma region Constants | ||||
|  | ||||
| global CodeType t_empty; | ||||
| global CodeType t_auto; | ||||
| global CodeType t_void; | ||||
| @@ -83,4 +86,5 @@ global CodeSpecifiers spec_static_member; | ||||
| global CodeSpecifiers spec_thread_local; | ||||
| global CodeSpecifiers spec_virtual; | ||||
| global CodeSpecifiers spec_volatile; | ||||
|  | ||||
| #pragma endregion Constants | ||||
|   | ||||
| @@ -9,6 +9,12 @@ namespace Parser | ||||
| 	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 \ | ||||
| 	Entry( Invalid,                "INVALID" )          \ | ||||
| 	Entry( Access_Private,         "private" )          \ | ||||
| @@ -49,8 +55,12 @@ namespace Parser | ||||
| 	Entry( Module_Export,          "export" )           \ | ||||
| 	Entry( Number,                 "number" )           \ | ||||
| 	Entry( Operator,               "operator" )         \ | ||||
| 	Entry( Preprocessor_Directive, "#")                 \ | ||||
| 	Entry( Preprocessor_Include,   "include" )          \ | ||||
| 	Entry( Preprocess_Define,      "#define")           \ | ||||
| 	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_Const,             "const" )            \ | ||||
| 	Entry( Spec_Consteval,         "consteval" )        \ | ||||
|   | ||||
| @@ -84,6 +84,7 @@ Code& Code::operator ++() | ||||
| } | ||||
|  | ||||
| #pragma region AST & Code Gen Common | ||||
|  | ||||
| #define Define_CodeImpl( Typename )                                                  \ | ||||
| char const* Typename::debug_str()                                                    \ | ||||
| {                                                                                    \ | ||||
| @@ -243,6 +244,7 @@ Define_CodeCast( Using ); | ||||
| Define_CodeCast( Var ); | ||||
| Define_CodeCast( Body); | ||||
| #undef Define_CodeCast | ||||
|  | ||||
| #pragma endregion AST & Code Gen Common | ||||
|  | ||||
| void CodeClass::add_interface( CodeType type ) | ||||
| @@ -361,9 +363,11 @@ StrC token_fmt_impl( sw num, ... ) | ||||
|  | ||||
| 	return { result, buf }; | ||||
| } | ||||
|  | ||||
| #pragma endregion Inlines | ||||
|  | ||||
| #pragma region Constants | ||||
|  | ||||
| #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS | ||||
| 	// 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_virtual; | ||||
| extern CodeSpecifiers spec_volatile; | ||||
|  | ||||
| #pragma endregion Constants | ||||
|  | ||||
| #pragma region Macros | ||||
|  | ||||
| #	define gen_main main | ||||
|  | ||||
| #	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. | ||||
| #	define token_fmt( ... ) gen::token_fmt_impl( (num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ ) | ||||
|  | ||||
| #pragma endregion Macros | ||||
|  | ||||
| #ifdef GEN_EXPOSE_BACKEND | ||||
|  | ||||
| 	// Global allocator used for data with process lifetime. | ||||
| 	extern AllocatorInfo  GlobalAllocator; | ||||
| 	extern Array< Arena > Global_AllocatorBuckets; | ||||
| @@ -517,4 +525,5 @@ extern CodeSpecifiers spec_volatile; | ||||
| 	extern AllocatorInfo Allocator_StringArena; | ||||
| 	extern AllocatorInfo Allocator_StringTable; | ||||
| 	extern AllocatorInfo Allocator_TypeTable; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -4,13 +4,21 @@ These constructors are the most implementation intensive other than the editor o | ||||
|  | ||||
| namespace Parser | ||||
| { | ||||
|  | ||||
| 	struct Token | ||||
| 	{ | ||||
| 		// TokType  Type; | ||||
| 		// s32      Start; | ||||
| 		// s32      End; | ||||
| 		// s32      Line; | ||||
| 		// s32      Column; | ||||
| 		// TokFlags Flags; | ||||
|  | ||||
| 		char const* Text; | ||||
| 		sptr        Length; | ||||
| 		TokType     Type; | ||||
| 		bool 	    IsAssign; | ||||
| 		s32         Line; | ||||
| 		s32         Column; | ||||
|  | ||||
| 		operator bool() | ||||
| 		{ | ||||
| @@ -21,60 +29,42 @@ namespace Parser | ||||
| 		{ | ||||
| 			return { Length, Text }; | ||||
| 		} | ||||
|  | ||||
| 		bool is_access_specifier() | ||||
| 		{ | ||||
| 			return Type >= TokType::Access_Private && Type <= TokType::Access_Public; | ||||
| 		} | ||||
|  | ||||
| 		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 | ||||
| 			; | ||||
| 		} | ||||
|  | ||||
| 		AccessSpec to_access_specifier() | ||||
| 		{ | ||||
| 			return scast(AccessSpec, Type); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	internal inline | ||||
| 	bool tok_is_specifier( Token const& tok ) | ||||
| 	{ | ||||
| 		return (tok.Type <= TokType::Star && tok.Type >= TokType::Spec_Alignas) | ||||
| 			|| tok.Type == TokType::Ampersand | ||||
| 			|| tok.Type == TokType::Ampersand_DBL | ||||
| 		; | ||||
| 	} | ||||
|  | ||||
| 	internal inline | ||||
| 	bool tok_is_access_specifier( Token const& tok ) | ||||
| 	{ | ||||
| 		return tok.Type >= TokType::Access_Private && tok.Type <= TokType::Access_Public; | ||||
| 	} | ||||
|  | ||||
| 	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 | ||||
| 	{ | ||||
| 		Array<Token> Arr; | ||||
| 		s32          Idx; | ||||
|  | ||||
| 		bool __eat( TokType type, char const* context ) | ||||
| 		{ | ||||
| 			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; | ||||
| 		} | ||||
| 		bool __eat( TokType type ); | ||||
|  | ||||
| 		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 move_forward() \ | ||||
| 		left--;               \ | ||||
| 		scanner++ | ||||
| 	#	define move_forward()       \ | ||||
| 		{                           \ | ||||
| 			if ( current == '\n' )  \ | ||||
| 			{                       \ | ||||
| 				line++;             \ | ||||
| 				column = 0;         \ | ||||
| 			}                       \ | ||||
| 			else                    \ | ||||
| 			{                       \ | ||||
| 				column++;           \ | ||||
| 			}                       \ | ||||
| 			left--;                 \ | ||||
| 			scanner++;              \ | ||||
| 		} | ||||
|  | ||||
| 	#	define SkipWhitespace()                     \ | ||||
| 		while ( left && char_is_space( current ) )  \ | ||||
| @@ -126,6 +190,9 @@ namespace Parser | ||||
| 		char const* word        = scanner; | ||||
| 		s32         word_length = 0; | ||||
|  | ||||
| 		s32 line   = 0; | ||||
| 		s32 column = 0; | ||||
|  | ||||
| 		SkipWhitespace(); | ||||
| 		if ( left <= 0 ) | ||||
| 		{ | ||||
| @@ -142,7 +209,7 @@ namespace Parser | ||||
|  | ||||
| 		while (left ) | ||||
| 		{ | ||||
| 			Token token = { nullptr, 0, TokType::Invalid, false }; | ||||
| 			Token token = { nullptr, 0, TokType::Invalid, false, line, column }; | ||||
|  | ||||
| 			SkipWhitespace(); | ||||
| 			if ( left <= 0 ) | ||||
| @@ -153,11 +220,15 @@ namespace Parser | ||||
| 				case '#': | ||||
| 					token.Text   = scanner; | ||||
| 					token.Length = 1; | ||||
| 					token.Type   = TokType::Preprocessor_Directive; | ||||
| 					move_forward(); | ||||
|  | ||||
| 					while (left && current != '\n' ) | ||||
| 					{ | ||||
| 						if ( token.Type == ETokType::Invalid && current == ' ' ) | ||||
| 						{ | ||||
| 							token.Type = ETokType::to_type( token ); | ||||
| 						} | ||||
|  | ||||
| 						if ( current == '\\'  ) | ||||
| 						{ | ||||
| 							move_forward(); | ||||
| @@ -178,8 +249,9 @@ namespace Parser | ||||
| 					token.Length = 1; | ||||
| 					token.Type   = TokType::Access_MemberSymbol; | ||||
|  | ||||
| 					if (left) | ||||
| 					if (left) { | ||||
| 						move_forward(); | ||||
| 					} | ||||
|  | ||||
| 					if ( current == '.' ) | ||||
| 					{ | ||||
| @@ -577,7 +649,7 @@ namespace Parser | ||||
|  | ||||
| 			if ( token.Type != TokType::Invalid ) | ||||
| 			{ | ||||
| 				if ( token.Type == TokType::Preprocessor_Directive && keep_preprocess_directives == false ) | ||||
| 				if ( token.is_preprocessor() && keep_preprocess_directives == false ) | ||||
| 					continue; | ||||
|  | ||||
| 				Tokens.append( token ); | ||||
| @@ -608,6 +680,7 @@ namespace Parser | ||||
| } | ||||
|  | ||||
| #pragma region Helper Macros | ||||
|  | ||||
| #	define check_parse_args( func, def )                                   \ | ||||
| if ( def.Len <= 0 )                                                        \ | ||||
| {                                                                          \ | ||||
| @@ -620,13 +693,16 @@ if ( def.Ptr == nullptr )                                                  \ | ||||
| 	return CodeInvalid;                                                    \ | ||||
| } | ||||
|  | ||||
| #	define nexttok 	    toks.next() | ||||
| #	define currtok      toks.current() | ||||
| #	define prevtok      toks.previous() | ||||
| #	define eat( Type_ ) toks.__eat( Type_, context ) | ||||
| #	define left         ( toks.Arr.num() - toks.Idx ) | ||||
| #	define nexttok 	    Context.Tokens.next() | ||||
| #	define currtok      Context.Tokens.current() | ||||
| #	define prevtok      Context.Tokens.previous() | ||||
| #	define eat( Type_ ) Context.Tokens.__eat( Type_ ) | ||||
| #	define left         ( Context.Tokens.Arr.num() - Context.Tokens.Idx ) | ||||
|  | ||||
| #	define check( Type_ ) ( left && currtok.Type == Type_ ) | ||||
|  | ||||
| // #	define  | ||||
|  | ||||
| #pragma endregion Helper Macros | ||||
|  | ||||
| struct ParseContext | ||||
| @@ -635,28 +711,28 @@ struct ParseContext | ||||
| 	char const*   Fn; | ||||
| }; | ||||
|  | ||||
| internal Code parse_function_body( Parser::TokArray& toks, char const* context ); | ||||
| internal Code parse_global_nspace( Parser::TokArray& toks, char const* context ); | ||||
| internal Code parse_function_body(); | ||||
| internal Code parse_global_nspace(); | ||||
|  | ||||
| internal CodeClass     parse_class           ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeEnum      parse_enum            ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeBody      parse_export_body     ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeBody      parse_extern_link_body( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeExtern    parse_exten_link      ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeFriend    parse_friend          ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeFn        parse_function        ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeNamespace parse_namespace       ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeOpCast    parse_operator_cast   ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeStruct    parse_struct          ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeVar       parse_variable        ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeTemplate  parse_template        ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeType      parse_type            ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeTypedef   parse_typedef         ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeUnion     parse_union           ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeUsing     parse_using           ( Parser::TokArray& toks, char const* context ); | ||||
| internal CodeClass     parse_class           (); | ||||
| internal CodeEnum      parse_enum            (); | ||||
| internal CodeBody      parse_export_body     (); | ||||
| internal CodeBody      parse_extern_link_body(); | ||||
| internal CodeExtern    parse_exten_link      (); | ||||
| internal CodeFriend    parse_friend          (); | ||||
| internal CodeFn        parse_function        (); | ||||
| internal CodeNamespace parse_namespace       (); | ||||
| internal CodeOpCast    parse_operator_cast   (); | ||||
| internal CodeStruct    parse_struct          (); | ||||
| internal CodeVar       parse_variable        (); | ||||
| internal CodeTemplate  parse_template        (); | ||||
| internal CodeType      parse_type            (); | ||||
| internal CodeTypedef   parse_typedef         (); | ||||
| internal CodeUnion     parse_union           (); | ||||
| internal CodeUsing     parse_using           (); | ||||
|  | ||||
| internal inline | ||||
| Code parse_array_decl( Parser::TokArray& toks, char const* context ) | ||||
| Code parse_array_decl() | ||||
| { | ||||
| 	using namespace Parser; | ||||
|  | ||||
| @@ -707,7 +783,7 @@ Code parse_array_decl( Parser::TokArray& toks, char const* context ) | ||||
| } | ||||
|  | ||||
| internal inline | ||||
| CodeAttributes parse_attributes( Parser::TokArray& toks, char const* context ) | ||||
| CodeAttributes parse_attributes() | ||||
| { | ||||
| 	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; | ||||
| 	} | ||||
|  | ||||
| 	else if ( tok_is_attribute( currtok ) ) | ||||
| 	else if ( currtok.is_attribute() ) | ||||
| 	{ | ||||
| 		eat(currtok.Type); | ||||
| 		s32 len = start.Length; | ||||
| @@ -775,7 +851,7 @@ CodeAttributes parse_attributes( Parser::TokArray& toks, char const* context ) | ||||
| } | ||||
|  | ||||
| internal inline | ||||
| Parser::Token parse_identifier( Parser::TokArray& toks, char const* context ) | ||||
| Parser::Token parse_identifier() | ||||
| { | ||||
| 	using namespace Parser; | ||||
| 	Token name = currtok; | ||||
| @@ -788,7 +864,7 @@ Parser::Token parse_identifier( Parser::TokArray& toks, char const* context ) | ||||
|  | ||||
| 		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 }; | ||||
| 		} | ||||
|  | ||||
| @@ -806,7 +882,7 @@ Parser::Token parse_identifier( Parser::TokArray& toks, char const* context ) | ||||
| } | ||||
|  | ||||
| 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 ECode; | ||||
| @@ -973,15 +1049,13 @@ CodeFn parse_function_after_name( | ||||
| 	, CodeSpecifiers    specifiers | ||||
| 	, CodeType          ret_type | ||||
| 	, StrC              name | ||||
| 	, Parser::TokArray& toks | ||||
| 	, char const*        context | ||||
| ) | ||||
| { | ||||
| 	using namespace Parser; | ||||
|  | ||||
| 	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) ); | ||||
| 		eat( currtok.Type ); | ||||
| @@ -1041,12 +1115,12 @@ CodeFn parse_function_after_name( | ||||
| } | ||||
|  | ||||
| internal inline | ||||
| CodeOperator parse_operator_after_ret_type( ModuleFlag mflags | ||||
| CodeOperator parse_operator_after_ret_type(  | ||||
| 	  ModuleFlag mflags | ||||
| 	, CodeAttributes attributes | ||||
| 	, CodeSpecifiers  specifiers | ||||
| 	, CodeType       ret_type | ||||
| 	, Parser::TokArray& toks | ||||
| 	, char const* context ) | ||||
| ) | ||||
| { | ||||
| 	using namespace Parser; | ||||
| 	using namespace EOperator; | ||||
| @@ -1251,7 +1325,7 @@ CodeOperator parse_operator_after_ret_type( ModuleFlag mflags | ||||
| 	// Parse Params | ||||
| 	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) ); | ||||
| 		eat( currtok.Type ); | ||||
| @@ -1341,7 +1415,7 @@ CodeVar parse_variable_after_name( | ||||
| } | ||||
|  | ||||
| internal inline | ||||
| Code parse_variable_assignment( Parser::TokArray& toks, char const* context ) | ||||
| Code parse_variable_assignment() | ||||
| { | ||||
| 	using namespace Parser; | ||||
|  | ||||
| @@ -1372,7 +1446,7 @@ Code parse_variable_assignment( Parser::TokArray& toks, char const* context ) | ||||
| } | ||||
|  | ||||
| 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; | ||||
|  | ||||
| @@ -1416,7 +1490,7 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes | ||||
| } | ||||
|  | ||||
| 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 ECode; | ||||
| @@ -1508,7 +1582,7 @@ CodeBody parse_class_struct_body( Parser::TokType which, Parser::TokArray& toks, | ||||
| 			GEN_Define_Attribute_Tokens | ||||
| 		#undef Entry | ||||
| 			{ | ||||
| 				attributes = parse_attributes( toks, context ); | ||||
| 				attributes = parse_attributes(); | ||||
| 			} | ||||
| 			//! Fallthrough intended | ||||
| 			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 }; | ||||
| 				s32        NumSpecifiers = 0; | ||||
|  | ||||
| 				while ( left && tok_is_specifier( currtok ) ) | ||||
| 				while ( left && currtok.is_specifier() ) | ||||
| 				{ | ||||
| 					SpecifierT spec = ESpecifier::to_type( currtok ); | ||||
|  | ||||
| @@ -1597,7 +1671,7 @@ CodeBody parse_class_struct_body( Parser::TokType which, Parser::TokArray& toks, | ||||
| } | ||||
|  | ||||
| internal | ||||
| Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char const* context ) | ||||
| Code parse_class_struct( Parser::TokType which ) | ||||
| { | ||||
| 	using namespace Parser; | ||||
|  | ||||
| @@ -1625,7 +1699,7 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con | ||||
|  | ||||
| 	eat( which ); | ||||
|  | ||||
| 	attributes = parse_attributes( toks, context ); | ||||
| 	attributes = parse_attributes(); | ||||
|  | ||||
| 	if ( check( TokType::Identifier ) ) | ||||
| 		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 ); | ||||
|  | ||||
| 		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 ); | ||||
| @@ -1650,7 +1724,7 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con | ||||
| 		{ | ||||
| 			eat(TokType::Access_Public); | ||||
|  | ||||
| 			if ( tok_is_access_specifier( currtok ) ) | ||||
| 			if ( currtok.is_access_specifier() ) | ||||
| 			{ | ||||
| 				eat(currtok.Type); | ||||
| 			} | ||||
| @@ -1685,7 +1759,7 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con | ||||
| } | ||||
|  | ||||
| internal | ||||
| Code parse_function_body( Parser::TokArray& toks, char const* context ) | ||||
| Code parse_function_body() | ||||
| { | ||||
| 	using namespace Parser; | ||||
| 	using namespace ECode; | ||||
| @@ -1724,7 +1798,7 @@ Code parse_function_body( Parser::TokArray& toks, char const* context ) | ||||
| } | ||||
|  | ||||
| internal | ||||
| CodeBody parse_global_nspace( CodeT which, Parser::TokArray& toks, char const* context ) | ||||
| CodeBody parse_global_nspace( CodeT which ) | ||||
| { | ||||
| 	using namespace Parser; | ||||
| 	using namespace ECode; | ||||
| @@ -1811,7 +1885,7 @@ CodeBody parse_global_nspace( CodeT which, Parser::TokArray& toks, char const* c | ||||
| 			GEN_Define_Attribute_Tokens | ||||
| 		#undef Entry | ||||
| 			{ | ||||
| 				attributes = parse_attributes( toks, context ); | ||||
| 				attributes = parse_attributes(); | ||||
| 			} | ||||
| 			//! Fallthrough intentional | ||||
| 			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 }; | ||||
| 				s32        NumSpecifiers = 0; | ||||
|  | ||||
| 				while ( left && tok_is_specifier( currtok ) ) | ||||
| 				while ( left && currtok.is_specifier() ) | ||||
| 				{ | ||||
| 					SpecifierT spec = ESpecifier::to_type( currtok ); | ||||
|  | ||||
| @@ -1890,7 +1964,7 @@ CodeBody parse_global_nspace( CodeT which, Parser::TokArray& toks, char const* c | ||||
| } | ||||
|  | ||||
| internal | ||||
| CodeClass parse_class( Parser::TokArray& toks, char const* context ) | ||||
| CodeClass parse_class() | ||||
| { | ||||
| 	return (CodeClass) parse_class_struct( Parser::TokType::Decl_Class, toks, context ); | ||||
| } | ||||
| @@ -1908,7 +1982,7 @@ CodeClass parse_class( StrC def ) | ||||
| } | ||||
|  | ||||
| internal | ||||
| CodeEnum parse_enum( Parser::TokArray& toks, char const* context ) | ||||
| CodeEnum parse_enum() | ||||
| { | ||||
| 	using namespace Parser; | ||||
| 	using namespace ECode; | ||||
| @@ -2027,7 +2101,7 @@ CodeEnum parse_enum( StrC def ) | ||||
| } | ||||
|  | ||||
| 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 ); | ||||
| } | ||||
| @@ -2170,9 +2244,9 @@ CodeFn parse_functon( Parser::TokArray& toks, char const* context ) | ||||
| 		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 ); | ||||
|  | ||||
| @@ -2294,9 +2368,9 @@ CodeOperator parse_operator( Parser::TokArray& toks, char const* context ) | ||||
| 		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 ); | ||||
|  | ||||
| @@ -2492,9 +2566,9 @@ CodeTemplate parse_template( Parser::TokArray& toks, char const* context ) | ||||
| 		SpecifierT specs_found[16] { ESpecifier::NumSpecifiers }; | ||||
| 		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 ); | ||||
|  | ||||
| @@ -2576,9 +2650,9 @@ CodeType parse_type( Parser::TokArray& toks, char const* context ) | ||||
| 	Token name      = { nullptr, 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 ); | ||||
|  | ||||
| @@ -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 ); | ||||
|  | ||||
| @@ -2842,7 +2916,7 @@ CodeUnion parse_union( Parser::TokArray& toks, char const* context ) | ||||
|  | ||||
| 	eat( TokType::Decl_Union ); | ||||
|  | ||||
| 	CodeAttributes attributes = parse_attributes( toks, context ); | ||||
| 	CodeAttributes attributes = parse_attributes(); | ||||
|  | ||||
| 	StrC name = { 0, nullptr }; | ||||
|  | ||||
| @@ -2986,12 +3060,10 @@ CodeUsing parse_using( StrC def ) | ||||
| } | ||||
|  | ||||
| internal | ||||
| CodeVar parse_variable( Parser::TokArray& toks, char const* context ) | ||||
| CodeVar parse_variable() | ||||
| { | ||||
| 	using namespace Parser; | ||||
|  | ||||
| 	Token name = { nullptr, 0, TokType::Invalid }; | ||||
|  | ||||
| 	SpecifierT specs_found[16] { ESpecifier::NumSpecifiers }; | ||||
| 	s32        NumSpecifiers = 0; | ||||
|  | ||||
| @@ -3005,7 +3077,7 @@ CodeVar parse_variable( Parser::TokArray& toks, char const* context ) | ||||
| 		eat( TokType::Module_Export ); | ||||
| 	} | ||||
|  | ||||
| 	attributes = parse_attributes( toks, context ); | ||||
| 	attributes = parse_attributes(); | ||||
|  | ||||
| 	while ( left && tok_is_specifier( currtok ) ) | ||||
| 	{ | ||||
| @@ -3050,24 +3122,32 @@ CodeVar parse_variable( Parser::TokArray& toks, char const* context ) | ||||
| 	if ( type == Code::Invalid ) | ||||
| 		return CodeInvalid; | ||||
|  | ||||
| 	name = currtok; | ||||
| 	Context.Scope->Name = current; | ||||
| 	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; | ||||
| } | ||||
|  | ||||
| CodeVar parse_variable( StrC def ) | ||||
| { | ||||
| 	check_parse_args( parse_variable, def ); | ||||
| 	using namespace Parser; | ||||
| 	check_parse_args( parse_variable, def ); | ||||
|  | ||||
| 	TokArray toks = lex( def ); | ||||
| 	if ( toks.Arr == nullptr ) | ||||
| 		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 | ||||
| @@ -3075,4 +3155,3 @@ CodeVar parse_variable( StrC def ) | ||||
| #	undef curr_tok | ||||
| #	undef eat | ||||
| #	undef left | ||||
|  | ||||
|   | ||||
| @@ -1338,7 +1338,7 @@ CodeBody def_class_body( s32 num, ... ) | ||||
| 	va_list va; | ||||
| 	va_start(va, num); | ||||
| 	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 ); | ||||
| 	va_end(va); | ||||
|  | ||||
| @@ -1354,7 +1354,7 @@ CodeBody def_class_body( s32 num, Code* codes ) | ||||
| 	result->Type = Function_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 ); | ||||
|  | ||||
| 	return result; | ||||
| @@ -1437,7 +1437,7 @@ CodeBody def_export_body( s32 num, ... ) | ||||
| 	va_list va; | ||||
| 	va_start(va, num); | ||||
| 	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 ); | ||||
| 	va_end(va); | ||||
|  | ||||
| @@ -1453,7 +1453,7 @@ CodeBody def_export_body( s32 num, Code* codes ) | ||||
| 	result->Type = 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 ); | ||||
|  | ||||
| 	return result; | ||||
| @@ -1470,7 +1470,7 @@ CodeBody def_extern_link_body( s32 num, ... ) | ||||
| 	va_list va; | ||||
| 	va_start(va, num); | ||||
| 	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 ); | ||||
| 	va_end(va); | ||||
|  | ||||
| @@ -1486,7 +1486,7 @@ CodeBody def_extern_link_body( s32 num, Code* codes ) | ||||
| 	result->Type = 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 ); | ||||
|  | ||||
| 	return result; | ||||
| @@ -1503,7 +1503,7 @@ CodeBody def_function_body( s32 num, ... ) | ||||
| 	va_list va; | ||||
| 	va_start(va, num); | ||||
| 	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 ); | ||||
| 	va_end(va); | ||||
|  | ||||
| @@ -1519,7 +1519,7 @@ CodeBody def_function_body( s32 num, Code* codes ) | ||||
| 	result->Type = 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 ); | ||||
|  | ||||
| 	return result; | ||||
| @@ -1536,7 +1536,7 @@ CodeBody def_global_body( s32 num, ... ) | ||||
| 	va_list va; | ||||
| 	va_start(va, num); | ||||
| 	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 ); | ||||
| 	va_end(va); | ||||
|  | ||||
| @@ -1552,7 +1552,7 @@ CodeBody def_global_body( s32 num, Code* codes ) | ||||
| 	result->Type = 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 ); | ||||
|  | ||||
| 	return result; | ||||
| @@ -1569,7 +1569,7 @@ CodeBody def_namespace_body( s32 num, ... ) | ||||
| 	va_list va; | ||||
| 	va_start(va, num); | ||||
| 	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 ); | ||||
| 	va_end(va); | ||||
|  | ||||
| @@ -1585,7 +1585,7 @@ CodeBody def_namespace_body( s32 num, Code* codes ) | ||||
| 	result->Type = Global_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 ); | ||||
|  | ||||
| 	return result; | ||||
| @@ -1737,7 +1737,7 @@ CodeBody def_struct_body( s32 num, ... ) | ||||
| 	va_list va; | ||||
| 	va_start(va, num); | ||||
| 	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 ); | ||||
| 	va_end(va); | ||||
|  | ||||
| @@ -1753,7 +1753,7 @@ CodeBody def_struct_body( s32 num, Code* codes ) | ||||
| 	result->Type = 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 ); | ||||
|  | ||||
| 	return result; | ||||
|   | ||||
| @@ -100,10 +100,3 @@ constexpr char const* Attribute_Keyword = stringize( GEN_Attribute_Keyword ); | ||||
|  | ||||
| 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 | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,7 @@ using namespace gen; | ||||
|  | ||||
| CodeBody gen_ecode( char const* path ) | ||||
| { | ||||
| 	char scratch_mem[kilobytes(1)]; | ||||
| 	char  scratch_mem[kilobytes(1)]; | ||||
| 	Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); | ||||
|  | ||||
| 	file_read_contents( scratch, zero_terminate, path ); | ||||
| @@ -50,8 +50,7 @@ CodeBody gen_ecode( char const* path ) | ||||
| #pragma pop_macro( "local_persist" ) | ||||
|  | ||||
| 	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 ) ); | ||||
| } | ||||
| @@ -209,7 +208,7 @@ CodeBody gen_especifier( char const* path ) | ||||
|  | ||||
| CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | ||||
| { | ||||
| 	char scratch_mem[kilobytes(64)]; | ||||
| 	char  scratch_mem[kilobytes(64)]; | ||||
| 	Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); | ||||
|  | ||||
| 	FileContents enum_content = file_read_contents( scratch, zero_terminate, etok_path ); | ||||
| @@ -217,8 +216,6 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | ||||
| 	CSV_Object csv_enum_nodes; | ||||
| 	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 ); | ||||
|  | ||||
| 	CSV_Object csv_attr_nodes; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user