Started to implement context stack for parser.

This commit is contained in:
Edward R. Gonzalez 2023-07-28 21:44:31 -04:00
parent 3f0b7e7fc6
commit 31e1c38c18
11 changed files with 350 additions and 260 deletions

View File

@ -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`

View File

@ -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"

1 Invalid __invalid__
37 Module_Export export
38 Number number
39 Operator operator
40 Preprocessor_Directive Preprocess_Define # #define
41 Preprocessor_Include Preprocess_Include include #include
42 Preprocess_If #if
43 Preprocess_ElIF #elif
44 Preprocess_Else #else
45 Preprocess_EndIf #endif
46 Spec_Alignas alignas
47 Spec_Const const
48 Spec_Consteval consteval

View File

@ -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>() )

View File

@ -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:

View File

@ -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

View File

@ -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" ) \

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;