mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-31 06:50:53 -07:00 
			
		
		
		
	c_library compiles and generates
This commit is contained in:
		| @@ -336,6 +336,7 @@ CodeBody parse_file( Str path ); | ||||
|  | ||||
| GEN_API CodeClass       parse_class        ( Str class_def       ); | ||||
| GEN_API CodeConstructor parse_constructor  ( Str constructor_def ); | ||||
| GEN_API CodeDefine      parse_define       ( Str define_def      ); | ||||
| GEN_API CodeDestructor  parse_destructor   ( Str destructor_def  ); | ||||
| GEN_API CodeEnum        parse_enum         ( Str enum_def        ); | ||||
| GEN_API CodeBody        parse_export_body  ( Str export_def      ); | ||||
|   | ||||
| @@ -82,6 +82,21 @@ CodeConstructor parse_constructor( Str def ) | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| CodeDefine parse_define( Str def ) | ||||
| { | ||||
| 	check_parse_args( def ); | ||||
|  | ||||
| 	TokArray toks = lex( def ); | ||||
| 	if ( toks.Arr == nullptr ) | ||||
| 		return InvalidCode; | ||||
|  | ||||
| 	_ctx->parser.Tokens = toks; | ||||
| 	push_scope(); | ||||
| 	CodeDefine result = parser_parse_define(); | ||||
| 	parser_pop(& _ctx->parser); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| CodeDestructor parse_destructor( Str def ) | ||||
| { | ||||
| 	check_parse_args( def ); | ||||
|   | ||||
| @@ -123,19 +123,19 @@ s32 lex_preprocessor_define( LexContext* ctx ) | ||||
| 		name.Text.Len++; | ||||
| 	} | ||||
|  | ||||
| 	Specifier spec   = str_to_specifier( name.Text ); | ||||
| 	TokType   attrib = str_to_toktype( name.Text ); | ||||
| 	Specifier spec    = str_to_specifier( name.Text ); | ||||
| 	TokType   attrib  = str_to_toktype( name.Text ); | ||||
| 	b32 not_specifier = spec   == Spec_Invalid; | ||||
| 	b32 not_attribute = attrib <= Tok___Attributes_Start; | ||||
|  | ||||
| 	PreprocessorMacro  macro            = { name.Text, MT_Statement, (MacroFlags)0 }; | ||||
| 	PreprocessorMacro  macro            = { name.Text, MT_Expression, (MacroFlags)0 }; | ||||
| 	PreprocessorMacro* registered_macro = lookup_preprocess_macro(name.Text); | ||||
|  | ||||
| 	if ( registered_macro == nullptr && not_specifier && not_attribute ) { | ||||
| 		log_fmt("Warning: '%S' was not registered before the lexer processed its #define directive, it will be registered as a statement macro\n" | ||||
| 		log_fmt("Warning: '%S' was not registered before the lexer processed its #define directive, it will be registered as a expression macro\n" | ||||
| 			, name.Text  | ||||
| 		); | ||||
| 		GEN_DEBUG_TRAP(); | ||||
| 		// GEN_DEBUG_TRAP(); | ||||
| 	} | ||||
| 	array_append( _ctx->Lexer_Tokens, name ); | ||||
|  | ||||
| @@ -145,7 +145,7 @@ s32 lex_preprocessor_define( LexContext* ctx ) | ||||
| 			log_fmt("Warning: %S registered macro is not flagged as functional yet the definition detects opening parenthesis '(' for arguments\n" | ||||
| 				, name.Text | ||||
| 			); | ||||
| 			GEN_DEBUG_TRAP(); | ||||
| 			// GEN_DEBUG_TRAP(); | ||||
| 		} | ||||
| 		else { | ||||
| 			macro.Flags |= MF_Functional; | ||||
| @@ -526,35 +526,41 @@ void lex_found_token( LexContext* ctx ) | ||||
| 	} | ||||
|  | ||||
| 	PreprocessorMacro* macro = lookup_preprocess_macro( ctx->token.Text ); | ||||
| 	if ( macro ) | ||||
| 	b32 has_args          = ctx->left && (* ctx->scanner) == '('; | ||||
| 	b32 resolved_to_macro = false; | ||||
| 	if (macro) { | ||||
| 		ctx->token.Type   = macrotype_to_toktype(macro->Type); | ||||
| 		b32 is_functional = macro_is_functional(* macro); | ||||
| 		resolved_to_macro = has_args ? is_functional : ! is_functional; | ||||
| 	} | ||||
| 	if ( resolved_to_macro ) | ||||
| 	{ | ||||
| 		ctx->token.Type = macrotype_to_toktype(macro->Type); | ||||
|  | ||||
| 		// TODO(Ed): When we introduce a macro AST (and expression support), we'll properly lex this section. | ||||
| 		// Want to ignore any arguments the define may have as they can be execution expressions. | ||||
| 		if ( ctx->left && (* ctx->scanner) == '(' ) | ||||
| 		if ( has_args ) | ||||
| 		{ | ||||
| 			ctx->token.Flags |= TF_Macro_Functional; | ||||
|  | ||||
| 			move_forward(); | ||||
| 			ctx->token.Text.Len++; | ||||
| 			// move_forward(); | ||||
| 			// ctx->token.Text.Len++; | ||||
|  | ||||
| 			s32 level = 0; | ||||
| 			while ( ctx->left && ((* ctx->scanner) != ')' || level > 0) ) | ||||
| 			{ | ||||
| 				if ( (* ctx->scanner) == '(' ) | ||||
| 					level++; | ||||
| 			// s32 level = 0; | ||||
| 			// while ( ctx->left && ((* ctx->scanner) != ')' || level > 0) ) | ||||
| 			// { | ||||
| 			// 	if ( (* ctx->scanner) == '(' ) | ||||
| 			// 		level++; | ||||
|  | ||||
| 				else if ( (* ctx->scanner) == ')' && level > 0 ) | ||||
| 					level--; | ||||
| 			// 	else if ( (* ctx->scanner) == ')' && level > 0 ) | ||||
| 			// 		level--; | ||||
|  | ||||
| 				move_forward(); | ||||
| 				ctx->token.Text.Len++; | ||||
| 			} | ||||
| 			// 	move_forward(); | ||||
| 			// 	ctx->token.Text.Len++; | ||||
| 			// } | ||||
|  | ||||
| 			move_forward(); | ||||
| 			ctx->token.Text.Len++; | ||||
| 			// move_forward(); | ||||
| 			// ctx->token.Text.Len++; | ||||
| 		} | ||||
|  | ||||
| 		//if ( (* ctx->scanner) == '\r' && ctx->scanner[1] == '\n' ) | ||||
| 		//{ | ||||
| 		//	move_forward(); | ||||
| @@ -1277,7 +1283,7 @@ TokArray lex( Str content ) | ||||
| 		{ | ||||
| 			lex_found_token( ctx ); | ||||
| 			TokType last_type = array_back(_ctx->Lexer_Tokens)->Type; | ||||
| 			if ( last_type == Tok_Preprocess_Macro_Stmt ) | ||||
| 			if ( last_type == Tok_Preprocess_Macro_Stmt || last_type == Tok_Preprocess_Macro_Expr ) | ||||
| 			{ | ||||
| 				Token thanks_c = { { c.scanner, 0 }, Tok_Invalid, c.line, c.column, TF_Null }; | ||||
| 				c.token = thanks_c; | ||||
|   | ||||
| @@ -93,7 +93,15 @@ bool lex__eat(TokArray* self, TokType type ) | ||||
| 		self->Idx ++; | ||||
| 	} | ||||
|  | ||||
| 	if ( at_idx.Type != type ) | ||||
| 	b32 not_accepted  = at_idx.Type != type; | ||||
| 	b32 is_identifier = at_idx.Type == Tok_Identifier; | ||||
| 	if ( not_accepted ) | ||||
| 	{ | ||||
| 		PreprocessorMacro* macro = lookup_preprocess_macro(at_idx.Text); | ||||
| 		b32 accept_as_identifier = macro && bitfield_is_set(MacroFlags, macro->Flags, MF_Allow_As_Identifier ); | ||||
| 		not_accepted             = type == Tok_Identifier && accept_as_identifier ? false : true; | ||||
| 	} | ||||
| 	if ( not_accepted ) | ||||
| 	{ | ||||
| 		Token tok = * lex_current( self, lex_skip_formatting ); | ||||
| 		log_failure( "Parse Error, TokArray::eat, Expected: ' %s ' not ' %.*s ' (%d, %d)`\n%s" | ||||
| @@ -188,7 +196,7 @@ internal CodeComment        parse_comment                      (); | ||||
| internal Code               parse_complicated_definition       ( TokType which ); | ||||
| internal CodeBody           parse_class_struct_body            ( TokType which, Token name ); | ||||
| internal Code               parse_class_struct                 ( TokType which, bool inplace_def ); | ||||
| internal CodeDefine         parse_define                       (); | ||||
| internal CodeDefine         parser_parse_define                (); | ||||
| internal Code               parse_expression                   (); | ||||
| internal Code               parse_forward_or_definition        ( TokType which, bool is_inplace ); | ||||
| internal CodeFn             parse_function_after_name          ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeTypename ret_type, Token name ); | ||||
| @@ -902,7 +910,7 @@ CodeBody parse_class_struct_body( TokType which, Token name ) | ||||
| 				break; | ||||
| 			} | ||||
| 			case Tok_Preprocess_Define: { | ||||
| 				member = cast(Code, parse_define()); | ||||
| 				member = cast(Code, parser_parse_define()); | ||||
| 				// #define | ||||
| 				break; | ||||
| 			} | ||||
| @@ -1286,9 +1294,14 @@ Code parse_complicated_definition( TokType which ) | ||||
| } | ||||
|  | ||||
| internal inline | ||||
| CodeDefine parse_define() | ||||
| CodeDefine parser_parse_define() | ||||
| { | ||||
| 	push_scope(); | ||||
| 	if ( check(Tok_Preprocess_Hash)) { | ||||
| 		// If parse_define is called by the user the hash reach here. | ||||
| 		eat(Tok_Preprocess_Hash); | ||||
| 	} | ||||
|  | ||||
| 	eat( Tok_Preprocess_Define ); | ||||
| 	// #define | ||||
|  | ||||
| @@ -1698,7 +1711,7 @@ CodeBody parse_global_nspace( CodeType which ) | ||||
| 			break; | ||||
|  | ||||
| 			case Tok_Preprocess_Define: | ||||
| 				member = cast(Code, parse_define()); | ||||
| 				member = cast(Code, parser_parse_define()); | ||||
| 				// #define ... | ||||
| 			break; | ||||
|  | ||||
| @@ -2933,6 +2946,32 @@ Code parse_simple_preprocess( TokType which ) | ||||
| 	// <Macro> | ||||
|  | ||||
| 	PreprocessorMacro* macro = lookup_preprocess_macro( full_macro.Text ); | ||||
| 	if ( which != Tok_Preprocess_Unsupported && macro == nullptr ) { | ||||
| 		log_failure("Expected the macro %S to be registered\n%S", full_macro,  parser_to_strbuilder(_ctx->parser)); | ||||
| 		return NullCode; | ||||
| 	} | ||||
|  | ||||
| 	// TODO(Ed) : Parse this properly later (expression and statement support) | ||||
| 	if ( macro && macro_is_functional(* macro) ) | ||||
| 	{ | ||||
| 		eat( Tok_Capture_Start ); | ||||
|  | ||||
| 		s32 level = 0; | ||||
| 		while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) ) | ||||
| 		{ | ||||
| 			if ( currtok.Type == Tok_Capture_Start ) | ||||
| 				level++; | ||||
|  | ||||
| 			else if ( currtok.Type == Tok_Capture_End && level > 0 ) | ||||
| 				level--; | ||||
|  | ||||
| 			eat( currtok.Type ); | ||||
| 		} | ||||
| 		eat( Tok_Capture_End ); | ||||
| 		// <Macro> ( <params> ) | ||||
|  | ||||
| 		full_macro.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)full_macro.Text.Ptr; | ||||
| 	} | ||||
|  | ||||
| 	if ( macro && macro_expects_body(* macro) && peektok.Type == Tok_BraceCurly_Open ) | ||||
| 	{ | ||||
| @@ -3619,7 +3658,7 @@ CodeEnum parser_parse_enum( bool inplace_def ) | ||||
| 		if ( str_contains( tok_to_str(currtok), enum_underlying_macro.Name) ) | ||||
| 		{ | ||||
| 			use_macro_underlying = true; | ||||
| 			underlying_macro     = parse_simple_preprocess( Tok_Preprocess_Macro_Typename ); | ||||
| 			underlying_macro     = parse_simple_preprocess( Tok_Preprocess_Macro_Expr ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -3660,7 +3699,7 @@ CodeEnum parser_parse_enum( bool inplace_def ) | ||||
| 				break; | ||||
|  | ||||
| 				case Tok_Preprocess_Define: | ||||
| 					member = cast(Code, parse_define()); | ||||
| 					member = cast(Code, parser_parse_define()); | ||||
| 					// #define | ||||
| 				break; | ||||
|  | ||||
| @@ -4916,22 +4955,32 @@ CodeTypedef parser_parse_typedef() | ||||
| #if GEN_PARSER_DISABLE_MACRO_TYPEDEF | ||||
| 	if ( false ) | ||||
| #else | ||||
| 	if ( check( Tok_Preprocess_Macro_Typename )) | ||||
| 	b32 valid_macro = false; | ||||
| 	valid_macro |= left && currtok.Type == Tok_Preprocess_Macro_Typename; | ||||
| 	valid_macro |= left && currtok.Type == Tok_Preprocess_Macro_Stmt; | ||||
| 	// if (currtok.Type == Tok_Preprocess_Macro_Stmt) | ||||
| 	// { | ||||
| 		// PreprocessMacro* macro = lookup_preprocess_macro(currtok.Text); | ||||
| 		// valid_macro |= macro && macro_expects_body(* macro)); | ||||
| 	// } | ||||
|  | ||||
| 	if ( valid_macro ) | ||||
| #endif | ||||
| 	{ | ||||
| 		type = cast(Code, t_empty); | ||||
| 		name = currtok; | ||||
| 		type          = cast(Code, t_empty); | ||||
| 		Code macro    = parse_simple_preprocess(currtok.Type); | ||||
| 		name          = currtok; | ||||
| 		name.Text.Len = macro->Content.Len; | ||||
| 		_ctx->parser.Scope->Name = name.Text; | ||||
| 		eat( Tok_Preprocess_Macro_Typename ); | ||||
| 		// <ModuleFalgs> typedef <Preprocessed_Macro> | ||||
|  | ||||
| 		if ( currtok.Type == Tok_Identifier ) | ||||
| 		{ | ||||
| 			type = untyped_str(name.Text); | ||||
| 			type = macro; | ||||
| 			name = currtok; | ||||
| 			eat(Tok_Identifier); | ||||
| 			// <ModuleFalgs> typedef <Preprocessed_Macro> <Identifier> | ||||
| 		} | ||||
| 		// <ModuleFalgs> typedef <Preprocessed_Macro> <Identifier> | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| @@ -5178,7 +5227,7 @@ CodeUnion parser_parse_union( bool inplace_def ) | ||||
| 				break; | ||||
|  | ||||
| 				case Tok_Preprocess_Define: | ||||
| 					member = cast(Code, parse_define()); | ||||
| 					member = cast(Code, parser_parse_define()); | ||||
| 				break; | ||||
|  | ||||
| 				case Tok_Preprocess_If: | ||||
|   | ||||
| @@ -129,8 +129,8 @@ struct ParseContext | ||||
|  | ||||
| enum MacroType : u16 | ||||
| { | ||||
| 	MT_Statement,      // A macro is assumed to be a statement if not resolved. | ||||
| 	MT_Expression, | ||||
| 	MT_Expression,     // A macro is assumed to be a expression if not resolved. | ||||
| 	MT_Statement,       | ||||
| 	MT_Typename, | ||||
| 	MT_Attribute,      // More of a note to the parser than anythign else (attributes should be defined in the user attribues def). | ||||
| 	MT_Specifier,      // More of a note to the parser than anythign else (specifiers should be defined in the user attribues def). | ||||
| @@ -175,8 +175,10 @@ Str macrotype_to_str( MacroType type ) | ||||
|  | ||||
| enum EMacroFlags : u16 | ||||
| { | ||||
| 	MF_Functional     = bit(0), // Macro has parameters (args expected to be passed) | ||||
| 	MF_Expects_Body   = bit(1), // Expects to assign a braced scope to its body. | ||||
| 	MF_Functional          = bit(0), // Macro has parameters (args expected to be passed) | ||||
| 	MF_Expects_Body        = bit(1), // Expects to assign a braced scope to its body. | ||||
| 	MF_Allow_As_Identifier = bit(2), // lex__eat wil treat this macro as an identifier if the parser attempts to consume it as one. | ||||
|                                      //  ^^^ This is a sort of kludge because we don't support push/pop macro programs rn. ^^^ | ||||
|  | ||||
| 	MF_Null           = 0, | ||||
| 	MF_UnderlyingType = GEN_U16_MAX, | ||||
|   | ||||
| @@ -225,7 +225,7 @@ forceinline ssize         size_remaining(Arena& arena, ssize alignment) { return | ||||
| // This id is defined by Unreal for asserts | ||||
| #pragma push_macro("check") | ||||
| #undef check | ||||
| forceinline void check(Arena& arena) { return arena_check(& arena); }; | ||||
| forceinline void check(Arena& arena) { return arena_check(& arena); } | ||||
| #pragma pop_macro("check") | ||||
| #endif | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user