diff --git a/Readme.md b/Readme.md
index fbab641..2f09e76 100644
--- a/Readme.md
+++ b/Readme.md
@@ -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.
diff --git a/gencpp.10x b/gencpp.10x
new file mode 100644
index 0000000..035c4fc
--- /dev/null
+++ b/gencpp.10x
@@ -0,0 +1,45 @@
+
+
+
+ *.*
+ *.obj,*.lib,*.pch,*.dll,*.pdb,.vs,Debug,Release,x64,obj,*.user,Intermediate
+ true
+ true
+ true
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+ Debug
+ Release
+
+
+ x64
+
+
+ C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.36.32532\include
+ C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.36.32532\ATLMFC\include
+ C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\VS\include
+ C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt
+ C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\um
+ C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\shared
+ C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\winrt
+ C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\cppwinrt
+ C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um
+
+
+
+
+
+
diff --git a/gencpp.vcxproj b/gencpp.vcxproj
index 7aea798..f6ec0cb 100644
--- a/gencpp.vcxproj
+++ b/gencpp.vcxproj
@@ -102,13 +102,21 @@
+
+
+
+
+
+
+
+
@@ -119,7 +127,9 @@
+
+
@@ -130,11 +140,17 @@
+
+
+
+
+
+
diff --git a/gencpp.vcxproj.filters b/gencpp.vcxproj.filters
index c21cf77..811419a 100644
--- a/gencpp.vcxproj.filters
+++ b/gencpp.vcxproj.filters
@@ -33,6 +33,24 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
@@ -92,6 +110,27 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
@@ -103,6 +142,9 @@
+
+
+
diff --git a/project/gen.cpp b/project/gen.cpp
index 42c281b..f1d4318 100644
--- a/project/gen.cpp
+++ b/project/gen.cpp
@@ -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 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;
}
diff --git a/project/gen.dep.hpp b/project/gen.dep.hpp
index 933bdeb..56826bd 100644
--- a/project/gen.dep.hpp
+++ b/project/gen.dep.hpp
@@ -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 result = { { nullptr }, { nullptr } };
diff --git a/project/gen.hpp b/project/gen.hpp
index 81944ac..2a32513 100644
--- a/project/gen.hpp
+++ b/project/gen.hpp
@@ -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;
diff --git a/scripts/clean.ps1 b/scripts/clean.ps1
index 7155f7f..daec07f 100644
--- a/scripts/clean.ps1
+++ b/scripts/clean.ps1
@@ -29,3 +29,4 @@ if ( $files )
{
Remove-Item $files
}
+