WIP (Not compiling prob): Started to overhaul macro handling

This commit is contained in:
Edward R. Gonzalez 2024-12-14 14:02:16 -05:00
parent 3c249d2fae
commit 76257123da
14 changed files with 282 additions and 176 deletions

View File

@ -26,6 +26,7 @@ struct AST_Constructor;
// struct AST_BaseClass;
struct AST_Class;
struct AST_Define;
struct AST_DefineParams;
struct AST_Destructor;
struct AST_Enum;
struct AST_Exec;
@ -98,6 +99,7 @@ typedef AST_Comment* CodeComment;
typedef AST_Class* CodeClass;
typedef AST_Constructor* CodeConstructor;
typedef AST_Define* CodeDefine;
typedef AST_DefineParams* CodeDefineParams;
typedef AST_Destructor* CodeDestructor;
typedef AST_Enum* CodeEnum;
typedef AST_Exec* CodeExec;
@ -120,6 +122,7 @@ struct CodeComment;
struct CodeClass;
struct CodeConstructor;
struct CodeDefine;
struct CodeDefineParams;
struct CodeDestructor;
struct CodeEnum;
struct CodeExec;
@ -305,6 +308,7 @@ struct Code
operator CodeClass() const;
operator CodeConstructor() const;
operator CodeDefine() const;
operator CodeDefineParams() const;
operator CodeDestructor() const;
operator CodeExec() const;
operator CodeEnum() const;
@ -365,6 +369,7 @@ int AST_ArrSpecs_Cap =
/*
Simple AST POD with functionality to seralize into C++ syntax.
TODO(Ed): Eventually haven't a transparent AST like this will longer be viable once statements & expressions are in (most likely....)
*/
struct AST
{
@ -372,7 +377,7 @@ struct AST
struct
{
Code InlineCmt; // Class, Constructor, Destructor, Enum, Friend, Functon, Operator, OpCast, Struct, Typedef, Using, Variable
Code Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable
Code Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable // TODO(Ed): Parameters can have attributes
Code Specs; // Destructor, Function, Operator, Typename, Variable
union {
Code InitializerList; // Constructor
@ -384,12 +389,12 @@ struct AST
union {
Code Macro; // Parameter
Code BitfieldSize; // Variable (Class/Struct Data Member)
Code Params; // Constructor, Function, Operator, Template, Typename
Code Params; // Constructor, Define, Function, Operator, Template, Typename
Code UnderlyingTypeMacro; // Enum
};
union {
Code ArrExpr; // Typename
Code Body; // Class, Constructor, Destructor, Enum, Friend, Function, Namespace, Struct, Union
Code Body; // Class, Constructor, Define, Destructor, Enum, Friend, Function, Namespace, Struct, Union
Code Declaration; // Friend, Template
Code Value; // Parameter, Variable
};

View File

@ -146,7 +146,13 @@ struct AST_Define
{
union {
char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ];
StrCached Content;
struct
{
char _PAD_PROPERTIES_ [ sizeof(AST*) * 4 ];
CodeDefineParams Params;
Code Body; // Should be completely serialized for now to a: StrCached Content.
char _PAD_PROPERTIES_ [ sizeof(AST*) * 1 ];
};
};
StrCached Name;
Code Prev;
@ -158,6 +164,22 @@ struct AST_Define
};
static_assert( sizeof(AST_Define) == sizeof(AST), "ERROR: AST_Define is not the same size as AST");
struct AST_DefineParams
{
union {
char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ];
};
StrCached Name;
CodeDefineParams Last;
CodeDefineParams Next;
Token* Tok;
Code Parent;
CodeType Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) ];
s32 NumEntries;
};
static_assert( sizeof(AST_DefineParams) == sizeof(AST), "ERROR: AST_DefineParams is not the same size as AST");
struct AST_Destructor
{
union {
@ -660,6 +682,7 @@ struct AST_Params
char _PAD_[ sizeof(Specifier) * AST_ArrSpecs_Cap + sizeof(AST*) ];
struct
{
// TODO(Ed): Support attributes for parameters (Some prefix macros can be converted to that...)
char _PAD_PROPERTIES_2_[ sizeof(AST*) * 3 ];
CodeTypename ValueType;
Code Macro;

View File

@ -32,7 +32,17 @@ GEN_API StrBuilder class_to_strbuilder ( CodeClass self );
GEN_API void class_to_strbuilder_def( CodeClass self, StrBuilder* result );
GEN_API void class_to_strbuilder_fwd( CodeClass self, StrBuilder* result );
GEN_API void params_append (CodeParams params, CodeParams param );
GEN_API void define_params_append (CodeDefineParams appendee, CodeDefineParams other );
GEN_API CodeDefineParams define_params_get (CodeDefineParams params, s32 idx);
GEN_API bool define_params_has_entries (CodeDefineParams params );
GEN_API StrBuilder define_params_to_strbuilder (CodeDefineParams params );
GEN_API void define_params_to_strbuilder_ref(CodeDefineParams params, StrBuilder* result );
GEN_API CodeDefineParams begin_CodeDefineParams(CodeDefineParams params);
GEN_API CodeDefineParams end_CodeDefineParams (CodeDefineParams params);
GEN_API CodeDefineParams next_CodeDefineParams (CodeDefineParams params, CodeDefineParams entry_iter);
GEN_API void params_append (CodeParams appendee, CodeParams other );
GEN_API CodeParams params_get (CodeParams params, s32 idx);
GEN_API bool params_has_entries (CodeParams params );
GEN_API StrBuilder params_to_strbuilder (CodeParams params );
@ -192,12 +202,11 @@ struct CodeParams
{
#if ! GEN_C_LIKE_CPP
Using_Code( CodeParams );
forceinline void append( CodeParams other );
forceinline CodeParams get( s32 idx );
forceinline bool has_entries();
forceinline StrBuilder to_strbuilder();
forceinline void to_strbuilder( StrBuilder& result );
forceinline void append( CodeParams other ) { return params_append(* this, other) }
forceinline CodeParams get( s32 idx ) { return params_get( * this, idx); }
forceinline bool has_entries() { return params_has_entries(* this); }
forceinline StrBuilder to_strbuilder() { return params_to_strbuilder(* this); }
forceinline void to_strbuilder( StrBuilder& result ) { return params_to_strbuilder_ref(*this, & result); }
#endif
Using_CodeOps( CodeParams );
forceinline CodeParams begin() { return begin_CodeParams(* this); }
@ -212,6 +221,29 @@ struct CodeParams
AST_Params* ast;
};
struct CodeDefineParams
{
#if ! GEN_C_LIKE_CPP
Using_Code( CodeDefineParams );
forceinline void append( CodeDefineParams other ) { return params_append( cast(CodeParams, * this), other) }
forceinline CodeDefineParams get( s32 idx ) { return params_get( cast(CodeParams, * this), idx); }
forceinline bool has_entries() { return params_has_entries( cast(CodeParams, * this)); }
forceinline StrBuilder to_strbuilder() { return define_params_to_strbuilder(* this); }
forceinline void to_strbuilder( StrBuilder& result ) { return define_params_to_strbuilder_ref(* this, & result); }
#endif
Using_CodeOps( CodeDefineParams );
forceinline CodeDefineParams begin() { return begin_CodeParams( cast(CodeParams, * this)); }
forceinline CodeDefineParams end() { return end_CodeParams( cast(CodeParams, * this)); }
forceinline operator Code() { return { (AST*)ast }; }
forceinline CodeDefineParams operator *() { return * this; } // Required to support for-range iteration.
forceinline AST_DefineParams* operator->() {
GEN_ASSERT(ast);
return ast;
}
forceinline CodeDefineParams& operator++() { return cast(CodeParams, * this).operator ++() };
AST_DefineParams* ast;
};
struct CodeSpecifiers
{
#if ! GEN_C_LIKE_CPP
@ -941,6 +973,7 @@ struct InvalidCode_ImplictCaster
operator CodeClass () const { return cast(CodeClass, Code_Invalid); }
operator CodeConstructor () const { return cast(CodeConstructor, Code_Invalid); }
operator CodeDefine () const { return cast(CodeDefine, Code_Invalid); }
operator CodeDefineParams () const { return cast(CodeDefineParams, Code_Invalid); }
operator CodeDestructor () const { return cast(CodeDestructor, Code_Invalid); }
operator CodeExec () const { return cast(CodeExec, Code_Invalid); }
operator CodeEnum () const { return cast(CodeEnum, Code_Invalid); }
@ -974,6 +1007,7 @@ struct NullCode_ImplicitCaster
operator CodeClass () const { return {nullptr}; }
operator CodeConstructor () const { return {nullptr}; }
operator CodeDefine () const { return {nullptr}; }
operator CodeDefineParams () const { return {nullptr}; }
operator CodeDestructor () const { return {nullptr}; }
operator CodeExec () const { return {nullptr}; }
operator CodeEnum () const { return {nullptr}; }
@ -1024,7 +1058,13 @@ forceinline StrBuilder to_strbuilder ( CodeClass self )
forceinline void to_strbuilder_def( CodeClass self, StrBuilder& result ) { return class_to_strbuilder_def(self, & result); }
forceinline void to_strbuilder_fwd( CodeClass self, StrBuilder& result ) { return class_to_strbuilder_fwd(self, & result); }
forceinline void append (CodeParams params, CodeParams param ) { return params_append(params, param); }
forceinline void append (CodeDefineParams appendee, CodeDefineParams other ) { return params_append(cast(CodeParam, appendee), other); }
forceinline CodeDefineParams get (CodeDefineParams params, s32 idx) { return params_get(cast(CodeParam, params), idx); }
forceinline bool has_entries (CodeDefineParams params ) { return params_has_entries(cast(CodeParam, params)); }
forceinline StrBuilder to_strbuilder(CodeDefineParams params ) { return define_params_to_strbuilder(params); }
forceinline void to_strbuilder(CodeDefineParams params, StrBuilder& result ) { return define_params_to_strbuilder_ref(params, & result); }
forceinline void append (CodeParams appendee, CodeParams other ) { return params_append(appendee, other); }
forceinline CodeParams get (CodeParams params, s32 idx) { return params_get(params, idx); }
forceinline bool has_entries (CodeParams params ) { return params_has_entries(params); }
forceinline StrBuilder to_strbuilder(CodeParams params ) { return params_to_strbuilder(params); }

View File

@ -257,6 +257,16 @@ CodeParams next_CodeParams(CodeParams params, CodeParams param_iter)
}
#pragma endregion CodeParams
#pragma region CodeDefineParams
forceinline void define_params_append (CodeDefineParams appendee, CodeDefineParams other ) { params_append( cast(CodeParams, appendee), cast(CodeParams, other) ); }
forceinline CodeDefineParams define_params_get (CodeDefineParams self, s32 idx ) { return params_get( cast(CodeParams, self), idx); }
forceinline bool define_params_has_entries(CodeDefineParams self) { return params_has_entries( cast(CodeParams, self)); }
CodeDefineParams begin_CodeDefineParams(CodeDefineParams params) { return begin_CodeParams( cast(CodeParams, params)); }
CodeDefineParams end_CodeDefineParams (CodeDefineParams params) { return end_CodeParams ( cast(CodeParams, params)); }
CodeDefineParams next_CodeDefineParams (CodeDefineParams params, CodeDefineParams entry_iter) { return next_CodeParams ( cast(CodeParams, params), cast(CoeParams, entry_iter)); }
#pragma endregion CodeDefineParams
#pragma region CodeSpecifiers
inline
bool specifiers_append(CodeSpecifiers self, Specifier spec )

View File

@ -354,7 +354,7 @@ void deinit(Context* ctx)
array_free( ctx->CodePools);
array_free( ctx->StringArenas);
arena_free(& ctx->LexArena);
// arena_free(& ctx->LexArena);
array_free(ctx->PreprocessorDefines);
@ -463,10 +463,12 @@ Code make_code()
return result;
}
void set_preprocess_define( Str id, b32 is_functional ) {
StrBuilder builder = strbuilder_make_str( _ctx->Allocator_Temp, id );
if (is_functional) {
strbuilder_append_char( & builder, '(' );
}
array_append( _ctx->PreprocessorDefines, cache_str( strbuilder_to_str(builder)) );
PreprocessorMacro* lookup_preprocess_macro( Str name ) {
u32 key = crc32( name.Ptr, name.Len );
return hashtable_get( _ctx->PreprocessorMacros, key );
}
void register_preprocess_macro( PreprocessorMacro macro ) {
u32 key = crc32( macro.Name.Ptr, macro.Name.Len );
hashtable_set( _ctx->PreprocessorMacros, key, macro );
}

View File

@ -71,7 +71,7 @@ struct Context
// Used by the lexer to persistently treat all these identifiers as preprocessor defines.
// Populate with strings via gen::cache_str.
// Functional defines must have format: id( ;at minimum to indicate that the define is only valid with arguments.
Array(StrCached) PreprocessorDefines;
HashTable(PreprocessorMacro) PreprocessorMacros;
// Backend
@ -88,8 +88,8 @@ struct Context
// TODO(Ed): This needs to be just handled by a parser context
Arena LexArena;
StringTable Lexer_defines;
// Arena LexArena;
// StringTable Lexer_defines;
Array(Token) Lexer_Tokens;
// TODO(Ed): Active parse context vs a parse result need to be separated conceptually
@ -109,9 +109,13 @@ GEN_API void reset(Context* ctx);
GEN_API void set_context(Context* ctx);
// Mostly used to verify a macro entry exists for the given name
GEN_API PreprocessMacro* lookup_preprocess_macro( Str Name );
// Alternative way to add a preprocess define entry for the lexer & parser to utilize
// if the user doesn't want to use def_define
GEN_API void set_preprocess_define( Str id, b32 is_functional );
// Macros are tracked by name so if the name already exists the entry will be overwritten.
GEN_API void register_preprocess_macro( PreprocessorMacro macro );
// Used internally to retrive or make string allocations.
// Strings are stored in a series of string arenas of fixed size (SizePer_StringArena)
@ -150,9 +154,11 @@ struct Opts_def_constructor {
GEN_API CodeConstructor def_constructor( Opts_def_constructor opts GEN_PARAM_DEFAULT );
struct Opts_def_define {
b32 dont_append_preprocess_defines;
MacroFlags flags;
CodeDefineParams params;
b32 dont_register_to_preprocess_macros;
};
GEN_API CodeDefine def_define( Str name, Str content, Opts_def_define opts GEN_PARAM_DEFAULT );
GEN_API CodeDefine def_define( Str name, MacroType type, Opts_def_define opts GEN_PARAM_DEFAULT );
struct Opts_def_destructor {
Code body;

View File

@ -221,6 +221,9 @@ s32 lex_preprocessor_directive( LexContext* ctx )
name.Text.Len = 1;
move_forward();
PreprocessorMacro* registered_macro = lookup_preprocess_macro(name.Text);
while ( ctx->left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) )
{
move_forward();
@ -477,23 +480,24 @@ TokArray lex( Str content )
return null_array;
}
for ( StrCached* entry = array_begin(_ctx->PreprocessorDefines); entry != array_end(_ctx->PreprocessorDefines); entry = array_next(_ctx->PreprocessorDefines, entry))
{
s32 length = 0;
char const* entry_scanner = (*entry).Ptr;
while ( entry->Len > length && (char_is_alphanumeric( *entry_scanner ) || *entry_scanner == '_') )
{
entry_scanner++;
length ++;
}
if ( entry_scanner[0] == '(' )
{
length++;
}
// TODO(ED): Remove this when preprocess defines has been converted
// for ( StrCached* entry = array_begin(_ctx->PreprocessorDefines); entry != array_end(_ctx->PreprocessorDefines); entry = array_next(_ctx->PreprocessorDefines, entry))
// {
// s32 length = 0;
// char const* entry_scanner = (*entry).Ptr;
// while ( entry->Len > length && (char_is_alphanumeric( *entry_scanner ) || *entry_scanner == '_') )
// {
// entry_scanner++;
// length ++;
// }
// if ( entry_scanner[0] == '(' )
// {
// length++;
// }
u64 key = crc32( entry->Ptr, length );
hashtable_set(c.defines, key, * entry );
}
// u64 key = crc32( entry->Ptr, length );
// hashtable_set(c.defines, key, * entry );
// }
array_clear(_ctx->Lexer_Tokens);
@ -1210,8 +1214,6 @@ TokArray lex( Str content )
}
}
hashtable_clear(_ctx->Lexer_defines);
// defines_map_arena.free();
TokArray result = { _ctx->Lexer_Tokens, 0 };
return result;
}

View File

@ -1774,7 +1774,7 @@ CodeBody parse_global_nspace( CodeType which )
// <Attributes>
}
//! Fallthrough intentional
GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_TOK_SPECIFIERS_CASES:
GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_TOK_SPECIFIER_CASES:
{
Specifier specs_found[16] = { Spec_NumSpecifiers };
s32 NumSpecifiers = 0;
@ -1787,7 +1787,7 @@ CodeBody parse_global_nspace( CodeType which )
switch ( spec )
{
GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_SPECIFIERS_CASES:
GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_SPECIFIER_CASES:
break;
case Spec_Consteval:
@ -2687,6 +2687,7 @@ CodeParams parse_params( bool use_template_capture )
#define CheckEndParams() \
(use_template_capture ? (currtok.Text.Ptr[ 0 ] != '>') : (currtok.Type != Tok_Capture_End))
// TODO(Ed): Use expression macros or this? macro as attribute?
// Ex: Unreal has this type of macro: vvvvvvvvv
// COREUOBJECT_API void CallFunction( FFrame& Stack, RESULT_DECL, UFunction* Function );
// and: vvvv
@ -2713,6 +2714,7 @@ CodeParams parse_params( bool use_template_capture )
// ( <Macro> <ValueType> <Name>
}
// TODO(Ed): Use expression macro for this?
// Unreal has yet another type of macro:
// template<class T UE_REQUIRES(TPointerIsConvertibleFromTo<T, UInterface>::Value)>
// class T ... and then ^this^ UE_REQUIRES shows up

View File

@ -25,7 +25,7 @@ case Spec_Static: \
case Spec_Volatile: \
case Spec_Virtual
#define GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_TOK_SPECIFIERS_CASES \
#define GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_TOK_SPECIFIER_CASES \
case Tok_Spec_Consteval: \
case Tok_Spec_Constexpr: \
case Tok_Spec_Constinit: \
@ -37,7 +37,7 @@ case Tok_Spec_Internal_Linkage: \
case Tok_Spec_NeverInline: \
case Tok_Spec_Static
#define GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_SPECIFIERS_CASES \
#define GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_SPECIFIER_CASES \
case Spec_Constexpr: \
case Spec_Constinit: \
case Spec_ForceInline: \

View File

@ -6,22 +6,32 @@
#include "gen/especifier.hpp"
#endif
enum MacroFlags : u32
enum MacroTypes : u16
{
// Can only be one of these at a time (required)
MF_Block_Start = bit(0), // Start of a "block" scope
MF_Block_End = bit(1), // End of a "block" scope
MF_Case_Statement = bit(2), // Used as a case statement (not utilized by the parser yet)
MF_Expression = bit(3), // Used as an expresssion (not utilized by the parser yet)
MF_Statement = bit(4), // Used a statement (will expect to be a lone macro)
MF_Expects_Body = bit(5), // Expects to consume a braced scope
MF_Typename = bit(6), // Behaves as a typename
MT_Block_Start, // Not Supported yet
MT_Block_End, // Not Supported yet
MT_Case_Statement, // Not Supported yet
MT_Expression,
MT_Statement,
MT_Typename,
// Optional
MF_Functional = bit(7),
MF_UnderlyingType = GEN_U16_Max,
};
enum MacroFlags : 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_Null = 0,
MF_UnderlyingType = GEN_U32_MAX,
MF_UnderlyingType = GEN_U16_Max,
};
struct PreprocessorMacro
{
StrCached Name;
MacroTypes Type;
MacroFlags Flags;
};
enum TokFlags : u32
@ -31,12 +41,14 @@ enum TokFlags : u32
TF_Preprocess = bit(2),
TF_Preprocess_Cond = bit(3),
TF_Attribute = bit(6),
TF_AccessOperator = bit( 7 ),
TF_AccessSpecifier = bit( 8 ),
TF_Specifier = bit( 9 ),
TF_EndDefinition = bit( 10 ), // Either ; or }
TF_Formatting = bit( 11 ),
TF_Literal = bit( 12 ),
TF_AccessOperator = bit(7),
TF_AccessSpecifier = bit(8),
TF_Specifier = bit(9),
TF_EndDefinition = bit(10), // Either ; or }
TF_Formatting = bit(11),
TF_Literal = bit(12),
TF_Macro_Functional = bit(13),
TF_Macro_Expects_Body = bit(14),
TF_Null = 0,
TF_UnderlyingType = GEN_U32_MAX,
@ -123,7 +135,7 @@ struct LexContext
char const* scanner;
s32 line;
s32 column;
StringTable defines;
// StringTable defines;
Token token;
};

View File

@ -37,6 +37,7 @@ Operator_Member_Fwd, "operator"
Operator_Cast, "operator"
Operator_Cast_Fwd, "operator"
Parameters, "__NA__"
Parameters_Define, "__NA__"
Preprocess_Define, "define"
Preprocess_Include, "include"
Preprocess_If, "if"

1 Invalid __NA__
37 Operator_Cast operator
38 Operator_Cast_Fwd operator
39 Parameters __NA__
40 Parameters_Define __NA__
41 Preprocess_Define define
42 Preprocess_Include include
43 Preprocess_If if

View File

@ -51,7 +51,9 @@ Preprocess_EndIf, "endif"
Preprocess_Include, "include"
Preprocess_Pragma, "pragma"
Preprocess_Content, "__macro_content__"
Preprocess_Macro, "__macro__"
Preprocess_Macro_Expr, "__macro_expression__"
Preprocess_Macro_Stmt, "__macro_statment__"
Preprocess_Macro_Typename, "__macro_typename__"
Preprocess_Unsupported, "__unsupported__"
Spec_Alignas, "alignas"
Spec_Const, "const"

1 Invalid __invalid__
51 Preprocess_Include include
52 Preprocess_Pragma pragma
53 Preprocess_Content __macro_content__
54 Preprocess_Macro Preprocess_Macro_Expr __macro__ __macro_expression__
55 Preprocess_Macro_Stmt __macro_statment__
56 Preprocess_Macro_Typename __macro_typename__
57 Preprocess_Unsupported __unsupported__
58 Spec_Alignas alignas
59 Spec_Const const

View File

@ -7,12 +7,13 @@ void convert_cpp_enum_to_c( CodeEnum to_convert, CodeBody to_append )
{
#pragma push_macro("enum_underlying")
#undef enum_underlying
StrCached type = to_convert->UnderlyingType ? to_convert->UnderlyingType : to_convert->Name
CodeTypedef tdef = parse_typedef(token_fmt("type", type, "name", to_convert->Name, stringize( typedef enum <type> <name>; )));
if (to_convert->UnderlyingType)
{
to_convert->UnderlyingTypeMacro = untyped_str(token_fmt("type", to_convert->UnderlyingType->Name, stringize(enum_underlying(<type>))));
to_convert->UnderlyingType = CodeTypename{nullptr};
}
CodeTypedef tdef = parse_typedef(token_fmt("name", to_convert->Name, stringize( typedef enum <name> <name>; )));
to_append.append(to_convert);
to_append.append(tdef);
#pragma pop_macro("enum_underlying")

View File

@ -27,7 +27,7 @@ case Spec_Static: \
case Spec_Volatile: \
case Spec_Virtual
#define GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_TOK_SPECIFIERS_CASES \
#define GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_TOK_SPECIFIER_CASES \
case Tok_Spec_Consteval: \
case Tok_Spec_Constexpr: \
case Tok_Spec_Constinit: \
@ -40,7 +40,7 @@ case Tok_Spec_Internal_Linkage: \
case Tok_Spec_NeverInline: \
case Tok_Spec_Static
#define GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_SPECIFIERS_CASES \
#define GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_SPECIFIER_CASES \
case Spec_Constexpr: \
case Spec_Constinit: \
case Spec_ForceInline: \