Progress on parser documentation

This commit is contained in:
Edward R. Gonzalez 2023-11-21 23:36:56 -05:00
parent f67f9547df
commit a667eb4afe
6 changed files with 273 additions and 41 deletions

View File

@ -72,12 +72,13 @@ Stores a comment.
Fields:
```cpp
StringCached Content;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
StringCached Content;
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
```
Serialization:
@ -102,6 +103,7 @@ CodeType ParentType;
CodeBody Body;
CodeType Prev; // Used to store references to interfaces
CodeType Next; // Used to store references to interfaces
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;

View File

@ -106,7 +106,7 @@ internal
}
```
Below is an outline of the general alogirithim used for these internal procedures. The intention is provide a basic briefing to aid the user in traversing the actual code definitions. These appear in the same order as they are in the `parser.cpp` file
Below is an outline of the general alogirithim used for these internal procedures. The intention is to provide a basic briefing to aid the user in traversing the actual code definitions. These appear in the same order as they are in the `parser.cpp` file
## `parse_array_decl`
@ -127,30 +127,155 @@ Below is an outline of the general alogirithim used for these internal procedure
## `parse_class_struct`
1. Check for export module specifier
2. class or struct keyword
3. `parse_attributes`
4. If identifier : `parse_identifier`
5. Parse inherited parent or interfaces
6. If opening curly brace : `parse_class_struct_body`
7. If not an inplace definition
1. End statement
2. Check for inline comment
## `parse_class_struct_body`
1. Opening curly brace
2. Parse the body (Possible options):
1. Newline : ast constant
2. Comment : `parse_comment`
3. Access_Public : ast constant
4. Access_Protected : ast constant
5. Access_Private : ast constant
6. Decl_Class : `parse_complicated_definition`
7. Decl_Enum : `parse_complicated_definition`
8. Decl_Friend : `parse_friend`
9. Decl_Operator : `parse_operator_cast`
10. Decl_Struct : `parse_complicated_definition`
11. Decl_Template : `parse_template`
12. Decl_Typedef : `parse_typedef`
13. Decl_Union : `parse_complicated_definition`
14. Decl_Using : `parse_using`
15. Operator == '~'
1. `parse_destructor`
16. Preprocess_Define : `parse_define`
17. Preprocess_Include : `parse_include`
18. Preprocess_Conditional (if, ifdef, ifndef, elif, else, endif) : `parse_preprocess_cond` or else/endif ast constant
19. Preprocess_Macro : `parse_simple_preprocess`
20. Preprocess_Pragma : `parse_pragma`
21. Preprocess_Unsupported : `parse_simple_preprocess`
22. StaticAssert : `parse_static_assert`
23. The following compound into a resolved definition or declaration:
1. Attributes (Standard, GNU, MSVC) : `parse_attributes`
2. Specifiers (consteval, constexpr, constinit, forceinline, inline, mutable, neverinline, static, volatile)
3. Possible Destructor : `parse_destructor`
4. Possible User defined operator cast : `parse_operator_cast`
5. Possible Constructor : `parse_constructor`
6. Something that has the following: (identifier, const, unsigned, signed, short, long, bool, char, int, double)
1. Possible Constructor `parse_constructor`
2. Possible Operator, Function, or varaible : `parse_operator_function_or_variable`
24. Something completely unknown (will just make untyped...) : `parse_untyped`
## `parse_comment`
1. Just wrap the token into a cached string ( the lexer did the processing )
## `parse_compilcated_definition`
This is a helper function used by the following functions to help resolve a declaration or definition:
* `parse_class_struct_body`
* `parse_global_nspace`
* `parse_union`
A portion of the code in `parse_typedef` is very similar to this as both have to resolve a similar issue.
1. Look ahead to the termination token (End statement)
2. Check to see if it fits the pattern for a forward declare
3. If the previous token was an identifier ( `token[-1]` ):
1. Look back one more token : `[-2]`
2. If the token has a closing brace its an inplace definition
3. If the `token[-2]` is an identifier & `token[-3]` is the declaration type, its a variable using a namespaced type.
4. If the `token[-2]` is an indirection, then its a variable using a namespaced/forwarded type.
5. If any of the above is the case, `parse_operator_function_or_variable`
4. If the previous token was a closing curly brace, its a definition : `parse_forward_or_definition`
5. If the previous token was a closing square brace, its an array definition : `parse_operator_function_or_variable`
## `parse_define`
1. Define directive
2. Get identifier
3. Get Content
## `parse_forward_or_definition`
* Parse any of the following for either a forward declaration or definition:
1. Decl_Class : `parse_class`
2. Decl_Enum : `parse_enum`
3. Decl_Struct : `parse_struct`
4. Decl_Union : `parse_union`
## `parse_function_after_name`
This is needed as a function defintion is not easily resolvable early on, as such this function handles resolving a function
after its been made ceratin that the type of declaration or definition is indeed for a function signature.
By the point this function is called the following are known : export module flag, attributes, specifiers, return type, & name
1. `parse_parameters`
2. parse postfix specifiers (we do not check if the specifier here is correct or not to be here... yet)
3. If there is a body : `parse_body`
4. Otherwise :
1. Statment end
2. Check for inline comment
## `parse_function_body`
Currently there is no actual parsing of the function body. Any content with the braces is shoved into an execution AST node.
In the future statements and expressions will be parsed.
1. Open curly brace
2. Grab all tokens between the brace and the closing brace, shove them in a execution AST node.
3. Closing curly brace
## `parse_global_nspace`
1. Make sure the type provided to the helper function is a `Namespace_Body`, `Global_Body`, `Export_Body`, `Extern_Linkage_body`.
2. If its not a `Global_Body` eat the opening brace for the scope.
3. `
1. Make sure this is being called for a valid type (namespace, global body, export body, linkage body)
2. If its not a global body, consume the opening curly brace
3. Parse the body (Possible options):
1. NewLine : ast constant
2. Comment : `parse_comment`
3. Decl_Cass : `parse_complicated_definition`
4. Decl_Enum : `parse_complicated_definition`
5. Decl_Extern_Linkage : `parse_extern_link`
6. Decl_Namespace : `parse_namespace`
7. Decl_Struct : `parse_complicated_definition`
8. Decl_Template : `parse_template`
9. Decl_Typedef : `parse_typedef`
10. Decl_Union : `parse_complicated_definition`
11. Decl_Using : `parse_using`
12. Preprocess_Define : `parse_define`
13. Preprocess_Include : `parse_include`
14. Preprocess_If, IfDef, IfNotDef, Elif : `parse_preprocess_cond`
15. Preprocess_Else : ast constant
16. Preprocess_Endif : ast constant
17. Preprocess_Macro : `parse_simple_preprocess`
18. Preprocess_Pragma : `parse_pragma`
19. Preprocess_Unsupported : `parse_simple_preprocess`
20. StaticAssert : `parse_static_assert`
21. Module_Export : `parse_export_body`
22. Module_Import : NOT_IMPLEMENTED
23. The following compound into a resolved definition or declaration:
1. Attributes ( Standard, GNU, MSVC, Macro ) : `parse_attributes`
2. Specifiers ( consteval, constexpr, constinit, extern, forceinline, global, inline, internal_linkage, neverinline, static )
3. Is either ( identifier, const specifier, long, short, signed, unsigned, bool, char, double, int)
1. If its an operator cast (definition outside class) : `parse_operator_cast`
2. Its an operator, function, or varaible : `parse_operator_function_or_varaible`
4. If its not a global body, consuem the closing curly brace
## `parse_identifier`
## `parse_include`
## `parse_operator_after_ret_type`
@ -224,7 +349,7 @@ Below is an outline of the general alogirithim used for these internal procedure
5. Decl_Struct
6. Decl_Union
7. Preprocess_Define
8. Preprocess_Conditional
8. Preprocess_Conditional (if, ifdef, ifndef, elif, else, endif)
9. Preprocess_Macro
10. Preprocess_Pragma
11. Unsupported preprocess directive

View File

@ -11,6 +11,7 @@ struct AST_Body;
struct AST_Attributes;
struct AST_Comment;
struct AST_Constructor;
// struct AST_BaseClass;
struct AST_Class;
struct AST_Define;
struct AST_Destructor;
@ -76,6 +77,7 @@ struct Code;
struct CodeBody;
// These are to offer ease of use and optionally strong type safety for the AST.
struct CodeAttributes;
// struct CodeBaseClass;
struct CodeComment;
struct CodeClass;
struct CodeConstructor;
@ -203,12 +205,14 @@ struct Code
#ifdef GEN_ENFORCE_STRONG_CODE_TYPES
# define operator explicit operator
#endif
operator CodeBody() const;
operator CodeAttributes() const;
// operator CodeBaseClass() const;
operator CodeComment() const;
operator CodeConstructor() const;
operator CodeDestructor() const;
operator CodeClass() const;
operator CodeConstructor() const;
operator CodeDefine() const;
operator CodeDestructor() const;
operator CodeExec() const;
operator CodeEnum() const;
operator CodeExtern() const;
@ -230,7 +234,6 @@ struct Code
operator CodeUnion() const;
operator CodeUsing() const;
operator CodeVar() const;
operator CodeBody() const;
#undef operator
};
@ -273,6 +276,7 @@ struct AST
operator Code();
operator CodeBody();
operator CodeAttributes();
// operator CodeBaseClass();
operator CodeComment();
operator CodeConstructor();
operator CodeDestructor();

View File

@ -15,7 +15,7 @@ struct AST_Body
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ];
Code Front;
Code Back;
parser::Token* Token;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
@ -32,7 +32,7 @@ struct AST_Attributes
};
Code Prev;
Code Next;
parser::Token* Token;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
@ -40,6 +40,23 @@ struct AST_Attributes
};
static_assert( sizeof(AST_Attributes) == sizeof(AST), "ERROR: AST_Attributes is not the same size as AST");
#if 0
struct AST_BaseClass
{
union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ];
};
Code Prev;
Code Next;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
};
static_assert( sizeof(AST_BaseClass) == sizeof(AST), "ERROR: AST_BaseClass is not the same size as AST");
#endif
struct AST_Comment
{
union {
@ -48,7 +65,7 @@ struct AST_Comment
};
Code Prev;
Code Next;
parser::Token* Token;
parser::Token* Tok;
Code Parent;
StringCached Name;
CodeT Type;

View File

@ -240,6 +240,7 @@ struct CodeStruct
}
Define_CodeType( Attributes );
// Define_CodeType( BaseClass );
Define_CodeType( Comment );
struct CodeConstructor

View File

@ -668,45 +668,54 @@ Code parse_class_struct( TokType which, bool inplace_def = false )
mflags = ModuleFlag::Export;
eat( TokType::Module_Export );
}
// <ModuleFlags>
eat( which );
// <ModuleFlags> <class/struct>
attributes = parse_attributes();
// <ModuleFlags> <class/struct> <Attributes>
if ( check( TokType::Identifier ) )
{
name = parse_identifier();
Context.Scope->Name = name;
}
// <ModuleFlags> <class/struct> <Attributes> <Name>
local_persist
char interface_arr_mem[ kilobytes(4) ] {0};
Array<CodeType> interfaces = Array<CodeType>::init_reserve( Arena::init_from_memory(interface_arr_mem, kilobytes(4) ), 4 );
// TODO(Ed) : Make an AST_DerivedType, we'll store any arbitary derived type into there as a linear linked list of them.
if ( check( TokType::Assign_Classifer ) )
{
eat( TokType::Assign_Classifer );
// <ModuleFlags> <class/struct> <Attributes> <Name> :
if ( currtok.is_access_specifier() )
{
access = currtok.to_access_specifier();
// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier>
}
Token parent_tok = parse_identifier();
parent = def_type( parent_tok );
// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Parent/Interface Name>
while ( check(TokType::Comma) )
{
eat(TokType::Access_Public);
eat( TokType::Comma );
// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Name>,
if ( currtok.is_access_specifier() )
{
eat(currtok.Type);
}
Token interface_tok = parse_identifier();
interfaces.append( def_type( interface_tok ) );
// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Name>, ...
}
}
@ -714,15 +723,18 @@ Code parse_class_struct( TokType which, bool inplace_def = false )
{
body = parse_class_struct_body( which, name );
}
// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Name>, ... { <Body> }
CodeComment inline_cmt = NoCode;
if ( ! inplace_def )
{
Token stmt_end = currtok;
eat( TokType::Statement_End );
// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Name>, ... { <Body> };
if ( currtok_noskip.Type == TokType::Comment && currtok_noskip.Line == stmt_end.Line )
inline_cmt = parse_comment();
// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Name>, ... { <Body> }; <InlineCmt>
}
if ( which == TokType::Decl_Class )
@ -745,6 +757,7 @@ CodeBody parse_class_struct_body( TokType which, Token name )
push_scope();
eat( TokType::BraceCurly_Open );
// {
CodeBody
result = (CodeBody) make_code();
@ -783,54 +796,66 @@ CodeBody parse_class_struct_body( TokType which, Token name )
member = access_public;
eat( TokType::Access_Public );
eat( TokType::Assign_Classifer );
// public:
break;
case TokType::Access_Protected:
member = access_protected;
eat( TokType::Access_Protected );
eat( TokType::Assign_Classifer );
// protected:
break;
case TokType::Access_Private:
member = access_private;
eat( TokType::Access_Private );
eat( TokType::Assign_Classifer );
// private:
break;
case TokType::Decl_Class:
member = parse_complicated_definition( TokType::Decl_Class );
// class
break;
case TokType::Decl_Enum:
member = parse_complicated_definition( TokType::Decl_Enum );
// enum
break;
case TokType::Decl_Friend:
member = parse_friend();
// friend
break;
case TokType::Decl_Operator:
member = parse_operator_cast();
// operator <Type>()
break;
case TokType::Decl_Struct:
member = parse_complicated_definition( TokType::Decl_Struct );
// struct
break;
case TokType::Decl_Template:
member = parse_template();
// template< ... >
break;
case TokType::Decl_Typedef:
member = parse_typedef();
// typedef
break;
case TokType::Decl_Union:
member = parse_complicated_definition( TokType::Decl_Union );
// union
break;
case TokType::Decl_Using:
member = parse_using();
// using
break;
case TokType::Operator:
@ -841,14 +866,17 @@ CodeBody parse_class_struct_body( TokType which, Token name )
}
member = parse_destructor();
// ~<Name>()
break;
case TokType::Preprocess_Define:
member = parse_define();
// #define
break;
case TokType::Preprocess_Include:
member = parse_include();
// #include
break;
case TokType::Preprocess_If:
@ -856,32 +884,39 @@ CodeBody parse_class_struct_body( TokType which, Token name )
case TokType::Preprocess_IfNotDef:
case TokType::Preprocess_ElIf:
member = parse_preprocess_cond();
break;
case TokType::Preprocess_Macro:
member = parse_simple_preprocess( TokType::Preprocess_Macro );
break;
case TokType::Preprocess_Pragma:
member = parse_pragma();
// #<Condition>
break;
case TokType::Preprocess_Else:
member = preprocess_else;
eat( TokType::Preprocess_Else );
// #else
break;
case TokType::Preprocess_EndIf:
member = preprocess_endif;
eat( TokType::Preprocess_EndIf );
// #endif
break;
case TokType::Preprocess_Macro:
member = parse_simple_preprocess( TokType::Preprocess_Macro );
// <Macro>
break;
case TokType::Preprocess_Pragma:
member = parse_pragma();
// #pragma
break;
case TokType::Preprocess_Unsupported:
member = parse_simple_preprocess( TokType::Preprocess_Unsupported );
// #<UNKNOWN>
break;
case TokType::StaticAssert:
member = parse_static_assert();
// static_assert
break;
case TokType::Attribute_Open:
@ -892,6 +927,7 @@ CodeBody parse_class_struct_body( TokType which, Token name )
#undef Entry
{
attributes = parse_attributes();
// <Attributes>
}
//! Fallthrough intended
case TokType::Spec_Consteval:
@ -942,16 +978,19 @@ CodeBody parse_class_struct_body( TokType which, Token name )
{
specifiers = def_specifiers( NumSpecifiers, specs_found );
}
// <Attributes> <Specifiers>
if ( currtok.Type == TokType::Operator && currtok.Text[0] == '~' )
{
member = parse_destructor( specifiers );
// <Attribute> <Specifiers> ~<Name>()
break;
}
if ( currtok.Type == TokType::Decl_Operator )
{
member = parse_operator_cast( specifiers );
// <Attributes> <Specifiers> operator <Type>()
break;
}
}
@ -972,11 +1011,15 @@ CodeBody parse_class_struct_body( TokType which, Token name )
if ( str_compare( name.Text, currtok.Text, name.Length ) == 0 )
{
member = parse_constructor();
// <Attributes> <Specifiers> <Name>()
break;
}
}
member = parse_operator_function_or_variable( expects_function, attributes, specifiers );
// <Attributes> <Specifiers> operator <Op> ...
// or
// <Attributes> <Specifiers> <Name> ...
}
break;
@ -990,6 +1033,7 @@ CodeBody parse_class_struct_body( TokType which, Token name )
}
member = untyped_str( untyped_tok );
// Something unknown
break;
}
@ -1004,6 +1048,7 @@ CodeBody parse_class_struct_body( TokType which, Token name )
}
eat( TokType::BraceCurly_Close );
// { <Members> }
Context.pop();
return result;
}
@ -1053,6 +1098,7 @@ Code parse_complicated_definition( TokType which )
{
// Its a forward declaration only
Code result = parse_forward_or_definition( which, is_inplace );
// <class, enum, struct, or union> <Name>;
Context.pop();
return result;
}
@ -1074,9 +1120,9 @@ Code parse_complicated_definition( TokType which )
ok_to_parse = true;
is_inplace = true;
}
else if ( tok.Type == TokType::Identifier && tokens[ idx - 3 ].Type == TokType::Decl_Struct )
else if ( tok.Type == TokType::Identifier && tokens[ idx - 3 ].Type == which )
{
// Its a variable with type ID using struct namespace.
// Its a variable with type ID using <which> namespace.
// <which> <type_identifier> <identifier>;
ok_to_parse = true;
}
@ -1095,22 +1141,23 @@ Code parse_complicated_definition( TokType which )
}
Code result = parse_operator_function_or_variable( false, { nullptr }, { nullptr } );
// <Attributes> <Specifiers> <ReturnType/ValueType> <operator <Op>, or Name> ...
Context.pop();
return result;
}
else if ( tok.Type == TokType::BraceCurly_Close )
{
// Its a definition
// <which> { ... };
Code result = parse_forward_or_definition( which, is_inplace );
// <which> { ... };
Context.pop();
return result;
}
else if ( tok.Type == TokType::BraceSquare_Close)
{
// Its an array definition
// <which> <type_identifier> <identifier> [ ... ];
Code result = parse_operator_function_or_variable( false, { nullptr }, { nullptr } );
// <which> <type_identifier> <identifier> [ ... ];
Context.pop();
return result;
}
@ -1127,6 +1174,7 @@ CodeDefine parse_define()
{
push_scope();
eat( TokType::Preprocess_Define );
// #define
CodeDefine
define = (CodeDefine) make_code();
@ -1142,6 +1190,7 @@ CodeDefine parse_define()
Context.Scope->Name = currtok;
define->Name = get_cached_string( currtok );
eat( TokType::Identifier );
// #define <Name>
if ( ! check( TokType::Preprocess_Content ))
{
@ -1154,6 +1203,7 @@ CodeDefine parse_define()
{
define->Content = get_cached_string( currtok );
eat( TokType::Preprocess_Content );
// #define <Name> <Content>
Context.pop();
return define;
@ -1161,6 +1211,7 @@ CodeDefine parse_define()
define->Content = get_cached_string( strip_formatting( currtok, strip_formatting_dont_preserve_newlines ) );
eat( TokType::Preprocess_Content );
// #define <Name> <Content>
Context.pop();
return define;
@ -1212,8 +1263,9 @@ CodeFn parse_function_after_name(
{
push_scope();
CodeParam params = parse_params();
// <Attributes> <Specifiers> <ReturnType> <Name> ( <Parameters> )
// These have to be kept separate from the return type's specifiers.
// TODO(Ed), Review old comment : These have to be kept separate from the return type's specifiers.
while ( left && currtok.is_specifier() )
{
if ( specifiers.ast == nullptr )
@ -1226,6 +1278,7 @@ CodeFn parse_function_after_name(
specifiers.append( ESpecifier::to_type(currtok) );
eat( currtok.Type );
}
// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers>
CodeBody body = NoCode;
CodeComment inline_cmt = NoCode;
@ -1237,14 +1290,17 @@ CodeFn parse_function_after_name(
Context.pop();
return CodeInvalid;
}
// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers> { <Body> }
}
else
{
Token stmt_end = currtok;
eat( TokType::Statement_End );
// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers>;
if ( currtok_noskip.Type == TokType::Comment && currtok_noskip.Line == stmt_end.Line )
inline_cmt = parse_comment();
// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers>; <InlineCmt>
}
using namespace ECode;
@ -1349,6 +1405,7 @@ CodeBody parse_global_nspace( CodeT which )
if ( which != Global_Body )
eat( TokType::BraceCurly_Open );
// {
CodeBody
result = (CodeBody) make_code();
@ -1381,10 +1438,12 @@ CodeBody parse_global_nspace( CodeT which )
case TokType::Decl_Class:
member = parse_complicated_definition( TokType::Decl_Class );
// class
break;
case TokType::Decl_Enum:
member = parse_complicated_definition( TokType::Decl_Enum );
// enum
break;
case TokType::Decl_Extern_Linkage:
@ -1392,38 +1451,47 @@ CodeBody parse_global_nspace( CodeT which )
log_failure( "Nested extern linkage\n%s", Context.to_string() );
member = parse_extern_link();
// extern "..." { ... }
break;
case TokType::Decl_Namespace:
member = parse_namespace();
// namespace <Name> { ... }
break;
case TokType::Decl_Struct:
member = parse_complicated_definition( TokType::Decl_Struct );
// struct ...
break;
case TokType::Decl_Template:
member = parse_template();
// template<...> ...
break;
case TokType::Decl_Typedef:
member = parse_typedef();
// typedef ...
break;
case TokType::Decl_Union:
member = parse_complicated_definition( TokType::Decl_Union );
// union ...
break;
case TokType::Decl_Using:
member = parse_using();
// using ...
break;
case TokType::Preprocess_Define:
member = parse_define();
// #define ...
break;
case TokType::Preprocess_Include:
member = parse_include();
// #include ...
break;
case TokType::Preprocess_If:
@ -1431,32 +1499,39 @@ CodeBody parse_global_nspace( CodeT which )
case TokType::Preprocess_IfNotDef:
case TokType::Preprocess_ElIf:
member = parse_preprocess_cond();
break;
case TokType::Preprocess_Macro:
member = parse_simple_preprocess( TokType::Preprocess_Macro );
break;
case TokType::Preprocess_Pragma:
member = parse_pragma();
// #<Conditional> ...
break;
case TokType::Preprocess_Else:
member = preprocess_else;
eat( TokType::Preprocess_Else );
// #else
break;
case TokType::Preprocess_EndIf:
member = preprocess_endif;
eat( TokType::Preprocess_EndIf );
// #endif
break;
case TokType::Preprocess_Macro:
member = parse_simple_preprocess( TokType::Preprocess_Macro );
// <Macro>
break;
case TokType::Preprocess_Pragma:
member = parse_pragma();
// #pragma ...
break;
case TokType::Preprocess_Unsupported:
member = parse_simple_preprocess( TokType::Preprocess_Unsupported );
// #<UNSUPPORTED> ...
break;
case TokType::StaticAssert:
member = parse_static_assert();
// static_assert( <Conditional Expression>, ... );
break;
case TokType::Module_Export:
@ -1464,13 +1539,16 @@ CodeBody parse_global_nspace( CodeT which )
log_failure( "Nested export declaration\n%s", Context.to_string() );
member = parse_export_body();
// export { ... }
break;
case TokType::Module_Import:
{
not_implemented( context );
// import ...
}
//! Fallthrough intentional
case TokType::Attribute_Open:
case TokType::Decl_GNU_Attribute:
case TokType::Decl_MSVC_Attribute:
#define Entry( attribute, str ) case TokType::attribute:
@ -1478,6 +1556,7 @@ CodeBody parse_global_nspace( CodeT which )
#undef Entry
{
attributes = parse_attributes();
// <Attributes>
}
//! Fallthrough intentional
case TokType::Spec_Consteval:
@ -1542,6 +1621,7 @@ CodeBody parse_global_nspace( CodeT which )
{
specifiers = def_specifiers( NumSpecifiers, specs_found );
}
// <Attributes> <Specifiers>
}
//! Fallthrough intentional
case TokType::Identifier:
@ -1581,10 +1661,12 @@ CodeBody parse_global_nspace( CodeT which )
if ( found_operator_cast )
{
member = parse_operator_cast();
// <Attributes> <Specifiers> <Name>::operator <Type>() { ... }
break;
}
member = parse_operator_function_or_variable( expects_function, attributes, specifiers );
// <Attributes> <Specifiers> ...
}
}
@ -1600,6 +1682,7 @@ CodeBody parse_global_nspace( CodeT which )
if ( which != Global_Body )
eat( TokType::BraceCurly_Close );
// { <Body> }
return result;
}