Support for module and attribute parsing ( untested )

This commit is contained in:
Edward R. Gonzalez 2023-07-23 22:14:48 -04:00
parent b1de5b1ac7
commit e7374ec328
8 changed files with 400 additions and 207 deletions

View File

@ -26,13 +26,17 @@ The project has reached an *alpha* state, all the current functionality works fo
The project has no external dependencies beyond: The project has no external dependencies beyond:
* `stdarg.h` * `errno.h` (gen.cpp)
* `stddef.h` * `stat.h` (gen.cpp)
* `stdio.h` * `stdarg.h` (gen.hpp)
* `errno.h` * `stddef.h` (gen.hpp
* `unistd.h` (Linux/Mac) * `stdio.h` (gen.cpp)
* `intrin.h` (Windows) * `copyfile.h` (Mac, gen.cpp)
* `windows.h` (Windows) * `types.h` (Linux, gen.cpp)
* `unistd.h` (Linux/Mac, gen.cpp)
* `intrin.h` (Windows, gen.hpp)
* `io.h` (Windows with gcc, gen.cpp)
* `windows.h` (Windows, gen.cpp)
Dependencies for the project are wrapped within `GENCPP_ROLL_OWN_DEPENDENCIES` (Defining it will disable them). 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). The majority of the dependency's implementation was derived from the [c-zpl library](https://github.com/zpl-c/zpl).
@ -684,7 +688,6 @@ Names or Content fields are interned strings and thus showed be cached using `ge
# TODO # TODO
* Support defining & parsing full definitions inside a typedef. (For C patterns) * Support defining & parsing full definitions inside a typedef. (For C patterns)
* Support module and attribute parsing (Marked with TODOs for now..)
* Implement a context stack for the parsing, allows for accurate scope validation for the AST types. * Implement a context stack for the parsing, allows for accurate scope validation for the AST types.
* Trailing specifiers ( postfix ) for functions (const, override, final) * Trailing specifiers ( postfix ) for functions (const, override, final)
* Make a more robust test suite. * Make a more robust test suite.

45
gencpp.10x Normal file
View File

@ -0,0 +1,45 @@
<?xml version="1.0"?>
<N10X>
<Workspace>
<IncludeFilter>*.*</IncludeFilter>
<ExcludeFilter>*.obj,*.lib,*.pch,*.dll,*.pdb,.vs,Debug,Release,x64,obj,*.user,Intermediate</ExcludeFilter>
<SyncFiles>true</SyncFiles>
<Recursive>true</Recursive>
<ShowEmptyFolders>true</ShowEmptyFolders>
<IsVirtual>false</IsVirtual>
<IsFolder>false</IsFolder>
<BuildCommand></BuildCommand>
<RebuildCommand></RebuildCommand>
<BuildFileCommand></BuildFileCommand>
<CleanCommand></CleanCommand>
<BuildWorkingDirectory></BuildWorkingDirectory>
<CancelBuild></CancelBuild>
<RunCommand></RunCommand>
<RunCommandWorkingDirectory></RunCommandWorkingDirectory>
<DebugCommand></DebugCommand>
<ExePathCommand></ExePathCommand>
<DebugSln></DebugSln>
<UseVisualStudioEnvBat>false</UseVisualStudioEnvBat>
<Configurations>
<Configuration>Debug</Configuration>
<Configuration>Release</Configuration>
</Configurations>
<Platforms>
<Platform>x64</Platform>
</Platforms>
<AdditionalIncludePaths>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.36.32532\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.36.32532\ATLMFC\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\VS\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\um</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\shared</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\winrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\cppwinrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um</AdditionalIncludePath>
</AdditionalIncludePaths>
<Defines></Defines>
<ConfigProperties></ConfigProperties>
<Children></Children>
</Workspace>
</N10X>

View File

@ -102,13 +102,21 @@
<None Include="scripts\build.ci.ps1" /> <None Include="scripts\build.ci.ps1" />
<None Include="scripts\build.ps1" /> <None Include="scripts\build.ps1" />
<None Include="scripts\clean.ps1" /> <None Include="scripts\clean.ps1" />
<None Include="scripts\gen.ps1" />
<None Include="scripts\genccp.natstepfilter" />
<None Include="scripts\gencpp.refactor" />
<None Include="scripts\get_sources.ps1" /> <None Include="scripts\get_sources.ps1" />
<None Include="test\gen\meson.build" /> <None Include="test\gen\meson.build" />
<None Include="test\meson.build" /> <None Include="test\meson.build" />
<None Include="test\Readme.md" /> <None Include="test\Readme.md" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="project\gen.dep.hpp" />
<ClInclude Include="project\gen.editor.hpp" />
<ClInclude Include="project\gen.hpp" /> <ClInclude Include="project\gen.hpp" />
<ClInclude Include="project\gen.pop_ignores.inline.hpp" />
<ClInclude Include="project\gen.push_ignores.inline.hpp" />
<ClInclude Include="project\gen.scanner.hpp" />
<ClInclude Include="project\gen.undef.macros.hpp" /> <ClInclude Include="project\gen.undef.macros.hpp" />
<ClInclude Include="test\DummyInclude.hpp" /> <ClInclude Include="test\DummyInclude.hpp" />
<ClInclude Include="test\gen\array.Upfront.gen.hpp" /> <ClInclude Include="test\gen\array.Upfront.gen.hpp" />
@ -119,7 +127,9 @@
<ClInclude Include="test\Parsed\Buffer.Parsed.hpp" /> <ClInclude Include="test\Parsed\Buffer.Parsed.hpp" />
<ClInclude Include="test\Parsed\HashTable.Parsed.hpp" /> <ClInclude Include="test\Parsed\HashTable.Parsed.hpp" />
<ClInclude Include="test\Parsed\Ring.Parsed.hpp" /> <ClInclude Include="test\Parsed\Ring.Parsed.hpp" />
<ClInclude Include="test\parsing.hpp" />
<ClInclude Include="test\SOA.hpp" /> <ClInclude Include="test\SOA.hpp" />
<ClInclude Include="test\upfront.hpp" />
<ClInclude Include="test\Upfront\Array.Upfront.hpp" /> <ClInclude Include="test\Upfront\Array.Upfront.hpp" />
<ClInclude Include="test\Upfront\Buffer.Upfront.hpp" /> <ClInclude Include="test\Upfront\Buffer.Upfront.hpp" />
<ClInclude Include="test\Upfront\HashTable.Upfront.hpp" /> <ClInclude Include="test\Upfront\HashTable.Upfront.hpp" />
@ -130,11 +140,17 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="project\gen.cpp" /> <ClCompile Include="project\gen.cpp" />
<ClCompile Include="project\gen.dep.cpp" />
<ClCompile Include="singleheader\gen\gen.singleheader.cpp" /> <ClCompile Include="singleheader\gen\gen.singleheader.cpp" />
<ClCompile Include="test\gen\build\meson-private\sanitycheckc.c" /> <ClCompile Include="test\gen\build\meson-private\sanitycheckc.c" />
<ClCompile Include="test\gen\build\meson-private\sanitycheckcpp.cc" /> <ClCompile Include="test\gen\build\meson-private\sanitycheckcpp.cc" />
<ClCompile Include="test\parsing.cpp" />
<ClCompile Include="test\sanity.cpp" />
<ClCompile Include="test\SOA.cpp" />
<ClCompile Include="test\test.cpp" /> <ClCompile Include="test\test.cpp" />
<ClCompile Include="test\test.parsing.cpp" />
<ClCompile Include="test\test.Upfront.cpp" /> <ClCompile Include="test\test.Upfront.cpp" />
<ClCompile Include="test\upfront.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Natvis Include=".vscode\gencpp.natvis" /> <Natvis Include=".vscode\gencpp.natvis" />

View File

@ -33,6 +33,24 @@
<ClCompile Include="test\test.Upfront.cpp"> <ClCompile Include="test\test.Upfront.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="project\gen.dep.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test\parsing.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test\sanity.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test\SOA.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test\upfront.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test\test.parsing.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="project\gen.hpp"> <ClInclude Include="project\gen.hpp">
@ -92,6 +110,27 @@
<ClInclude Include="test\Parsed\Sanity.Parsed.hpp"> <ClInclude Include="test\Parsed\Sanity.Parsed.hpp">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="project\gen.dep.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="project\gen.editor.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="project\gen.pop_ignores.inline.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="project\gen.push_ignores.inline.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="project\gen.scanner.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="test\parsing.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="test\upfront.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include=".editorconfig" /> <None Include=".editorconfig" />
@ -103,6 +142,9 @@
<None Include="test\gen\meson.build" /> <None Include="test\gen\meson.build" />
<None Include="test\meson.build" /> <None Include="test\meson.build" />
<None Include="test\Readme.md" /> <None Include="test\Readme.md" />
<None Include="scripts\gen.ps1" />
<None Include="scripts\genccp.natstepfilter" />
<None Include="scripts\gencpp.refactor" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Natvis Include=".vscode\gencpp.natvis" /> <Natvis Include=".vscode\gencpp.natvis" />

View File

@ -17,7 +17,7 @@
namespace gen { namespace gen {
#pragma region StaticData #pragma region StaticData
// TODO : Convert global allocation strategy to use the dual-scratch allocator for a contextual scope. // TODO : Convert global allocation strategy to use a slab allocation strategy.
global AllocatorInfo GlobalAllocator; global AllocatorInfo GlobalAllocator;
global Array<Arena> Global_AllocatorBuckets; global Array<Arena> Global_AllocatorBuckets;
@ -849,11 +849,6 @@ String AST::to_string()
result.append( "typedef "); result.append( "typedef ");
if ( Attributes )
{
result.append_fmt( "%s ", Attributes->to_string() );
}
result.append_fmt( "%s %s", UnderlyingType->to_string(), Name ); result.append_fmt( "%s %s", UnderlyingType->to_string(), Name );
if ( UnderlyingType->Type == Typename && UnderlyingType->ArrExpr ) if ( UnderlyingType->Type == Typename && UnderlyingType->ArrExpr )
@ -2567,9 +2562,6 @@ CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes, Module
result->UnderlyingType = type; result->UnderlyingType = type;
if ( attributes )
result->Attributes = attributes;
return result; return result;
} }
@ -3307,6 +3299,8 @@ namespace Parser
It will not be capable of lexing C++ code with unsupported features. It will not be capable of lexing C++ code with unsupported features.
For the sake of scanning files, it can scan preprocessor directives For the sake of scanning files, it can scan preprocessor directives
Attributes_Start is only used to indicate the start of the user_defined attribute list.
*/ */
# define Define_TokType \ # define Define_TokType \
@ -3318,6 +3312,8 @@ namespace Parser
Entry( Ampersand, "&" ) \ Entry( Ampersand, "&" ) \
Entry( Ampersand_DBL, "&&" ) \ Entry( Ampersand_DBL, "&&" ) \
Entry( Assign_Classifer, ":" ) \ Entry( Assign_Classifer, ":" ) \
Entry( Attribute_Open, "[[" ) \
Entry( Attribute_Close, "]]" ) \
Entry( BraceCurly_Open, "{" ) \ Entry( BraceCurly_Open, "{" ) \
Entry( BraceCurly_Close, "}" ) \ Entry( BraceCurly_Close, "}" ) \
Entry( BraceSquare_Open, "[" ) \ Entry( BraceSquare_Open, "[" ) \
@ -3328,6 +3324,8 @@ namespace Parser
Entry( Char, "__char__" ) \ Entry( Char, "__char__" ) \
Entry( Comma, "," ) \ Entry( Comma, "," ) \
Entry( Decl_Class, "class" ) \ Entry( Decl_Class, "class" ) \
Entry( Decl_GNU_Attribute, "__attribute__" ) \
Entry( Decl_MSVC_Attribute, "__declspec" ) \
Entry( Decl_Enum, "enum" ) \ Entry( Decl_Enum, "enum" ) \
Entry( Decl_Extern_Linkage, "extern" ) \ Entry( Decl_Extern_Linkage, "extern" ) \
Entry( Decl_Friend, "friend" ) \ Entry( Decl_Friend, "friend" ) \
@ -3369,15 +3367,15 @@ namespace Parser
Entry( Type_Long, "long" ) \ Entry( Type_Long, "long" ) \
Entry( Type_char, "char" ) \ Entry( Type_char, "char" ) \
Entry( Type_int, "int" ) \ Entry( Type_int, "int" ) \
Entry( Type_double, "double" ) Entry( Type_double, "double" ) \
Entry( Attributes_Start, "__attrib_start__" )
enum class TokType : u32 enum class TokType : u32
{ {
# define Entry( Name_, Str_ ) Name_, # define Entry( Name_, Str_ ) Name_,
Define_TokType Define_TokType
GEN_Define_Attribute_Tokens
# undef Entry # undef Entry
Attr_Keyword,
Num, Num,
Invalid Invalid
}; };
@ -3408,9 +3406,8 @@ namespace Parser
{ {
# define Entry( Name_, Str_ ) { sizeof(Str_), Str_ }, # define Entry( Name_, Str_ ) { sizeof(Str_), Str_ },
Define_TokType Define_TokType
GEN_Define_Attribute_Tokens
# undef Entry # undef Entry
{ sizeof(Attribute::Keyword), Attribute::Keyword },
}; };
for ( u32 index = 0; index < (u32)TokType::Num; index++ ) for ( u32 index = 0; index < (u32)TokType::Num; index++ )
@ -3436,9 +3433,8 @@ namespace Parser
{ {
# define Entry( Name_, Str_ ) Str_, # define Entry( Name_, Str_ ) Str_,
Define_TokType Define_TokType
GEN_Define_Attribute_Tokens
# undef Entry # undef Entry
Attribute::Keyword,
}; };
return lookup[(u32)type]; return lookup[(u32)type];
@ -3467,6 +3463,11 @@ namespace Parser
return scast(AccessSpec, tok.Type); return scast(AccessSpec, tok.Type);
} }
internal inline
bool tok_is_attribute( Token const& tok )
{
return tok.Type > TokType::Attributes_Start;
}
struct TokArray struct TokArray
{ {
@ -4108,6 +4109,68 @@ Code parse_array_decl( Parser::TokArray& toks, char const* context )
return { nullptr }; return { nullptr };
} }
internal inline
CodeAttributes parse_attributes( Parser::TokArray& toks, char const* context )
{
using namespace Parser;
Token start;
if ( check(TokType::Attribute_Open) )
{
eat( TokType::Attribute_Open);
while ( left && currtok.Type != TokType::Attribute_Close )
{
eat( currtok.Type );
}
eat( TokType::Attribute_Close );
}
else if ( check(TokType::Decl_GNU_Attribute) )
{
eat(TokType::BraceCurly_Open);
eat(TokType::BraceCurly_Open);
while ( left && currtok.Type != TokType::BraceCurly_Close )
{
eat(currtok.Type);
}
eat(TokType::BraceCurly_Close);
eat(TokType::BraceCurly_Close);
}
else if ( check(TokType::Decl_MSVC_Attribute) )
{
eat( TokType::Decl_MSVC_Attribute );
eat( TokType::BraceCurly_Open);
while ( left && currtok.Type != TokType::BraceCurly_Close )
{
eat(currtok.Type);
}
eat(TokType::BraceCurly_Close);
}
else if ( tok_is_attribute( currtok ) )
{
eat(currtok.Type);
}
s32 len = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)start.Text;
if ( len > 0 )
{
StrC attribute_txt = { len, start.Text };
return def_attributes( attribute_txt );
}
return { nullptr };
}
internal inline internal inline
Parser::Token parse_identifier( Parser::TokArray& toks, char const* context ) Parser::Token parse_identifier( Parser::TokArray& toks, char const* context )
{ {
@ -4711,7 +4774,7 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes
{ {
if ( expects_function ) if ( expects_function )
{ {
log_failure( "gen::parse_template: expected function declaration (consteval was used)" ); log_failure( "gen::parse_operator_function_or_variable: expected function declaration (consteval was used)" );
return Code::Invalid; return Code::Invalid;
} }
@ -4809,36 +4872,14 @@ CodeBody parse_class_struct_body( Parser::TokType which, Parser::TokArray& toks,
member = parse_using( toks, context ); member = parse_using( toks, context );
break; break;
case TokType::BraceSquare_Open: case TokType::Attribute_Open:
case TokType::Attr_Keyword: case TokType::Decl_GNU_Attribute:
case TokType::Decl_MSVC_Attribute:
#define Entry( attribute, str ) case TokType::attribute:
GEN_Define_Attribute_Tokens
#undef Entry
{ {
// Standard attribute attributes = parse_attributes( toks, context );
if ( currtok.Type == TokType::BraceSquare_Open )
{
eat( TokType::BraceSquare_Open );
if ( currtok.Type != TokType::BraceSquare_Open )
{
log_failure( "%s: Error, expected attribute name", context );
return result;
}
while ( left && currtok.Type != TokType::BraceSquare_Close )
{
// TODO : Parse attributes
}
eat( TokType::BraceSquare_Close );
eat( TokType::BraceSquare_Close );
}
// Platform Specific attribute
eat( TokType::Attr_Keyword );
eat( TokType::Capture_Start );
// TODO : Parse attributes
eat( TokType::Capture_End );
} }
//! Fallthrough intended //! Fallthrough intended
case TokType::Spec_Consteval: case TokType::Spec_Consteval:
@ -4943,11 +4984,15 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con
CodeClass result = CodeInvalid; CodeClass result = CodeInvalid;
// TODO : Parse module specifiers if ( check(TokType::Module_Export) )
{
mflags = ModuleFlag::Export;
eat( TokType::Module_Export );
}
eat( which ); eat( which );
// TODO : Parse attributes attributes = parse_attributes( toks, context );
if ( check( TokType::Identifier ) ) if ( check( TokType::Identifier ) )
name = parse_identifier( toks, context ); name = parse_identifier( toks, context );
@ -4979,16 +5024,14 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con
if ( which == TokType::Decl_Class ) if ( which == TokType::Decl_Class )
result = def_class( name, body, parent, access result = def_class( name, body, parent, access
// TODO : Set these up later , attributes
, NoCode // Attributes , mflags
, ModuleFlag::None
); );
else else
result = def_struct( name, body, (CodeType)parent, access result = def_struct( name, body, (CodeType)parent, access
// TODO : Set these up later , attributes
, NoCode // Attributes , mflags
, ModuleFlag::None
); );
return result; return result;
@ -5115,38 +5158,13 @@ CodeBody parse_global_nspace( CodeT which, Parser::TokArray& toks, char const* c
not_implemented( context ); not_implemented( context );
} }
//! Fallthrough intentional //! Fallthrough intentional
case TokType::BraceSquare_Open: case TokType::Decl_GNU_Attribute:
case TokType::Attr_Keyword: case TokType::Decl_MSVC_Attribute:
#define Entry( attribute, str ) case TokType::attribute:
GEN_Define_Attribute_Tokens
#undef Entry
{ {
not_implemented( context ); attributes = parse_attributes( toks, context );
// Standard attribute
if ( currtok.Type == TokType::BraceSquare_Open )
{
eat( TokType::BraceSquare_Open );
if ( currtok.Type != TokType::BraceSquare_Open )
{
log_failure( "%s: Error, expected attribute name", context );
return result;
}
while ( left && currtok.Type != TokType::BraceSquare_Close )
{
// TODO : Parse attributes
}
eat( TokType::BraceSquare_Close );
eat( TokType::BraceSquare_Close );
}
// Platform Specific attribute
eat( TokType::Attr_Keyword );
eat( TokType::Capture_Start );
// TODO : Parse attributes
eat( TokType::Capture_End );
} }
//! Fallthrough intentional //! Fallthrough intentional
case TokType::Spec_Consteval: case TokType::Spec_Consteval:
@ -5494,10 +5512,15 @@ CodeFn parse_functon( Parser::TokArray& toks, char const* context )
CodeAttributes attributes = { nullptr }; CodeAttributes attributes = { nullptr };
CodeSpecifier specifiers = { nullptr }; CodeSpecifier specifiers = { nullptr };
ModuleFlag mflags = ModuleFlag::None;
// TODO : Parse module specifiers if ( check(TokType::Module_Export) )
{
mflags = ModuleFlag::Export;
eat( TokType::Module_Export );
}
// TODO : Parse attributes attributes = parse_attributes( toks, context );
while ( left && tok_is_specifier( currtok ) ) while ( left && tok_is_specifier( currtok ) )
{ {
@ -5536,7 +5559,7 @@ CodeFn parse_functon( Parser::TokArray& toks, char const* context )
if ( ! name ) if ( ! name )
return CodeInvalid; return CodeInvalid;
CodeFn result = parse_function_after_name( ModuleFlag::None, attributes, specifiers, ret_type, name, toks, context ); CodeFn result = parse_function_after_name( mflags, attributes, specifiers, ret_type, name, toks, context );
return result; return result;
} }
@ -5603,16 +5626,23 @@ CodeNamespace parse_namespace( StrC def )
internal internal
CodeOperator parse_operator( Parser::TokArray& toks, char const* context ) CodeOperator parse_operator( Parser::TokArray& toks, char const* context )
{ {
// TODO : Parse Module specifier using namespace Parser;
// TODO : Parse Attributes
CodeAttributes attributes = { nullptr }; CodeAttributes attributes = { nullptr };
CodeSpecifier specifiers = { nullptr }; CodeSpecifier specifiers = { nullptr };
ModuleFlag mflags = ModuleFlag::None;
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers }; SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
s32 num_specifiers = 0; s32 num_specifiers = 0;
if ( check(TokType::Module_Export) )
{
mflags = ModuleFlag::Export;
eat( TokType::Module_Export );
}
attributes = parse_attributes( toks, context );
while ( left && tok_is_specifier( currtok ) ) while ( left && tok_is_specifier( currtok ) )
{ {
SpecifierT spec = ESpecifier::to_type( currtok ); SpecifierT spec = ESpecifier::to_type( currtok );
@ -5643,7 +5673,7 @@ CodeOperator parse_operator( Parser::TokArray& toks, char const* context )
// Parse Return Type // Parse Return Type
CodeType ret_type = parse_type( toks, stringize(parse_operator) ); CodeType ret_type = parse_type( toks, stringize(parse_operator) );
CodeOperator result = parse_operator_after_ret_type( ModuleFlag::None, attributes, specifiers, ret_type, toks, context ); CodeOperator result = parse_operator_after_ret_type( mflags, attributes, specifiers, ret_type, toks, context );
return result; return result;
} }
@ -5751,7 +5781,13 @@ CodeTemplate parse_template( Parser::TokArray& toks, char const* context )
using namespace Parser; using namespace Parser;
// TODO : Parse Module specifier ModuleFlag mflags = ModuleFlag::None;
if ( check(TokType::Module_Export) )
{
mflags = ModuleFlag::Export;
eat( TokType::Module_Export );
}
eat( TokType::Decl_Template ); eat( TokType::Decl_Template );
@ -5784,17 +5820,16 @@ CodeTemplate parse_template( Parser::TokArray& toks, char const* context )
// Its either a function or a variable // Its either a function or a variable
Token name = { nullptr, 0, TokType::Invalid }; Token name = { nullptr, 0, TokType::Invalid };
CodeAttributes attributes = { nullptr }; CodeAttributes attributes = { nullptr };
CodeSpecifier specifiers = { nullptr }; CodeSpecifier specifiers = { nullptr };
// TODO : Parse attributes
bool expects_function = false; bool expects_function = false;
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers }; SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
s32 num_specifiers = 0; s32 num_specifiers = 0;
attributes = parse_attributes( toks, stringize(parse_template) );
while ( left && tok_is_specifier( currtok ) ) while ( left && tok_is_specifier( currtok ) )
{ {
SpecifierT spec = ESpecifier::to_type( currtok ); SpecifierT spec = ESpecifier::to_type( currtok );
@ -5846,6 +5881,7 @@ CodeTemplate parse_template( Parser::TokArray& toks, char const* context )
result->Type = ECode::Template; result->Type = ECode::Template;
result->Params = params; result->Params = params;
result->Declaration = definition; result->Declaration = definition;
result->ModuleFlags = mflags;
return result; return result;
# undef UseTemplateCapture # undef UseTemplateCapture
@ -5876,6 +5912,8 @@ CodeType parse_type( Parser::TokArray& toks, char const* context )
Token name = { nullptr, 0, TokType::Invalid }; Token name = { nullptr, 0, TokType::Invalid };
Token brute_sig = { currtok.Text, 0, TokType::Invalid }; Token brute_sig = { currtok.Text, 0, TokType::Invalid };
CodeAttributes attributes = parse_attributes( toks, context );
while ( left && tok_is_specifier( currtok ) ) while ( left && tok_is_specifier( currtok ) )
{ {
SpecifierT spec = ESpecifier::to_type( currtok ); SpecifierT spec = ESpecifier::to_type( currtok );
@ -6030,6 +6068,9 @@ CodeType parse_type( Parser::TokArray& toks, char const* context )
result->Name = get_cached_string( name ); result->Name = get_cached_string( name );
if ( attributes )
result->Attributes = attributes;
return result; return result;
} }
@ -6056,6 +6097,14 @@ CodeTypedef parse_typedef( Parser::TokArray& toks, char const* context )
Code array_expr = { nullptr }; Code array_expr = { nullptr };
Code type = { nullptr }; Code type = { nullptr };
ModuleFlag mflags = ModuleFlag::None;
if ( check(TokType::Module_Export) )
{
mflags = ModuleFlag::Export;
eat( TokType::Module_Export );
}
eat( TokType::Decl_Typedef ); eat( TokType::Decl_Typedef );
if ( check( TokType::Decl_Enum ) ) if ( check( TokType::Decl_Enum ) )
@ -6089,6 +6138,7 @@ CodeTypedef parse_typedef( Parser::TokArray& toks, char const* context )
result = (CodeTypedef) make_code(); result = (CodeTypedef) make_code();
result->Type = Typedef; result->Type = Typedef;
result->Name = get_cached_string( name ); result->Name = get_cached_string( name );
result->ModuleFlags = mflags;
result->UnderlyingType = type; result->UnderlyingType = type;
@ -6115,12 +6165,17 @@ CodeUnion parse_union( Parser::TokArray& toks, char const* context )
{ {
using namespace Parser; using namespace Parser;
// TODO : Parse module spec ModuleFlag mflags = ModuleFlag::None;
if ( check(TokType::Module_Export) )
{
mflags = ModuleFlag::Export;
eat( TokType::Module_Export );
}
eat( TokType::Decl_Union ); eat( TokType::Decl_Union );
// TODO : Parse attributes CodeAttributes attributes = parse_attributes( toks, context );
CodeAttributes attributes = { nullptr };
StrC name = { 0, nullptr }; StrC name = { 0, nullptr };
@ -6151,6 +6206,7 @@ CodeUnion parse_union( Parser::TokArray& toks, char const* context )
CodeUnion CodeUnion
result = (CodeUnion) make_code(); result = (CodeUnion) make_code();
result->Type = ECode::Union; result->Type = ECode::Union;
result->ModuleFlags = mflags;
if ( name ) if ( name )
result->Name = get_cached_string( name ); result->Name = get_cached_string( name );
@ -6190,7 +6246,14 @@ CodeUsing parse_using( Parser::TokArray& toks, char const* context )
bool is_namespace = false; bool is_namespace = false;
// TODO : Parse module specs ModuleFlag mflags = ModuleFlag::None;
CodeAttributes attributes = { nullptr };
if ( check(TokType::Module_Export) )
{
mflags = ModuleFlag::Export;
eat( TokType::Module_Export );
}
eat( TokType::Decl_Using ); eat( TokType::Decl_Using );
@ -6205,7 +6268,7 @@ CodeUsing parse_using( Parser::TokArray& toks, char const* context )
if ( currtok.IsAssign ) if ( currtok.IsAssign )
{ {
// TODO : Parse Attributes (using type-alias) attributes = parse_attributes( toks, context );
eat( TokType::Operator ); eat( TokType::Operator );
@ -6221,6 +6284,7 @@ CodeUsing parse_using( Parser::TokArray& toks, char const* context )
CodeUsing CodeUsing
result = (CodeUsing) make_code(); result = (CodeUsing) make_code();
result->Name = get_cached_string( name ); result->Name = get_cached_string( name );
result->ModuleFlags = mflags;
if ( is_namespace) if ( is_namespace)
{ {
@ -6235,6 +6299,9 @@ CodeUsing parse_using( Parser::TokArray& toks, char const* context )
if ( array_expr ) if ( array_expr )
type->ArrExpr = array_expr; type->ArrExpr = array_expr;
if ( attributes )
result->Attributes = attributes;
} }
return result; return result;
} }
@ -6261,12 +6328,17 @@ CodeVar parse_variable( Parser::TokArray& toks, char const* context )
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers }; SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
s32 num_specifiers = 0; s32 num_specifiers = 0;
ModuleFlag mflags = ModuleFlag::None;
CodeAttributes attributes = { nullptr }; CodeAttributes attributes = { nullptr };
CodeSpecifier specifiers = { nullptr }; CodeSpecifier specifiers = { nullptr };
// TODO : Parse module specifiers if ( check(TokType::Module_Export) )
{
mflags = ModuleFlag::Export;
eat( TokType::Module_Export );
}
// TODO : Parse attributes attributes = parse_attributes( toks, context );
while ( left && tok_is_specifier( currtok ) ) while ( left && tok_is_specifier( currtok ) )
{ {
@ -6314,7 +6386,7 @@ CodeVar parse_variable( Parser::TokArray& toks, char const* context )
name = currtok; name = currtok;
eat( TokType::Identifier ); eat( TokType::Identifier );
CodeVar result = parse_variable_after_name( ModuleFlag::None, attributes, specifiers, type, name, toks, context ); CodeVar result = parse_variable_after_name( mflags, attributes, specifiers, type, name, toks, context );
return result; return result;
} }

View File

@ -146,7 +146,7 @@ namespace gen {
// Bits // Bits
#define bit( Value ) ( 1 << (Value) ) #define bit( Value ) ( 1 << Value )
#define bitfield_is_equal( Type, Field, Mask ) ( (Type(Mask) & Type(Field)) == Type(Mask) ) #define bitfield_is_equal( Type, Field, Mask ) ( (Type(Mask) & Type(Field)) == Type(Mask) )
// Casting // Casting
@ -230,7 +230,7 @@ while(0);
#define size_of( x ) ( sw )( sizeof( x ) ) #define size_of( x ) ( sw )( sizeof( x ) )
template< class Type > template< class Type >
void swap( Type& a, Type& b ) void swap( Type a, Type b )
{ {
Type tmp = a; Type tmp = a;
a = b; a = b;
@ -1271,7 +1271,7 @@ struct Array
return true; return true;
} }
bool append_at( Type item, sw idx ) bool append_at( Type item, uw idx )
{ {
Header* header = get_header(); Header* header = get_header();
@ -1297,7 +1297,7 @@ struct Array
return true; return true;
} }
bool append_at( Type* items, uw item_num, sw idx ) bool append_at( Type* items, uw item_num, uw idx )
{ {
Header* header = get_header(); Header* header = get_header();
@ -1502,7 +1502,7 @@ struct HashTable
} }
static static
HashTable init_reserve( AllocatorInfo allocator, sw num ) HashTable init_reserve( AllocatorInfo allocator, uw num )
{ {
HashTable<Type> result = { { nullptr }, { nullptr } }; HashTable<Type> result = { { nullptr }, { nullptr } };

View File

@ -220,7 +220,11 @@ namespace ESpecifier
Entry( RValue, && ) \ Entry( RValue, && ) \
Entry( Static, static ) \ Entry( Static, static ) \
Entry( Thread_Local, thread_local ) \ Entry( Thread_Local, thread_local ) \
Entry( Volatile, volatile ) Entry( Volatile, volatile ) \
Entry( Virtual, virtual ) \
Entry( Const_Fn, const ) \
Entry( Final, final ) \
Entry( Override, override )
enum Type : u32 enum Type : u32
{ {
@ -333,40 +337,48 @@ ModuleFlag operator|( ModuleFlag A, ModuleFlag B)
/* /*
Predefined attributes Predefined attributes
Used for the parser constructors to identify non-standard attributes Used for the parser constructors to identify non-standard attributes
Override these to change the attribute to your own unique identifier convention.
The tokenizer identifies attribute defines with the GEN_Define_Attribute_Tokens macros.
See the example below and the Define_TokType macro used in gen.cpp to know the format.
While the library can parse raw attributes, most projects use defines to wrap them for compiler
platform indendence. The token define allows support for them without having to modify the library.
*/ */
namespace Attribute
{
#if defined(GEN_SYSTEM_WINDOWS) || defined( __CYGWIN__ ) #if defined(GEN_SYSTEM_WINDOWS) || defined( __CYGWIN__ )
# define GEN_API_ #ifndef GEN_Attribute_Keyword
# define GEN_API_Export_Code __declspec(dllexport) # define GEN_API_Export_Code __declspec(dllexport)
# define GEN_API_Import_Code __declspec(dllimport) # define GEN_API_Import_Code __declspec(dllimport)
# define GEN_Attribute_Keyword __declspec # define GEN_Attribute_Keyword __declspec
#endif
constexpr char const* API_Export = stringize( GEN_API_Export_Code ); constexpr char const* Attribute_Keyword = stringize( GEN_Attribute_Keyword);
constexpr char const* API_Import = stringize( GEN_API_Import_Code );
constexpr char const* Keyword = stringize( GEN_Attribute_Keyword);
#elif GEN_HAS_ATTRIBUTE( visibility ) || GEN_GCC_VERSION_CHECK( 3, 3, 0 ) #elif GEN_HAS_ATTRIBUTE( visibility ) || GEN_GCC_VERSION_CHECK( 3, 3, 0 )
#ifndef GEN_Attribute_Keyword
# define GEN_API_Export_Code __attribute__ ((visibility ("default"))) # define GEN_API_Export_Code __attribute__ ((visibility ("default")))
# define GEN_API_Import_Code __attribute__ ((visibility ("default"))) # define GEN_API_Import_Code __attribute__ ((visibility ("default")))
# define GEN_Attribute_Keyword __attribute__ # define GEN_Attribute_Keyword __attribute__
#endif
constexpr char const* API_Export = stringize( GEN_API_Export_Code ); constexpr char const* Attribute_Keyword = stringize( GEN_Attribute_Keyword );
constexpr char const* API_Import = stringize( GEN_API_Import_Code );
constexpr char const* Keyword = stringize( GEN_Attribute_Keyword);
#else #else
#ifndef GEN_Attribute_Keyword
# define GEN_API_Export_Code # define GEN_API_Export_Code
# define GEN_API_Import_Code # define GEN_API_Import_Code
# define GEN_Attribute_Keyword # define GEN_Attribute_Keyword
constexpr char const* API_Export = "";
constexpr char const* API_Import = "";
constexpr char const* Keyword = "";
#endif #endif
}
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
#pragma endregion Types #pragma endregion Types
#pragma region Data Structures #pragma region Data Structures
@ -629,7 +641,7 @@ struct AST_POD
union { union {
struct struct
{ {
AST* Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable AST* Attributes; // Class, Enum, Function, Struct, Typename, Union, Using, Variable
AST* Specs; // Function, Operator, Type symbol, Variable AST* Specs; // Function, Operator, Type symbol, Variable
union { union {
AST* ParentType; // Class, Struct AST* ParentType; // Class, Struct
@ -1254,10 +1266,9 @@ struct AST_Typedef
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ]; char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct struct
{ {
CodeAttributes Attributes;
char _PAD_SPECS_ [ sizeof(AST*) ];
Code UnderlyingType;
char _PAD_PROPERTIES_[ sizeof(AST*) * 2 ]; char _PAD_PROPERTIES_[ sizeof(AST*) * 2 ];
Code UnderlyingType;
char _PAD_PROPERTIES_2_[ sizeof(AST*) * 2 ];
}; };
}; };
Code Prev; Code Prev;
@ -1907,6 +1918,9 @@ namespace gen
extern CodeType t_class; extern CodeType t_class;
extern CodeType t_typename; extern CodeType t_typename;
extern Code attrib_api_export;
extern Code attrib_api_import;
extern Code access_public; extern Code access_public;
extern Code access_protected; extern Code access_protected;
extern Code access_private; extern Code access_private;

View File

@ -29,3 +29,4 @@ if ( $files )
{ {
Remove-Item $files Remove-Item $files
} }