mirror of
https://github.com/Ed94/gencpp.git
synced 2025-06-14 18:51:47 -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