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:
* `stdarg.h`
* `stddef.h`
* `stdio.h`
* `errno.h`
* `unistd.h` (Linux/Mac)
* `intrin.h` (Windows)
* `windows.h` (Windows)
* `errno.h` (gen.cpp)
* `stat.h` (gen.cpp)
* `stdarg.h` (gen.hpp)
* `stddef.h` (gen.hpp
* `stdio.h` (gen.cpp)
* `copyfile.h` (Mac, gen.cpp)
* `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).
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
* 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.
* Trailing specifiers ( postfix ) for functions (const, override, final)
* 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.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="test\gen\meson.build" />
<None Include="test\meson.build" />
<None Include="test\Readme.md" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="project\gen.dep.hpp" />
<ClInclude Include="project\gen.editor.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="test\DummyInclude.hpp" />
<ClInclude Include="test\gen\array.Upfront.gen.hpp" />
@ -119,7 +127,9 @@
<ClInclude Include="test\Parsed\Buffer.Parsed.hpp" />
<ClInclude Include="test\Parsed\HashTable.Parsed.hpp" />
<ClInclude Include="test\Parsed\Ring.Parsed.hpp" />
<ClInclude Include="test\parsing.hpp" />
<ClInclude Include="test\SOA.hpp" />
<ClInclude Include="test\upfront.hpp" />
<ClInclude Include="test\Upfront\Array.Upfront.hpp" />
<ClInclude Include="test\Upfront\Buffer.Upfront.hpp" />
<ClInclude Include="test\Upfront\HashTable.Upfront.hpp" />
@ -130,11 +140,17 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="project\gen.cpp" />
<ClCompile Include="project\gen.dep.cpp" />
<ClCompile Include="singleheader\gen\gen.singleheader.cpp" />
<ClCompile Include="test\gen\build\meson-private\sanitycheckc.c" />
<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.parsing.cpp" />
<ClCompile Include="test\test.Upfront.cpp" />
<ClCompile Include="test\upfront.cpp" />
</ItemGroup>
<ItemGroup>
<Natvis Include=".vscode\gencpp.natvis" />

View File

@ -33,6 +33,24 @@
<ClCompile Include="test\test.Upfront.cpp">
<Filter>Source Files</Filter>
</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>
<ClInclude Include="project\gen.hpp">
@ -92,6 +110,27 @@
<ClInclude Include="test\Parsed\Sanity.Parsed.hpp">
<Filter>Header Files</Filter>
</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>
<None Include=".editorconfig" />
@ -103,6 +142,9 @@
<None Include="test\gen\meson.build" />
<None Include="test\meson.build" />
<None Include="test\Readme.md" />
<None Include="scripts\gen.ps1" />
<None Include="scripts\genccp.natstepfilter" />
<None Include="scripts\gencpp.refactor" />
</ItemGroup>
<ItemGroup>
<Natvis Include=".vscode\gencpp.natvis" />

View File

@ -17,7 +17,7 @@
namespace gen {
#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 Array<Arena> Global_AllocatorBuckets;
@ -849,11 +849,6 @@ String AST::to_string()
result.append( "typedef ");
if ( Attributes )
{
result.append_fmt( "%s ", Attributes->to_string() );
}
result.append_fmt( "%s %s", UnderlyingType->to_string(), Name );
if ( UnderlyingType->Type == Typename && UnderlyingType->ArrExpr )
@ -2567,9 +2562,6 @@ CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes, Module
result->UnderlyingType = type;
if ( attributes )
result->Attributes = attributes;
return result;
}
@ -3307,77 +3299,83 @@ namespace Parser
It will not be capable of lexing C++ code with unsupported features.
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 \
Entry( Access_Private, "private" ) \
Entry( Access_Protected, "protected" ) \
Entry( Access_Public, "public" ) \
Entry( Access_MemberSymbol, "." ) \
Entry( Access_StaticSymbol, "::") \
Entry( Ampersand, "&" ) \
Entry( Ampersand_DBL, "&&" ) \
Entry( Assign_Classifer, ":" ) \
Entry( BraceCurly_Open, "{" ) \
Entry( BraceCurly_Close, "}" ) \
Entry( BraceSquare_Open, "[" ) \
Entry( BraceSquare_Close, "]" ) \
Entry( Capture_Start, "(" ) \
Entry( Capture_End, ")" ) \
Entry( Comment, "__comment__" ) \
Entry( Char, "__char__" ) \
Entry( Comma, "," ) \
Entry( Decl_Class, "class" ) \
Entry( Decl_Enum, "enum" ) \
Entry( Decl_Extern_Linkage, "extern" ) \
Entry( Decl_Friend, "friend" ) \
Entry( Decl_Module, "module" ) \
Entry( Decl_Namespace, "namespace" ) \
Entry( Decl_Operator, "operator" ) \
Entry( Decl_Struct, "struct" ) \
Entry( Decl_Template, "template" ) \
Entry( Decl_Typedef, "typedef" ) \
Entry( Decl_Using, "using" ) \
Entry( Decl_Union, "union" ) \
Entry( Identifier, "__identifier__" ) \
Entry( Module_Import, "import" ) \
Entry( Module_Export, "export" ) \
Entry( Number, "number" ) \
Entry( Operator, "operator" ) \
Entry( Preprocessor_Directive, "#") \
Entry( Preprocessor_Include, "include" ) \
Entry( Spec_Alignas, "alignas" ) \
Entry( Spec_Const, "const" ) \
Entry( Spec_Consteval, "consteval" ) \
Entry( Spec_Constexpr, "constexpr" ) \
Entry( Spec_Constinit, "constinit" ) \
Entry( Spec_Extern, "extern" ) \
Entry( Spec_Global, "global" ) \
Entry( Spec_Inline, "inline" ) \
Entry( Spec_Internal_Linkage, "internal" ) \
Entry( Spec_LocalPersist, "local_persist" ) \
Entry( Spec_Mutable, "mutable" ) \
Entry( Spec_Static, "static" ) \
Entry( Spec_ThreadLocal, "thread_local" ) \
Entry( Spec_Volatile, "volatile") \
Entry( Star, "*" ) \
Entry( Statement_End, ";" ) \
Entry( String, "__string__" ) \
Entry( Type_Unsigned, "unsigned" ) \
Entry( Type_Signed, "signed" ) \
Entry( Type_Short, "short" ) \
Entry( Type_Long, "long" ) \
Entry( Type_char, "char" ) \
Entry( Type_int, "int" ) \
Entry( Type_double, "double" )
Entry( Access_Private, "private" ) \
Entry( Access_Protected, "protected" ) \
Entry( Access_Public, "public" ) \
Entry( Access_MemberSymbol, "." ) \
Entry( Access_StaticSymbol, "::") \
Entry( Ampersand, "&" ) \
Entry( Ampersand_DBL, "&&" ) \
Entry( Assign_Classifer, ":" ) \
Entry( Attribute_Open, "[[" ) \
Entry( Attribute_Close, "]]" ) \
Entry( BraceCurly_Open, "{" ) \
Entry( BraceCurly_Close, "}" ) \
Entry( BraceSquare_Open, "[" ) \
Entry( BraceSquare_Close, "]" ) \
Entry( Capture_Start, "(" ) \
Entry( Capture_End, ")" ) \
Entry( Comment, "__comment__" ) \
Entry( Char, "__char__" ) \
Entry( Comma, "," ) \
Entry( Decl_Class, "class" ) \
Entry( Decl_GNU_Attribute, "__attribute__" ) \
Entry( Decl_MSVC_Attribute, "__declspec" ) \
Entry( Decl_Enum, "enum" ) \
Entry( Decl_Extern_Linkage, "extern" ) \
Entry( Decl_Friend, "friend" ) \
Entry( Decl_Module, "module" ) \
Entry( Decl_Namespace, "namespace" ) \
Entry( Decl_Operator, "operator" ) \
Entry( Decl_Struct, "struct" ) \
Entry( Decl_Template, "template" ) \
Entry( Decl_Typedef, "typedef" ) \
Entry( Decl_Using, "using" ) \
Entry( Decl_Union, "union" ) \
Entry( Identifier, "__identifier__" ) \
Entry( Module_Import, "import" ) \
Entry( Module_Export, "export" ) \
Entry( Number, "number" ) \
Entry( Operator, "operator" ) \
Entry( Preprocessor_Directive, "#") \
Entry( Preprocessor_Include, "include" ) \
Entry( Spec_Alignas, "alignas" ) \
Entry( Spec_Const, "const" ) \
Entry( Spec_Consteval, "consteval" ) \
Entry( Spec_Constexpr, "constexpr" ) \
Entry( Spec_Constinit, "constinit" ) \
Entry( Spec_Extern, "extern" ) \
Entry( Spec_Global, "global" ) \
Entry( Spec_Inline, "inline" ) \
Entry( Spec_Internal_Linkage, "internal" ) \
Entry( Spec_LocalPersist, "local_persist" ) \
Entry( Spec_Mutable, "mutable" ) \
Entry( Spec_Static, "static" ) \
Entry( Spec_ThreadLocal, "thread_local" ) \
Entry( Spec_Volatile, "volatile") \
Entry( Star, "*" ) \
Entry( Statement_End, ";" ) \
Entry( String, "__string__" ) \
Entry( Type_Unsigned, "unsigned" ) \
Entry( Type_Signed, "signed" ) \
Entry( Type_Short, "short" ) \
Entry( Type_Long, "long" ) \
Entry( Type_char, "char" ) \
Entry( Type_int, "int" ) \
Entry( Type_double, "double" ) \
Entry( Attributes_Start, "__attrib_start__" )
enum class TokType : u32
{
# define Entry( Name_, Str_ ) Name_,
Define_TokType
GEN_Define_Attribute_Tokens
# undef Entry
Attr_Keyword,
Num,
Invalid
};
@ -3408,9 +3406,8 @@ namespace Parser
{
# define Entry( Name_, Str_ ) { sizeof(Str_), Str_ },
Define_TokType
GEN_Define_Attribute_Tokens
# undef Entry
{ sizeof(Attribute::Keyword), Attribute::Keyword },
};
for ( u32 index = 0; index < (u32)TokType::Num; index++ )
@ -3436,9 +3433,8 @@ namespace Parser
{
# define Entry( Name_, Str_ ) Str_,
Define_TokType
GEN_Define_Attribute_Tokens
# undef Entry
Attribute::Keyword,
};
return lookup[(u32)type];
@ -3467,6 +3463,11 @@ namespace Parser
return scast(AccessSpec, tok.Type);
}
internal inline
bool tok_is_attribute( Token const& tok )
{
return tok.Type > TokType::Attributes_Start;
}
struct TokArray
{
@ -4108,6 +4109,68 @@ Code parse_array_decl( Parser::TokArray& toks, char const* context )
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
Parser::Token parse_identifier( Parser::TokArray& toks, char const* context )
{
@ -4288,7 +4351,7 @@ CodeParam parse_params( Parser::TokArray& toks, char const* context, bool use_te
// Function parsing is handled in multiple places because its initial signature is shared with variable parsing
internal inline
CodeFn parse_function_after_name(
ModuleFlag mflags
ModuleFlag mflags
, CodeAttributes attributes
, CodeSpecifier specifiers
, CodeType ret_type
@ -4711,7 +4774,7 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes
{
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;
}
@ -4809,36 +4872,14 @@ CodeBody parse_class_struct_body( Parser::TokType which, Parser::TokArray& toks,
member = parse_using( toks, context );
break;
case TokType::BraceSquare_Open:
case TokType::Attr_Keyword:
case TokType::Attribute_Open:
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
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 );
attributes = parse_attributes( toks, context );
}
//! Fallthrough intended
case TokType::Spec_Consteval:
@ -4943,11 +4984,15 @@ Code parse_class_struct( Parser::TokType which, Parser::TokArray& toks, char con
CodeClass result = CodeInvalid;
// TODO : Parse module specifiers
if ( check(TokType::Module_Export) )
{
mflags = ModuleFlag::Export;
eat( TokType::Module_Export );
}
eat( which );
// TODO : Parse attributes
attributes = parse_attributes( toks, context );
if ( check( TokType::Identifier ) )
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 )
result = def_class( name, body, parent, access
// TODO : Set these up later
, NoCode // Attributes
, ModuleFlag::None
, attributes
, mflags
);
else
result = def_struct( name, body, (CodeType)parent, access
// TODO : Set these up later
, NoCode // Attributes
, ModuleFlag::None
, attributes
, mflags
);
return result;
@ -5115,38 +5158,13 @@ CodeBody parse_global_nspace( CodeT which, Parser::TokArray& toks, char const* c
not_implemented( context );
}
//! Fallthrough intentional
case TokType::BraceSquare_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
{
not_implemented( 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 );
attributes = parse_attributes( toks, context );
}
//! Fallthrough intentional
case TokType::Spec_Consteval:
@ -5494,10 +5512,15 @@ CodeFn parse_functon( Parser::TokArray& toks, char const* context )
CodeAttributes attributes = { 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 ) )
{
@ -5536,7 +5559,7 @@ CodeFn parse_functon( Parser::TokArray& toks, char const* context )
if ( ! name )
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;
}
@ -5603,16 +5626,23 @@ CodeNamespace parse_namespace( StrC def )
internal
CodeOperator parse_operator( Parser::TokArray& toks, char const* context )
{
// TODO : Parse Module specifier
using namespace Parser;
// TODO : Parse Attributes
CodeAttributes attributes = { nullptr };
CodeSpecifier specifiers = { nullptr };
CodeSpecifier specifiers = { nullptr };
ModuleFlag mflags = ModuleFlag::None;
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
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 ) )
{
SpecifierT spec = ESpecifier::to_type( currtok );
@ -5643,7 +5673,7 @@ CodeOperator parse_operator( Parser::TokArray& toks, char const* context )
// Parse Return Type
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;
}
@ -5751,7 +5781,13 @@ CodeTemplate parse_template( Parser::TokArray& toks, char const* context )
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 );
@ -5784,17 +5820,16 @@ CodeTemplate parse_template( Parser::TokArray& toks, char const* context )
// Its either a function or a variable
Token name = { nullptr, 0, TokType::Invalid };
CodeAttributes attributes = { nullptr };
CodeSpecifier specifiers = { nullptr };
// TODO : Parse attributes
CodeAttributes attributes = { nullptr };
CodeSpecifier specifiers = { nullptr };
bool expects_function = false;
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
s32 num_specifiers = 0;
attributes = parse_attributes( toks, stringize(parse_template) );
while ( left && tok_is_specifier( 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->Params = params;
result->Declaration = definition;
result->ModuleFlags = mflags;
return result;
# undef UseTemplateCapture
@ -5876,6 +5912,8 @@ 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 );
while ( left && tok_is_specifier( 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 );
if ( attributes )
result->Attributes = attributes;
return result;
}
@ -6056,6 +6097,14 @@ CodeTypedef parse_typedef( Parser::TokArray& toks, char const* context )
Code array_expr = { nullptr };
Code type = { nullptr };
ModuleFlag mflags = ModuleFlag::None;
if ( check(TokType::Module_Export) )
{
mflags = ModuleFlag::Export;
eat( TokType::Module_Export );
}
eat( TokType::Decl_Typedef );
if ( check( TokType::Decl_Enum ) )
@ -6086,9 +6135,10 @@ CodeTypedef parse_typedef( Parser::TokArray& toks, char const* context )
using namespace ECode;
CodeTypedef
result = (CodeTypedef) make_code();
result->Type = Typedef;
result->Name = get_cached_string( name );
result = (CodeTypedef) make_code();
result->Type = Typedef;
result->Name = get_cached_string( name );
result->ModuleFlags = mflags;
result->UnderlyingType = type;
@ -6115,12 +6165,17 @@ CodeUnion parse_union( Parser::TokArray& toks, char const* context )
{
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 );
// TODO : Parse attributes
CodeAttributes attributes = { nullptr };
CodeAttributes attributes = parse_attributes( toks, context );
StrC name = { 0, nullptr };
@ -6150,7 +6205,8 @@ CodeUnion parse_union( Parser::TokArray& toks, char const* context )
CodeUnion
result = (CodeUnion) make_code();
result->Type = ECode::Union;
result->Type = ECode::Union;
result->ModuleFlags = mflags;
if ( name )
result->Name = get_cached_string( name );
@ -6190,7 +6246,14 @@ CodeUsing parse_using( Parser::TokArray& toks, char const* context )
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 );
@ -6205,7 +6268,7 @@ CodeUsing parse_using( Parser::TokArray& toks, char const* context )
if ( currtok.IsAssign )
{
// TODO : Parse Attributes (using type-alias)
attributes = parse_attributes( toks, context );
eat( TokType::Operator );
@ -6219,8 +6282,9 @@ CodeUsing parse_using( Parser::TokArray& toks, char const* context )
using namespace ECode;
CodeUsing
result = (CodeUsing) make_code();
result->Name = get_cached_string( name );
result = (CodeUsing) make_code();
result->Name = get_cached_string( name );
result->ModuleFlags = mflags;
if ( is_namespace)
{
@ -6235,6 +6299,9 @@ CodeUsing parse_using( Parser::TokArray& toks, char const* context )
if ( array_expr )
type->ArrExpr = array_expr;
if ( attributes )
result->Attributes = attributes;
}
return result;
}
@ -6261,12 +6328,17 @@ CodeVar parse_variable( Parser::TokArray& toks, char const* context )
SpecifierT specs_found[16] { ESpecifier::Num_Specifiers };
s32 num_specifiers = 0;
ModuleFlag mflags = ModuleFlag::None;
CodeAttributes attributes = { 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 ) )
{
@ -6314,7 +6386,7 @@ CodeVar parse_variable( Parser::TokArray& toks, char const* context )
name = currtok;
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;
}

View File

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

View File

@ -220,7 +220,11 @@ namespace ESpecifier
Entry( RValue, && ) \
Entry( Static, static ) \
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
{
@ -333,40 +337,48 @@ ModuleFlag operator|( ModuleFlag A, ModuleFlag B)
/*
Predefined 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__ )
# define GEN_API_
#ifndef GEN_Attribute_Keyword
# define GEN_API_Export_Code __declspec(dllexport)
# define GEN_API_Import_Code __declspec(dllimport)
# define GEN_Attribute_Keyword __declspec
#endif
constexpr char const* API_Export = stringize( GEN_API_Export_Code );
constexpr char const* API_Import = stringize( GEN_API_Import_Code );
constexpr char const* Keyword = stringize( GEN_Attribute_Keyword);
constexpr char const* Attribute_Keyword = stringize( GEN_Attribute_Keyword);
#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_Import_Code __attribute__ ((visibility ("default")))
# define GEN_Attribute_Keyword __attribute__
#endif
constexpr char const* API_Export = stringize( GEN_API_Export_Code );
constexpr char const* API_Import = stringize( GEN_API_Import_Code );
constexpr char const* Keyword = stringize( GEN_Attribute_Keyword);
constexpr char const* Attribute_Keyword = stringize( GEN_Attribute_Keyword );
#else
#ifndef GEN_Attribute_Keyword
# define GEN_API_Export_Code
# define GEN_API_Import_Code
# define GEN_Attribute_Keyword
constexpr char const* API_Export = "";
constexpr char const* API_Import = "";
constexpr char const* Keyword = "";
#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 region Data Structures
@ -629,7 +641,7 @@ struct AST_POD
union {
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
union {
AST* ParentType; // Class, Struct
@ -1254,10 +1266,9 @@ struct AST_Typedef
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
CodeAttributes Attributes;
char _PAD_SPECS_ [ sizeof(AST*) ];
Code UnderlyingType;
char _PAD_PROPERTIES_[ sizeof(AST*) * 2 ];
Code UnderlyingType;
char _PAD_PROPERTIES_2_[ sizeof(AST*) * 2 ];
};
};
Code Prev;
@ -1886,7 +1897,7 @@ namespace gen
// NOTE: This limits the maximum size of an allocation
// If you are generating a string larger than this, increase the size of the bucket here.
constexpr uw Global_BucketSize = megabytes(10);
constexpr uw Global_BucketSize = megabytes(10);
constexpr s32 CodePool_NumBlocks = kilobytes(64);
constexpr s32 SizePer_StringArena = megabytes(1);
@ -1907,6 +1918,9 @@ namespace gen
extern CodeType t_class;
extern CodeType t_typename;
extern Code attrib_api_export;
extern Code attrib_api_import;
extern Code access_public;
extern Code access_protected;
extern Code access_private;

View File

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