mirror of
https://github.com/Ed94/gencpp.git
synced 2024-12-22 07:44:45 -08:00
Naive preprocessor support initial implementation (compiles and runs, not heavily tested)
This commit is contained in:
parent
3d7cb85e71
commit
bfbfae466f
@ -8,12 +8,6 @@ These build up a code AST to then serialize with a file builder.
|
|||||||
This code base attempts follow the [handmade philosophy](https://handmade.network/manifesto),
|
This code base attempts follow the [handmade philosophy](https://handmade.network/manifesto),
|
||||||
its not meant to be a black box metaprogramming utility, its meant for the user to extend for their project domain.
|
its not meant to be a black box metaprogramming utility, its meant for the user to extend for their project domain.
|
||||||
|
|
||||||
### TOC
|
|
||||||
|
|
||||||
* [Notes](#notes)
|
|
||||||
* [Usage](#usage)
|
|
||||||
* [Building](#building)
|
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
The project has reached an *alpha* state, all the current functionality works for the test cases but it will most likely break in many other cases.
|
The project has reached an *alpha* state, all the current functionality works for the test cases but it will most likely break in many other cases.
|
||||||
|
@ -5,8 +5,7 @@ This parser does not, and should not do the compiler's job. By only supporting t
|
|||||||
|
|
||||||
|
|
||||||
Everything is done in one pass for both the preprocessor directives and the rest of the language.
|
Everything is done in one pass for both the preprocessor directives and the rest of the language.
|
||||||
The parser performs no macro expansion as the scope of gencpp feature-set is to only support the preprocessor for the goal of having rudimentary awareness of preprocessor ***conditionals***, ***defines***, and ***includes***.
|
The parser performs no macro expansion as the scope of gencpp feature-set is to only support the preprocessor for the goal of having rudimentary awareness of preprocessor ***conditionals***, ***defines***, and ***includes***, and ***`pragmas`**.
|
||||||
*(Conditionals and defines are a TODO)*
|
|
||||||
|
|
||||||
The keywords supported for the preprocessor are:
|
The keywords supported for the preprocessor are:
|
||||||
|
|
||||||
@ -17,8 +16,9 @@ The keywords supported for the preprocessor are:
|
|||||||
* elif
|
* elif
|
||||||
* endif
|
* endif
|
||||||
* undef
|
* undef
|
||||||
|
* pragma
|
||||||
|
|
||||||
Just like with actual preprocessor, each directive # line is considered one preproecessor unit, and will be treated as one Preprocessor AST. *These ASTs will be considered members or entries of braced scope they reside within*.
|
Each directive `#` line is considered one preproecessor unit, and will be treated as one Preprocessor AST. *These ASTs will be considered members or entries of braced scope they reside within*.
|
||||||
All keywords except *include* are suppported as members of a scope for a class/struct, global, or namespace body.
|
All keywords except *include* are suppported as members of a scope for a class/struct, global, or namespace body.
|
||||||
|
|
||||||
Any preprocessor definition abuse that changes the syntax of the core language is unsupported and will fail to parse if not kept within an execution scope (function body, or expression assignment).
|
Any preprocessor definition abuse that changes the syntax of the core language is unsupported and will fail to parse if not kept within an execution scope (function body, or expression assignment).
|
||||||
|
@ -42,6 +42,7 @@ Otherwise the library is free of any templates.
|
|||||||
|
|
||||||
* Execution statement validation : Execution expressions are defined using the untyped AST.
|
* Execution statement validation : Execution expressions are defined using the untyped AST.
|
||||||
* Lambdas (This naturally means its unsupported)
|
* Lambdas (This naturally means its unsupported)
|
||||||
|
* Non-trivial template validation support.
|
||||||
* RAII : This needs support for constructors/destructor parsing
|
* RAII : This needs support for constructors/destructor parsing
|
||||||
* Haven't gotten around to yet (its in the github issues)
|
* Haven't gotten around to yet (its in the github issues)
|
||||||
|
|
||||||
|
0
docs/Upfront.md
Normal file
0
docs/Upfront.md
Normal file
@ -8,8 +8,8 @@
|
|||||||
<ShowEmptyFolders>true</ShowEmptyFolders>
|
<ShowEmptyFolders>true</ShowEmptyFolders>
|
||||||
<IsVirtual>false</IsVirtual>
|
<IsVirtual>false</IsVirtual>
|
||||||
<IsFolder>false</IsFolder>
|
<IsFolder>false</IsFolder>
|
||||||
<BuildCommand>powershell ./scripts/build.ps1</BuildCommand>
|
<BuildCommand>powershell ./scripts/test.gen_run.ps1</BuildCommand>
|
||||||
<RebuildCommand>powershell ./scripts/rebuild.ps1</RebuildCommand>
|
<RebuildCommand></RebuildCommand>
|
||||||
<BuildFileCommand></BuildFileCommand>
|
<BuildFileCommand></BuildFileCommand>
|
||||||
<CleanCommand>powershell ./scripts/clean.ps1</CleanCommand>
|
<CleanCommand>powershell ./scripts/clean.ps1</CleanCommand>
|
||||||
<BuildWorkingDirectory></BuildWorkingDirectory>
|
<BuildWorkingDirectory></BuildWorkingDirectory>
|
||||||
@ -38,7 +38,9 @@
|
|||||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\cppwinrt</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>
|
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um</AdditionalIncludePath>
|
||||||
</AdditionalIncludePaths>
|
</AdditionalIncludePaths>
|
||||||
<Defines></Defines>
|
<Defines>
|
||||||
|
<Define>GEN_TIME</Define>
|
||||||
|
</Defines>
|
||||||
<ConfigProperties>
|
<ConfigProperties>
|
||||||
<ConfigAndPlatform>
|
<ConfigAndPlatform>
|
||||||
<Name>Debug:x64</Name>
|
<Name>Debug:x64</Name>
|
||||||
|
@ -489,8 +489,40 @@ String AST::to_string()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Preprocessor_Include:
|
case Preprocess_Define:
|
||||||
result.append_fmt( "#include \"%s\"", Name );
|
result.append_fmt( "#define %s %s", Name, Content );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Preprocess_If:
|
||||||
|
result.append_fmt( "#if %s", Content );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Preprocess_IfDef:
|
||||||
|
result.append_fmt( "#ifdef %s", Content );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Preprocess_IfNotDef:
|
||||||
|
result.append_fmt( "#ifndef %s", Content );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Preprocess_Include:
|
||||||
|
result.append_fmt( "#include \"%s\"", Content );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Preprocess_ElIf:
|
||||||
|
result.append_fmt( "#elif %s", Content );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Preprocess_Else:
|
||||||
|
result.append_fmt( "#else" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Preprocess_EndIf:
|
||||||
|
result.append_fmt( "#endif" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Preprocess_Pragma:
|
||||||
|
result.append_fmt( "#pragma %s", Content );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Specifiers:
|
case Specifiers:
|
||||||
|
@ -12,6 +12,7 @@ struct AST_Body;
|
|||||||
struct AST_Attributes;
|
struct AST_Attributes;
|
||||||
struct AST_Comment;
|
struct AST_Comment;
|
||||||
struct AST_Class;
|
struct AST_Class;
|
||||||
|
struct AST_Define;
|
||||||
struct AST_Enum;
|
struct AST_Enum;
|
||||||
struct AST_Exec;
|
struct AST_Exec;
|
||||||
struct AST_Extern;
|
struct AST_Extern;
|
||||||
@ -23,6 +24,8 @@ struct AST_Namespace;
|
|||||||
struct AST_Operator;
|
struct AST_Operator;
|
||||||
struct AST_OpCast;
|
struct AST_OpCast;
|
||||||
struct AST_Param;
|
struct AST_Param;
|
||||||
|
struct AST_Pragma;
|
||||||
|
struct AST_PreprocessCond;
|
||||||
struct AST_Specifiers;
|
struct AST_Specifiers;
|
||||||
struct AST_Struct;
|
struct AST_Struct;
|
||||||
struct AST_Template;
|
struct AST_Template;
|
||||||
@ -38,6 +41,7 @@ struct CodeBody;
|
|||||||
struct CodeAttributes;
|
struct CodeAttributes;
|
||||||
struct CodeComment;
|
struct CodeComment;
|
||||||
struct CodeClass;
|
struct CodeClass;
|
||||||
|
struct CodeDefine;
|
||||||
struct CodeEnum;
|
struct CodeEnum;
|
||||||
struct CodeExec;
|
struct CodeExec;
|
||||||
struct CodeExtern;
|
struct CodeExtern;
|
||||||
@ -49,6 +53,8 @@ struct CodeNamespace;
|
|||||||
struct CodeOperator;
|
struct CodeOperator;
|
||||||
struct CodeOpCast;
|
struct CodeOpCast;
|
||||||
struct CodeParam;
|
struct CodeParam;
|
||||||
|
struct CodePreprocessCond;
|
||||||
|
struct CodePragma;
|
||||||
struct CodeSpecifiers;
|
struct CodeSpecifiers;
|
||||||
struct CodeStruct;
|
struct CodeStruct;
|
||||||
struct CodeTemplate;
|
struct CodeTemplate;
|
||||||
@ -115,6 +121,7 @@ struct Code
|
|||||||
operator CodeAttributes() const;
|
operator CodeAttributes() const;
|
||||||
operator CodeComment() const;
|
operator CodeComment() const;
|
||||||
operator CodeClass() const;
|
operator CodeClass() const;
|
||||||
|
operator CodeDefine() const;
|
||||||
operator CodeExec() const;
|
operator CodeExec() const;
|
||||||
operator CodeEnum() const;
|
operator CodeEnum() const;
|
||||||
operator CodeExtern() const;
|
operator CodeExtern() const;
|
||||||
@ -126,6 +133,8 @@ struct Code
|
|||||||
operator CodeOperator() const;
|
operator CodeOperator() const;
|
||||||
operator CodeOpCast() const;
|
operator CodeOpCast() const;
|
||||||
operator CodeParam() const;
|
operator CodeParam() const;
|
||||||
|
operator CodePragma() const;
|
||||||
|
operator CodePreprocessCond() const;
|
||||||
operator CodeSpecifiers() const;
|
operator CodeSpecifiers() const;
|
||||||
operator CodeStruct() const;
|
operator CodeStruct() const;
|
||||||
operator CodeTemplate() const;
|
operator CodeTemplate() const;
|
||||||
@ -175,6 +184,7 @@ struct AST
|
|||||||
operator CodeAttributes();
|
operator CodeAttributes();
|
||||||
operator CodeComment();
|
operator CodeComment();
|
||||||
operator CodeClass();
|
operator CodeClass();
|
||||||
|
operator CodeDefine();
|
||||||
operator CodeEnum();
|
operator CodeEnum();
|
||||||
operator CodeExec();
|
operator CodeExec();
|
||||||
operator CodeExtern();
|
operator CodeExtern();
|
||||||
@ -186,6 +196,8 @@ struct AST
|
|||||||
operator CodeOperator();
|
operator CodeOperator();
|
||||||
operator CodeOpCast();
|
operator CodeOpCast();
|
||||||
operator CodeParam();
|
operator CodeParam();
|
||||||
|
operator CodePragma();
|
||||||
|
operator CodePreprocessCond();
|
||||||
operator CodeSpecifiers();
|
operator CodeSpecifiers();
|
||||||
operator CodeStruct();
|
operator CodeStruct();
|
||||||
operator CodeTemplate();
|
operator CodeTemplate();
|
||||||
@ -378,6 +390,7 @@ struct CodeBody
|
|||||||
|
|
||||||
Define_CodeType( Attributes );
|
Define_CodeType( Attributes );
|
||||||
Define_CodeType( Comment );
|
Define_CodeType( Comment );
|
||||||
|
Define_CodeType( Define );
|
||||||
Define_CodeType( Enum );
|
Define_CodeType( Enum );
|
||||||
Define_CodeType( Exec );
|
Define_CodeType( Exec );
|
||||||
Define_CodeType( Extern );
|
Define_CodeType( Extern );
|
||||||
@ -388,6 +401,8 @@ Define_CodeType( Module );
|
|||||||
Define_CodeType( Namespace );
|
Define_CodeType( Namespace );
|
||||||
Define_CodeType( Operator );
|
Define_CodeType( Operator );
|
||||||
Define_CodeType( OpCast );
|
Define_CodeType( OpCast );
|
||||||
|
Define_CodeType( Pragma );
|
||||||
|
Define_CodeType( PreprocessCond );
|
||||||
Define_CodeType( Template );
|
Define_CodeType( Template );
|
||||||
Define_CodeType( Type );
|
Define_CodeType( Type );
|
||||||
Define_CodeType( Typedef );
|
Define_CodeType( Typedef );
|
||||||
@ -631,6 +646,21 @@ struct AST_Class
|
|||||||
};
|
};
|
||||||
static_assert( sizeof(AST_Class) == sizeof(AST), "ERROR: AST_Class is not the same size as AST");
|
static_assert( sizeof(AST_Class) == sizeof(AST), "ERROR: AST_Class is not the same size as AST");
|
||||||
|
|
||||||
|
struct AST_Define
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
|
||||||
|
StringCached Content;
|
||||||
|
};
|
||||||
|
Code Prev;
|
||||||
|
Code Next;
|
||||||
|
Code Parent;
|
||||||
|
StringCached Name;
|
||||||
|
CodeT Type;
|
||||||
|
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
|
||||||
|
};
|
||||||
|
static_assert( sizeof(AST_Define) == sizeof(AST), "ERROR: AST_Define is not the same size as AST");
|
||||||
|
|
||||||
struct AST_Enum
|
struct AST_Enum
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
@ -847,6 +877,36 @@ struct AST_Param
|
|||||||
};
|
};
|
||||||
static_assert( sizeof(AST_Param) == sizeof(AST), "ERROR: AST_Param is not the same size as AST");
|
static_assert( sizeof(AST_Param) == sizeof(AST), "ERROR: AST_Param is not the same size as AST");
|
||||||
|
|
||||||
|
struct AST_Pragma
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
|
||||||
|
StringCached Content;
|
||||||
|
};
|
||||||
|
Code Prev;
|
||||||
|
Code Next;
|
||||||
|
Code Parent;
|
||||||
|
StringCached Name;
|
||||||
|
CodeT Type;
|
||||||
|
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
|
||||||
|
};
|
||||||
|
static_assert( sizeof(AST_Pragma) == sizeof(AST), "ERROR: AST_Pragma is not the same size as AST");
|
||||||
|
|
||||||
|
struct AST_PreprocessCond
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
|
||||||
|
StringCached Content;
|
||||||
|
};
|
||||||
|
Code Prev;
|
||||||
|
Code Next;
|
||||||
|
Code Parent;
|
||||||
|
StringCached Name;
|
||||||
|
CodeT Type;
|
||||||
|
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
|
||||||
|
};
|
||||||
|
static_assert( sizeof(AST_PreprocessCond) == sizeof(AST), "ERROR: AST_PreprocessCond is not the same size as AST");
|
||||||
|
|
||||||
struct AST_Specifiers
|
struct AST_Specifiers
|
||||||
{
|
{
|
||||||
SpecifierT ArrSpecs[ AST::ArrSpecs_Cap ];
|
SpecifierT ArrSpecs[ AST::ArrSpecs_Cap ];
|
||||||
|
@ -37,7 +37,15 @@ namespace ECode
|
|||||||
Entry( Operator_Cast ) \
|
Entry( Operator_Cast ) \
|
||||||
Entry( Operator_Cast_Fwd ) \
|
Entry( Operator_Cast_Fwd ) \
|
||||||
Entry( Parameters ) \
|
Entry( Parameters ) \
|
||||||
Entry( Preprocessor_Include ) \
|
Entry( Preprocess_Define ) \
|
||||||
|
Entry( Preprocess_If ) \
|
||||||
|
Entry( Preprocess_IfDef ) \
|
||||||
|
Entry( Preprocess_IfNotDef ) \
|
||||||
|
Entry( Preprocess_ElIf ) \
|
||||||
|
Entry( Preprocess_Else ) \
|
||||||
|
Entry( Preprocess_EndIf ) \
|
||||||
|
Entry( Preprocess_Include ) \
|
||||||
|
Entry( Preprocess_Pragma ) \
|
||||||
Entry( Specifiers ) \
|
Entry( Specifiers ) \
|
||||||
Entry( Struct ) \
|
Entry( Struct ) \
|
||||||
Entry( Struct_Fwd ) \
|
Entry( Struct_Fwd ) \
|
||||||
|
@ -15,7 +15,7 @@ namespace Parser
|
|||||||
Entry( API_Import, "GEN_API_Import_Code" )
|
Entry( API_Import, "GEN_API_Import_Code" )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# define Define_TokType \
|
# define Define_TokType \
|
||||||
Entry( Invalid, "INVALID" ) \
|
Entry( Invalid, "INVALID" ) \
|
||||||
Entry( Access_Private, "private" ) \
|
Entry( Access_Private, "private" ) \
|
||||||
Entry( Access_Protected, "protected" ) \
|
Entry( Access_Protected, "protected" ) \
|
||||||
@ -37,7 +37,7 @@ namespace Parser
|
|||||||
Entry( Char, "character" ) \
|
Entry( Char, "character" ) \
|
||||||
Entry( Comma, "," ) \
|
Entry( Comma, "," ) \
|
||||||
Entry( Decl_Class, "class" ) \
|
Entry( Decl_Class, "class" ) \
|
||||||
Entry( Decl_GNU_Attribute, "__attribute__" ) \
|
Entry( Decl_GNU_Attribute, "__attribute__" ) \
|
||||||
Entry( Decl_MSVC_Attribute, "__declspec" ) \
|
Entry( Decl_MSVC_Attribute, "__declspec" ) \
|
||||||
Entry( Decl_Enum, "enum" ) \
|
Entry( Decl_Enum, "enum" ) \
|
||||||
Entry( Decl_Extern_Linkage, "extern" ) \
|
Entry( Decl_Extern_Linkage, "extern" ) \
|
||||||
@ -56,11 +56,15 @@ namespace Parser
|
|||||||
Entry( Number, "number" ) \
|
Entry( Number, "number" ) \
|
||||||
Entry( Operator, "operator" ) \
|
Entry( Operator, "operator" ) \
|
||||||
Entry( Preprocess_Define, "#define") \
|
Entry( Preprocess_Define, "#define") \
|
||||||
Entry( Preproces_Include, "include" ) \
|
Entry( Preprocess_Include, "include" ) \
|
||||||
Entry( Preprocess_If, "#if") \
|
Entry( Preprocess_If, "#if") \
|
||||||
Entry( Preprocess_Elif, "#elif") \
|
Entry( Preprocess_IfDef, "#if") \
|
||||||
|
Entry( Preprocess_IfNotDef, "#ifndef") \
|
||||||
|
Entry( Preprocess_ElIf, "#elif") \
|
||||||
Entry( Preprocess_Else, "#else") \
|
Entry( Preprocess_Else, "#else") \
|
||||||
Entry( Preprocess_EndIf, "#endif") \
|
Entry( Preprocess_EndIf, "#endif") \
|
||||||
|
Entry( Preprocess_Pragma, "#pragma") \
|
||||||
|
Entry( Preprocess_Content, "macro content") \
|
||||||
Entry( Spec_Alignas, "alignas" ) \
|
Entry( Spec_Alignas, "alignas" ) \
|
||||||
Entry( Spec_Const, "const" ) \
|
Entry( Spec_Const, "const" ) \
|
||||||
Entry( Spec_Consteval, "consteval" ) \
|
Entry( Spec_Consteval, "consteval" ) \
|
||||||
|
@ -162,6 +162,7 @@ Define_CodeImpl( CodeBody );
|
|||||||
Define_CodeImpl( CodeAttributes );
|
Define_CodeImpl( CodeAttributes );
|
||||||
Define_CodeImpl( CodeComment );
|
Define_CodeImpl( CodeComment );
|
||||||
Define_CodeImpl( CodeClass );
|
Define_CodeImpl( CodeClass );
|
||||||
|
Define_CodeImpl( CodeDefine );
|
||||||
Define_CodeImpl( CodeEnum );
|
Define_CodeImpl( CodeEnum );
|
||||||
Define_CodeImpl( CodeExec );
|
Define_CodeImpl( CodeExec );
|
||||||
Define_CodeImpl( CodeExtern );
|
Define_CodeImpl( CodeExtern );
|
||||||
@ -173,6 +174,8 @@ Define_CodeImpl( CodeNamespace );
|
|||||||
Define_CodeImpl( CodeOperator );
|
Define_CodeImpl( CodeOperator );
|
||||||
Define_CodeImpl( CodeOpCast );
|
Define_CodeImpl( CodeOpCast );
|
||||||
Define_CodeImpl( CodeParam );
|
Define_CodeImpl( CodeParam );
|
||||||
|
Define_CodeImpl( CodePragma );
|
||||||
|
Define_CodeImpl( CodePreprocessCond );
|
||||||
Define_CodeImpl( CodeSpecifiers );
|
Define_CodeImpl( CodeSpecifiers );
|
||||||
Define_CodeImpl( CodeStruct );
|
Define_CodeImpl( CodeStruct );
|
||||||
Define_CodeImpl( CodeTemplate );
|
Define_CodeImpl( CodeTemplate );
|
||||||
@ -193,6 +196,7 @@ Define_AST_Cast( Body );
|
|||||||
Define_AST_Cast( Attributes );
|
Define_AST_Cast( Attributes );
|
||||||
Define_AST_Cast( Comment );
|
Define_AST_Cast( Comment );
|
||||||
Define_AST_Cast( Class );
|
Define_AST_Cast( Class );
|
||||||
|
Define_AST_Cast( Define );
|
||||||
Define_AST_Cast( Enum );
|
Define_AST_Cast( Enum );
|
||||||
Define_AST_Cast( Exec );
|
Define_AST_Cast( Exec );
|
||||||
Define_AST_Cast( Extern );
|
Define_AST_Cast( Extern );
|
||||||
@ -204,6 +208,8 @@ Define_AST_Cast( Namespace );
|
|||||||
Define_AST_Cast( Operator );
|
Define_AST_Cast( Operator );
|
||||||
Define_AST_Cast( OpCast );
|
Define_AST_Cast( OpCast );
|
||||||
Define_AST_Cast( Param );
|
Define_AST_Cast( Param );
|
||||||
|
Define_AST_Cast( Pragma );
|
||||||
|
Define_AST_Cast( PreprocessCond );
|
||||||
Define_AST_Cast( Struct );
|
Define_AST_Cast( Struct );
|
||||||
Define_AST_Cast( Specifiers );
|
Define_AST_Cast( Specifiers );
|
||||||
Define_AST_Cast( Template );
|
Define_AST_Cast( Template );
|
||||||
@ -223,6 +229,7 @@ Code::operator Code ## type() const \
|
|||||||
Define_CodeCast( Attributes );
|
Define_CodeCast( Attributes );
|
||||||
Define_CodeCast( Comment );
|
Define_CodeCast( Comment );
|
||||||
Define_CodeCast( Class );
|
Define_CodeCast( Class );
|
||||||
|
Define_CodeCast( Define );
|
||||||
Define_CodeCast( Exec );
|
Define_CodeCast( Exec );
|
||||||
Define_CodeCast( Enum );
|
Define_CodeCast( Enum );
|
||||||
Define_CodeCast( Extern );
|
Define_CodeCast( Extern );
|
||||||
@ -234,6 +241,8 @@ Define_CodeCast( Namespace );
|
|||||||
Define_CodeCast( Operator );
|
Define_CodeCast( Operator );
|
||||||
Define_CodeCast( OpCast );
|
Define_CodeCast( OpCast );
|
||||||
Define_CodeCast( Param );
|
Define_CodeCast( Param );
|
||||||
|
Define_CodeCast( Pragma );
|
||||||
|
Define_CodeCast( PreprocessCond );
|
||||||
Define_CodeCast( Specifiers );
|
Define_CodeCast( Specifiers );
|
||||||
Define_CodeCast( Struct );
|
Define_CodeCast( Struct );
|
||||||
Define_CodeCast( Template );
|
Define_CodeCast( Template );
|
||||||
@ -368,28 +377,6 @@ StrC token_fmt_impl( sw num, ... )
|
|||||||
|
|
||||||
#pragma region Constants
|
#pragma region Constants
|
||||||
|
|
||||||
#ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
|
||||||
// Predefined typename codes. Are set to readonly and are setup during gen::init()
|
|
||||||
|
|
||||||
extern CodeType t_b32;
|
|
||||||
|
|
||||||
extern CodeType t_s8;
|
|
||||||
extern CodeType t_s16;
|
|
||||||
extern CodeType t_s32;
|
|
||||||
extern CodeType t_s64;
|
|
||||||
|
|
||||||
extern CodeType t_u8;
|
|
||||||
extern CodeType t_u16;
|
|
||||||
extern CodeType t_u32;
|
|
||||||
extern CodeType t_u64;
|
|
||||||
|
|
||||||
extern CodeType t_sw;
|
|
||||||
extern CodeType t_uw;
|
|
||||||
|
|
||||||
extern CodeType t_f32;
|
|
||||||
extern CodeType t_f64;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef GEN_GLOBAL_BUCKET_SIZE
|
#ifndef GEN_GLOBAL_BUCKET_SIZE
|
||||||
# define GEN_GLOBAL_BUCKET_SIZE megabytes(10)
|
# define GEN_GLOBAL_BUCKET_SIZE megabytes(10)
|
||||||
#endif
|
#endif
|
||||||
@ -437,29 +424,22 @@ constexpr s32 TokenFmt_TokenMap_MemSize = GEN_TOKEN_FMT_TOKEN_MAP_MEM_SIZE;
|
|||||||
constexpr s32 LexAllocator_Size = GEN_LEX_ALLOCATOR_SIZE;
|
constexpr s32 LexAllocator_Size = GEN_LEX_ALLOCATOR_SIZE;
|
||||||
constexpr s32 Builder_StrBufferReserve = GEN_BUILDER_STR_BUFFER_RESERVE;
|
constexpr s32 Builder_StrBufferReserve = GEN_BUILDER_STR_BUFFER_RESERVE;
|
||||||
|
|
||||||
extern CodeType t_empty; // Used with varaidc parameters. (Exposing just in case its useful for another circumstance)
|
|
||||||
extern CodeType t_auto;
|
|
||||||
extern CodeType t_void;
|
|
||||||
extern CodeType t_int;
|
|
||||||
extern CodeType t_bool;
|
|
||||||
extern CodeType t_char;
|
|
||||||
extern CodeType t_wchar_t;
|
|
||||||
extern CodeType t_class;
|
|
||||||
extern CodeType t_typename;
|
|
||||||
|
|
||||||
extern CodeParam param_varadic;
|
|
||||||
|
|
||||||
extern CodeAttributes attrib_api_export;
|
|
||||||
extern CodeAttributes 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;
|
||||||
|
|
||||||
|
extern CodeAttributes attrib_api_export;
|
||||||
|
extern CodeAttributes attrib_api_import;
|
||||||
|
|
||||||
extern Code module_global_fragment;
|
extern Code module_global_fragment;
|
||||||
extern Code module_private_fragment;
|
extern Code module_private_fragment;
|
||||||
|
|
||||||
extern Code pragma_once;
|
extern CodePragma pragma_once;
|
||||||
|
|
||||||
|
extern CodeParam param_varadic;
|
||||||
|
|
||||||
|
extern CodePreprocessCond preprocess_else;
|
||||||
|
extern CodePreprocessCond preprocess_endif;
|
||||||
|
|
||||||
extern CodeSpecifiers spec_const;
|
extern CodeSpecifiers spec_const;
|
||||||
extern CodeSpecifiers spec_consteval;
|
extern CodeSpecifiers spec_consteval;
|
||||||
@ -482,6 +462,38 @@ extern CodeSpecifiers spec_thread_local;
|
|||||||
extern CodeSpecifiers spec_virtual;
|
extern CodeSpecifiers spec_virtual;
|
||||||
extern CodeSpecifiers spec_volatile;
|
extern CodeSpecifiers spec_volatile;
|
||||||
|
|
||||||
|
extern CodeType t_empty; // Used with varaidc parameters. (Exposing just in case its useful for another circumstance)
|
||||||
|
extern CodeType t_auto;
|
||||||
|
extern CodeType t_void;
|
||||||
|
extern CodeType t_int;
|
||||||
|
extern CodeType t_bool;
|
||||||
|
extern CodeType t_char;
|
||||||
|
extern CodeType t_wchar_t;
|
||||||
|
extern CodeType t_class;
|
||||||
|
extern CodeType t_typename;
|
||||||
|
|
||||||
|
#ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||||
|
// Predefined typename codes. Are set to readonly and are setup during gen::init()
|
||||||
|
|
||||||
|
extern CodeType t_b32;
|
||||||
|
|
||||||
|
extern CodeType t_s8;
|
||||||
|
extern CodeType t_s16;
|
||||||
|
extern CodeType t_s32;
|
||||||
|
extern CodeType t_s64;
|
||||||
|
|
||||||
|
extern CodeType t_u8;
|
||||||
|
extern CodeType t_u16;
|
||||||
|
extern CodeType t_u32;
|
||||||
|
extern CodeType t_u64;
|
||||||
|
|
||||||
|
extern CodeType t_sw;
|
||||||
|
extern CodeType t_uw;
|
||||||
|
|
||||||
|
extern CodeType t_f32;
|
||||||
|
extern CodeType t_f64;
|
||||||
|
#endif
|
||||||
|
|
||||||
#pragma endregion Constants
|
#pragma endregion Constants
|
||||||
|
|
||||||
#pragma region Macros
|
#pragma region Macros
|
||||||
|
@ -71,6 +71,59 @@ void define_constants()
|
|||||||
Code::Invalid = make_code();
|
Code::Invalid = make_code();
|
||||||
Code::Invalid.set_global();
|
Code::Invalid.set_global();
|
||||||
|
|
||||||
|
access_private = make_code();
|
||||||
|
access_private->Type = ECode::Access_Private;
|
||||||
|
access_private->Name = get_cached_string( txt_StrC("private:") );
|
||||||
|
access_private.set_global();
|
||||||
|
|
||||||
|
access_protected = make_code();
|
||||||
|
access_protected->Type = ECode::Access_Protected;
|
||||||
|
access_protected->Name = get_cached_string( txt_StrC("protected:") );
|
||||||
|
access_protected.set_global();
|
||||||
|
|
||||||
|
access_public = make_code();
|
||||||
|
access_public->Type = ECode::Access_Public;
|
||||||
|
access_public->Name = get_cached_string( txt_StrC("public:") );
|
||||||
|
access_public.set_global();
|
||||||
|
|
||||||
|
attrib_api_export = def_attributes( code(GEN_API_Export_Code));
|
||||||
|
attrib_api_export.set_global();
|
||||||
|
|
||||||
|
attrib_api_import = def_attributes( code(GEN_API_Import_Code));
|
||||||
|
attrib_api_import.set_global();
|
||||||
|
|
||||||
|
module_global_fragment = make_code();
|
||||||
|
module_global_fragment->Type = ECode::Untyped;
|
||||||
|
module_global_fragment->Name = get_cached_string( txt_StrC("module;") );
|
||||||
|
module_global_fragment->Content = module_global_fragment->Name;
|
||||||
|
module_global_fragment.set_global();
|
||||||
|
|
||||||
|
module_private_fragment = make_code();
|
||||||
|
module_private_fragment->Type = ECode::Untyped;
|
||||||
|
module_private_fragment->Name = get_cached_string( txt_StrC("module : private;") );
|
||||||
|
module_private_fragment->Content = module_private_fragment->Name;
|
||||||
|
module_private_fragment.set_global();
|
||||||
|
|
||||||
|
pragma_once = (CodePragma) make_code();
|
||||||
|
pragma_once->Type = ECode::Untyped;
|
||||||
|
pragma_once->Name = get_cached_string( txt_StrC("once") );
|
||||||
|
pragma_once->Content = pragma_once->Name;
|
||||||
|
pragma_once.set_global();
|
||||||
|
|
||||||
|
param_varadic = (CodeType) make_code();
|
||||||
|
param_varadic->Type = ECode::Parameters;
|
||||||
|
param_varadic->Name = get_cached_string( txt_StrC("...") );
|
||||||
|
param_varadic->ValueType = t_empty;
|
||||||
|
param_varadic.set_global();
|
||||||
|
|
||||||
|
preprocess_else = (CodePreprocessCond) make_code();
|
||||||
|
preprocess_else->Type = ECode::Preprocess_Else;
|
||||||
|
preprocess_else.set_global();
|
||||||
|
|
||||||
|
preprocess_endif = (CodePreprocessCond) make_code();
|
||||||
|
preprocess_endif->Type = ECode::Preprocess_EndIf;
|
||||||
|
preprocess_endif.set_global();
|
||||||
|
|
||||||
# define def_constant_code_type( Type_ ) \
|
# define def_constant_code_type( Type_ ) \
|
||||||
t_##Type_ = def_type( name(Type_) ); \
|
t_##Type_ = def_type( name(Type_) ); \
|
||||||
t_##Type_.set_global();
|
t_##Type_.set_global();
|
||||||
@ -110,51 +163,6 @@ void define_constants()
|
|||||||
t_empty->Name = get_cached_string( txt_StrC("") );
|
t_empty->Name = get_cached_string( txt_StrC("") );
|
||||||
t_empty.set_global();
|
t_empty.set_global();
|
||||||
|
|
||||||
param_varadic = (CodeType) make_code();
|
|
||||||
param_varadic->Type = ECode::Parameters;
|
|
||||||
param_varadic->Name = get_cached_string( txt_StrC("...") );
|
|
||||||
param_varadic->ValueType = t_empty;
|
|
||||||
param_varadic.set_global();
|
|
||||||
|
|
||||||
attrib_api_export = def_attributes( code(GEN_API_Export_Code));
|
|
||||||
attrib_api_export.set_global();
|
|
||||||
|
|
||||||
attrib_api_import = def_attributes( code(GEN_API_Import_Code));
|
|
||||||
attrib_api_import.set_global();
|
|
||||||
|
|
||||||
access_private = make_code();
|
|
||||||
access_private->Type = ECode::Access_Private;
|
|
||||||
access_private->Name = get_cached_string( txt_StrC("private:") );
|
|
||||||
access_private.set_global();
|
|
||||||
|
|
||||||
access_protected = make_code();
|
|
||||||
access_protected->Type = ECode::Access_Protected;
|
|
||||||
access_protected->Name = get_cached_string( txt_StrC("protected:") );
|
|
||||||
access_protected.set_global();
|
|
||||||
|
|
||||||
access_public = make_code();
|
|
||||||
access_public->Type = ECode::Access_Public;
|
|
||||||
access_public->Name = get_cached_string( txt_StrC("public:") );
|
|
||||||
access_public.set_global();
|
|
||||||
|
|
||||||
module_global_fragment = make_code();
|
|
||||||
module_global_fragment->Type = ECode::Untyped;
|
|
||||||
module_global_fragment->Name = get_cached_string( txt_StrC("module;") );
|
|
||||||
module_global_fragment->Content = module_global_fragment->Name;
|
|
||||||
module_global_fragment.set_global();
|
|
||||||
|
|
||||||
module_private_fragment = make_code();
|
|
||||||
module_private_fragment->Type = ECode::Untyped;
|
|
||||||
module_private_fragment->Name = get_cached_string( txt_StrC("module : private;") );
|
|
||||||
module_private_fragment->Content = module_private_fragment->Name;
|
|
||||||
module_private_fragment.set_global();
|
|
||||||
|
|
||||||
pragma_once = make_code();
|
|
||||||
pragma_once->Type = ECode::Untyped;
|
|
||||||
pragma_once->Name = get_cached_string( txt_StrC("#pragma once") );
|
|
||||||
pragma_once->Content = pragma_once->Name;
|
|
||||||
pragma_once.set_global();
|
|
||||||
|
|
||||||
# pragma push_macro( "global" )
|
# pragma push_macro( "global" )
|
||||||
# pragma push_macro( "internal" )
|
# pragma push_macro( "internal" )
|
||||||
# pragma push_macro( "local_persist" )
|
# pragma push_macro( "local_persist" )
|
||||||
|
@ -45,6 +45,8 @@ CodeClass def_class( StrC name
|
|||||||
, ModuleFlag mflags = ModuleFlag::None
|
, ModuleFlag mflags = ModuleFlag::None
|
||||||
, CodeType* interfaces = nullptr, s32 num_interfaces = 0 );
|
, CodeType* interfaces = nullptr, s32 num_interfaces = 0 );
|
||||||
|
|
||||||
|
CodeDefine def_define( StrC name, StrC content );
|
||||||
|
|
||||||
CodeEnum def_enum( StrC name
|
CodeEnum def_enum( StrC name
|
||||||
, Code body = NoCode, CodeType type = NoCode
|
, Code body = NoCode, CodeType type = NoCode
|
||||||
, EnumT specifier = EnumRegular, CodeAttributes attributes = NoCode
|
, EnumT specifier = EnumRegular, CodeAttributes attributes = NoCode
|
||||||
@ -70,7 +72,11 @@ CodeOperator def_operator( OperatorT op
|
|||||||
|
|
||||||
CodeOpCast def_operator_cast( CodeType type, Code body = NoCode, CodeSpecifiers specs = NoCode );
|
CodeOpCast def_operator_cast( CodeType type, Code body = NoCode, CodeSpecifiers specs = NoCode );
|
||||||
|
|
||||||
CodeParam def_param ( CodeType type, StrC name, Code value = NoCode );
|
CodeParam def_param ( CodeType type, StrC name, Code value = NoCode );
|
||||||
|
CodePragma def_pragma( StrC directive );
|
||||||
|
|
||||||
|
CodePreprocessCond def_preprocess_cond( EPreprocessCond type, StrC content );
|
||||||
|
|
||||||
CodeSpecifiers def_specifier( SpecifierT specifier );
|
CodeSpecifiers def_specifier( SpecifierT specifier );
|
||||||
|
|
||||||
CodeStruct def_struct( StrC name
|
CodeStruct def_struct( StrC name
|
||||||
|
@ -36,7 +36,12 @@ namespace Parser
|
|||||||
|
|
||||||
bool is_preprocessor()
|
bool is_preprocessor()
|
||||||
{
|
{
|
||||||
return Type >= TokType::Preprocess_Define && Type <= TokType::Preprocess_EndIf;
|
return Type >= TokType::Preprocess_Define && Type <= TokType::Preprocess_Pragma;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_preprocess_cond()
|
||||||
|
{
|
||||||
|
return Type >= TokType::Preprocess_If && Type <= TokType::Preprocess_EndIf;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_specifier()
|
bool is_specifier()
|
||||||
@ -163,7 +168,13 @@ namespace Parser
|
|||||||
{
|
{
|
||||||
String token_str = String::make( GlobalAllocator, { Arr[Idx].Length, Arr[Idx].Text } );
|
String token_str = String::make( GlobalAllocator, { Arr[Idx].Length, Arr[Idx].Text } );
|
||||||
|
|
||||||
log_failure( "Parse Error, TokArray::eat, Expected: %s, not '%s' (%d, %d)`\n%s", ETokType::to_str(type), token_str, current().Line, current().Column, Context.to_string() );
|
log_failure( "Parse Error, TokArray::eat, Expected: %s, not '%s' (%d, %d)`\n%s"
|
||||||
|
, ETokType::to_str(type)
|
||||||
|
, token_str
|
||||||
|
, current().Line
|
||||||
|
, current().Column
|
||||||
|
, Context.to_string()
|
||||||
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -177,7 +188,7 @@ namespace Parser
|
|||||||
IsAssign = bit(0),
|
IsAssign = bit(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
TokArray lex( StrC content, bool keep_preprocess_directives = true )
|
TokArray lex( StrC content )
|
||||||
{
|
{
|
||||||
# define current ( * scanner )
|
# define current ( * scanner )
|
||||||
|
|
||||||
@ -202,17 +213,6 @@ namespace Parser
|
|||||||
move_forward(); \
|
move_forward(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
# define SkipWhitespace_Checked( Context_, Msg_, ... ) \
|
|
||||||
while ( left && char_is_space( current ) ) \
|
|
||||||
{ \
|
|
||||||
move_forward(); \
|
|
||||||
} \
|
|
||||||
if ( left <= 0 ) \
|
|
||||||
{ \
|
|
||||||
log_failure( "gen::" txt(Context_) ": " Msg_, __VA_ARGS__ ); \
|
|
||||||
return { 0, nullptr }; \
|
|
||||||
}
|
|
||||||
|
|
||||||
local_persist thread_local
|
local_persist thread_local
|
||||||
Array<Token> Tokens = { nullptr };
|
Array<Token> Tokens = { nullptr };
|
||||||
|
|
||||||
@ -249,34 +249,93 @@ namespace Parser
|
|||||||
|
|
||||||
switch ( current )
|
switch ( current )
|
||||||
{
|
{
|
||||||
// TODO : Need to handle the preprocessor as a separate pass.
|
|
||||||
case '#':
|
case '#':
|
||||||
|
{
|
||||||
token.Text = scanner;
|
token.Text = scanner;
|
||||||
token.Length = 1;
|
token.Length = 1;
|
||||||
move_forward();
|
move_forward();
|
||||||
|
|
||||||
while (left && current != '\n' )
|
while (left && current != ' ' )
|
||||||
{
|
{
|
||||||
if ( token.Type == ETokType::Invalid && current == ' ' )
|
|
||||||
{
|
|
||||||
token.Type = ETokType::to_type( token );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( current == '\\' )
|
|
||||||
{
|
|
||||||
move_forward();
|
|
||||||
|
|
||||||
if ( current != '\n' && keep_preprocess_directives )
|
|
||||||
{
|
|
||||||
log_failure( "gen::lex: invalid preprocessor directive, will still grab but will not compile %s", token.Text );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
move_forward();
|
move_forward();
|
||||||
token.Length++;
|
token.Length++;
|
||||||
}
|
}
|
||||||
goto FoundToken;
|
|
||||||
|
|
||||||
|
token.Type = ETokType::to_type( token );
|
||||||
|
Tokens.append( token );
|
||||||
|
|
||||||
|
Token content = { scanner, 0, TokType::Preprocess_Content, false, line, column };
|
||||||
|
|
||||||
|
if ( token.Type == TokType::Preprocess_Include )
|
||||||
|
{
|
||||||
|
content.Type = TokType::String;
|
||||||
|
|
||||||
|
SkipWhitespace();
|
||||||
|
if ( current != '"' )
|
||||||
|
{
|
||||||
|
log_failure( "gen::Parser::lex: Expected '\"' after #include, not '%c' (%d, %d)\n%s"
|
||||||
|
, current
|
||||||
|
, token.Line
|
||||||
|
, token.Column
|
||||||
|
, Context.to_string()
|
||||||
|
);
|
||||||
|
return { { nullptr }, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( left && current != '"' )
|
||||||
|
{
|
||||||
|
move_forward();
|
||||||
|
content.Length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
move_forward();
|
||||||
|
content.Length++;
|
||||||
|
|
||||||
|
Tokens.append( content );
|
||||||
|
continue; // Skip found token, its all handled here.
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( left )
|
||||||
|
{
|
||||||
|
if ( current == '\\' )
|
||||||
|
{
|
||||||
|
move_forward();
|
||||||
|
content.Length++;
|
||||||
|
|
||||||
|
if ( current == '\n' )
|
||||||
|
{
|
||||||
|
move_forward();
|
||||||
|
content.Length++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String directive_str = String::fmt_buf( GlobalAllocator, "%s", token.Text, token.Length );
|
||||||
|
String content_str = String::fmt_buf( GlobalAllocator, "%s", content, min( 40, left + content.Length ) );
|
||||||
|
|
||||||
|
log_failure( "gen::Parser::lex: Invalid escape sequence '\\%c' (%d, %d)"
|
||||||
|
" in preprocessor directive '%.*s' (%d, %d)\n"
|
||||||
|
"will continue parsing, but compiliation will fail (if using non-fatal failures).\n"
|
||||||
|
, content_str, line, column
|
||||||
|
, directive_str, token.Line, token.Column );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( current == '\n' )
|
||||||
|
{
|
||||||
|
move_forward();
|
||||||
|
content.Length++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
move_forward();
|
||||||
|
content.Length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tokens.append( content );
|
||||||
|
continue; // Skip found token, its all handled here.
|
||||||
|
}
|
||||||
case '.':
|
case '.':
|
||||||
token.Text = scanner;
|
token.Text = scanner;
|
||||||
token.Length = 1;
|
token.Length = 1;
|
||||||
@ -297,7 +356,9 @@ namespace Parser
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_failure( "gen::lex: invalid varadic argument, expected '...' got '..%c'", current );
|
String context_str = String::fmt_buf( GlobalAllocator, "%s", scanner, min( 100, left ) );
|
||||||
|
|
||||||
|
log_failure( "gen::lex: invalid varadic argument, expected '...' got '..%c' (%d, %d)", context_str, line, column );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,7 +730,7 @@ namespace Parser
|
|||||||
{
|
{
|
||||||
String context_str = String::fmt_buf( GlobalAllocator, "%s", scanner, min( 100, left ) );
|
String context_str = String::fmt_buf( GlobalAllocator, "%s", scanner, min( 100, left ) );
|
||||||
|
|
||||||
log_failure( "Failed to lex token %s", context_str );
|
log_failure( "Failed to lex token %s (%d, %d)", context_str, line, column );
|
||||||
|
|
||||||
// Skip to next whitespace since we can't know if anything else is valid until then.
|
// Skip to next whitespace since we can't know if anything else is valid until then.
|
||||||
while ( left && ! char_is_space( current ) )
|
while ( left && ! char_is_space( current ) )
|
||||||
@ -682,9 +743,6 @@ namespace Parser
|
|||||||
|
|
||||||
if ( token.Type != TokType::Invalid )
|
if ( token.Type != TokType::Invalid )
|
||||||
{
|
{
|
||||||
if ( token.is_preprocessor() && keep_preprocess_directives == false )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Tokens.append( token );
|
Tokens.append( token );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -708,22 +766,21 @@ namespace Parser
|
|||||||
# undef current
|
# undef current
|
||||||
# undef move_forward
|
# undef move_forward
|
||||||
# undef SkipWhitespace
|
# undef SkipWhitespace
|
||||||
# undef SkipWhitespace_Checked
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma region Helper Macros
|
#pragma region Helper Macros
|
||||||
|
|
||||||
# define check_parse_args( def ) \
|
# define check_parse_args( def ) \
|
||||||
if ( def.Len <= 0 ) \
|
if ( def.Len <= 0 ) \
|
||||||
{ \
|
{ \
|
||||||
log_failure( "gen::" stringize(__func__) ": length must greater than 0" ); \
|
log_failure( "gen::" stringize(__func__) ": length must greater than 0" ); \
|
||||||
return CodeInvalid; \
|
return CodeInvalid; \
|
||||||
} \
|
} \
|
||||||
if ( def.Ptr == nullptr ) \
|
if ( def.Ptr == nullptr ) \
|
||||||
{ \
|
{ \
|
||||||
log_failure( "gen::" stringize(__func__) ": def was null" ); \
|
log_failure( "gen::" stringize(__func__) ": def was null" ); \
|
||||||
return CodeInvalid; \
|
return CodeInvalid; \
|
||||||
}
|
}
|
||||||
|
|
||||||
# define nexttok Context.Tokens.next()
|
# define nexttok Context.Tokens.next()
|
||||||
@ -734,7 +791,7 @@ if ( def.Ptr == nullptr )
|
|||||||
|
|
||||||
# define check( Type_ ) ( left && currtok.Type == Type_ )
|
# define check( Type_ ) ( left && currtok.Type == Type_ )
|
||||||
|
|
||||||
# define push_scope() \
|
# define push_scope() \
|
||||||
StackNode scope { nullptr, currtok, NullToken, txt_StrC( __func__ ) }; \
|
StackNode scope { nullptr, currtok, NullToken, txt_StrC( __func__ ) }; \
|
||||||
Context.push( & scope )
|
Context.push( & scope )
|
||||||
|
|
||||||
@ -760,6 +817,115 @@ internal CodeTypedef parse_typedef ();
|
|||||||
internal CodeUnion parse_union ();
|
internal CodeUnion parse_union ();
|
||||||
internal CodeUsing parse_using ();
|
internal CodeUsing parse_using ();
|
||||||
|
|
||||||
|
internal inline
|
||||||
|
CodeDefine parse_define()
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
push_scope();
|
||||||
|
|
||||||
|
eat( TokType::Preprocess_Define );
|
||||||
|
|
||||||
|
CodeDefine
|
||||||
|
define = (CodeDefine) make_code();
|
||||||
|
define->Type = ECode::Preprocess_Define;
|
||||||
|
|
||||||
|
if ( ! check( TokType::Identifier ) )
|
||||||
|
{
|
||||||
|
log_failure( "Error, expected identifier after #define\n%s", Context.to_string() );
|
||||||
|
return CodeInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
define->Name = get_cached_string( currtok );
|
||||||
|
eat( TokType::Identifier );
|
||||||
|
|
||||||
|
if ( ! check( TokType::Preprocess_Content ))
|
||||||
|
{
|
||||||
|
log_failure( "Error, expected content after #define %s\n%s", define->Name, Context.to_string() );
|
||||||
|
return CodeInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
define->Content = get_cached_string( currtok );
|
||||||
|
eat( TokType::Preprocess_Content );
|
||||||
|
|
||||||
|
Context.pop();
|
||||||
|
return define;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline
|
||||||
|
CodePreprocessCond parse_preprocess_cond()
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
push_scope();
|
||||||
|
|
||||||
|
if ( ! currtok.is_preprocess_cond() )
|
||||||
|
{
|
||||||
|
log_failure( "Error, expected preprocess conditional\n%s", Context.to_string() );
|
||||||
|
return CodeInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodePreprocessCond
|
||||||
|
cond = (CodePreprocessCond) make_code();
|
||||||
|
cond->Type = scast(CodeT, currtok.Type - (ETokType::Preprocess_If - ECode::Preprocess_If) );
|
||||||
|
eat( currtok.Type );
|
||||||
|
|
||||||
|
if ( ! check( TokType::Preprocess_Content ))
|
||||||
|
{
|
||||||
|
log_failure( "Error, expected content after #define\n%s", Context.to_string() );
|
||||||
|
return CodeInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
cond->Content = get_cached_string( currtok );
|
||||||
|
eat( TokType::Preprocess_Content );
|
||||||
|
|
||||||
|
Context.pop();
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline
|
||||||
|
CodeInclude parse_include()
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
push_scope();
|
||||||
|
|
||||||
|
CodeInclude
|
||||||
|
include = (CodeInclude) make_code();
|
||||||
|
include->Type = ECode::Preprocess_Include;
|
||||||
|
|
||||||
|
if ( ! check( TokType::String ))
|
||||||
|
{
|
||||||
|
log_failure( "Error, expected include string after #include\n%s", Context.to_string() );
|
||||||
|
return CodeInvalid;
|
||||||
|
}
|
||||||
|
include->Content = get_cached_string( currtok );
|
||||||
|
eat( TokType::String );
|
||||||
|
|
||||||
|
Context.pop();
|
||||||
|
return include;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline
|
||||||
|
CodePragma parse_pragma()
|
||||||
|
{
|
||||||
|
using namespace Parser;
|
||||||
|
push_scope();
|
||||||
|
|
||||||
|
CodePragma
|
||||||
|
pragma = (CodePragma) make_code();
|
||||||
|
pragma->Type = ECode::Preprocess_Pragma;
|
||||||
|
|
||||||
|
if ( ! check( TokType::Preprocess_Content ))
|
||||||
|
{
|
||||||
|
log_failure( "Error, expected content after #define\n%s", Context.to_string() );
|
||||||
|
return CodeInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma->Content = get_cached_string( currtok );
|
||||||
|
eat( TokType::Preprocess_Content );
|
||||||
|
|
||||||
|
Context.pop();
|
||||||
|
return pragma;
|
||||||
|
}
|
||||||
|
|
||||||
internal inline
|
internal inline
|
||||||
Code parse_array_decl()
|
Code parse_array_decl()
|
||||||
{
|
{
|
||||||
@ -1677,6 +1843,33 @@ CodeBody parse_class_struct_body( Parser::TokType which )
|
|||||||
member = parse_using();
|
member = parse_using();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TokType::Preprocess_Define:
|
||||||
|
member = parse_define();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Preprocess_Include:
|
||||||
|
member = parse_include();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Preprocess_If:
|
||||||
|
case TokType::Preprocess_IfDef:
|
||||||
|
case TokType::Preprocess_IfNotDef:
|
||||||
|
case TokType::Preprocess_ElIf:
|
||||||
|
member = parse_preprocess_cond();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Preprocess_Pragma:
|
||||||
|
member = parse_pragma();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Preprocess_Else:
|
||||||
|
member = preprocess_else;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Preprocess_EndIf:
|
||||||
|
member = preprocess_endif;
|
||||||
|
break;
|
||||||
|
|
||||||
case TokType::Attribute_Open:
|
case TokType::Attribute_Open:
|
||||||
case TokType::Decl_GNU_Attribute:
|
case TokType::Decl_GNU_Attribute:
|
||||||
case TokType::Decl_MSVC_Attribute:
|
case TokType::Decl_MSVC_Attribute:
|
||||||
@ -1966,6 +2159,33 @@ CodeBody parse_global_nspace( CodeT which )
|
|||||||
member = parse_using();
|
member = parse_using();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TokType::Preprocess_Define:
|
||||||
|
member = parse_define();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Preprocess_Include:
|
||||||
|
member = parse_include();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Preprocess_If:
|
||||||
|
case TokType::Preprocess_IfDef:
|
||||||
|
case TokType::Preprocess_IfNotDef:
|
||||||
|
case TokType::Preprocess_ElIf:
|
||||||
|
member = parse_preprocess_cond();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Preprocess_Pragma:
|
||||||
|
member = parse_pragma();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Preprocess_Else:
|
||||||
|
member = preprocess_else;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokType::Preprocess_EndIf:
|
||||||
|
member = preprocess_endif;
|
||||||
|
break;
|
||||||
|
|
||||||
case TokType::Module_Export:
|
case TokType::Module_Export:
|
||||||
if ( which == Export_Body )
|
if ( which == Export_Body )
|
||||||
log_failure( "Nested export declaration\n%s", Context.to_string() );
|
log_failure( "Nested export declaration\n%s", Context.to_string() );
|
||||||
|
0
project/components/interface.upfront.bodies.cpp
Normal file
0
project/components/interface.upfront.bodies.cpp
Normal file
@ -489,6 +489,26 @@ CodeClass def_class( StrC name
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CodeDefine def_define( StrC name, StrC content )
|
||||||
|
{
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
|
name_check( def_define, name );
|
||||||
|
|
||||||
|
if ( content.Len <= 0 || content.Ptr == nullptr )
|
||||||
|
{
|
||||||
|
log_failure( "gen::def_define: Invalid value provided" );
|
||||||
|
return CodeInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeDefine
|
||||||
|
result = (CodeDefine) make_code();
|
||||||
|
result->Name = get_cached_string( name );
|
||||||
|
result->Content = get_cached_string( content );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
CodeEnum def_enum( StrC name
|
CodeEnum def_enum( StrC name
|
||||||
, Code body, CodeType type
|
, Code body, CodeType type
|
||||||
, EnumT specifier, CodeAttributes attributes
|
, EnumT specifier, CodeAttributes attributes
|
||||||
@ -719,7 +739,7 @@ CodeInclude def_include ( StrC path )
|
|||||||
|
|
||||||
Code
|
Code
|
||||||
result = make_code();
|
result = make_code();
|
||||||
result->Type = ECode::Preprocessor_Include;
|
result->Type = ECode::Preprocess_Include;
|
||||||
result->Name = get_cached_string( path );
|
result->Name = get_cached_string( path );
|
||||||
result->Content = result->Name;
|
result->Content = result->Name;
|
||||||
|
|
||||||
@ -910,6 +930,53 @@ CodeParam def_param( CodeType type, StrC name, Code value )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CodePragma def_pragma( StrC directive )
|
||||||
|
{
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
|
if ( directive.Len <= 0 || directive.Ptr == nullptr )
|
||||||
|
{
|
||||||
|
log_failure( "gen::def_comment: Invalid comment provided:" );
|
||||||
|
return CodeInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodePragma
|
||||||
|
result = (CodePragma) make_code();
|
||||||
|
result->Type = Preprocess_Pragma;
|
||||||
|
result->Content = get_cached_string( directive );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodePreprocessCond def_preprocess_cond( EPreprocessCond type, StrC expr )
|
||||||
|
{
|
||||||
|
using namespace ECode;
|
||||||
|
|
||||||
|
if ( expr.Len <= 0 || expr.Ptr == nullptr )
|
||||||
|
{
|
||||||
|
log_failure( "gen::def_comment: Invalid comment provided:" );
|
||||||
|
return CodeInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodePreprocessCond
|
||||||
|
result = (CodePreprocessCond) make_code();
|
||||||
|
result->Content = get_cached_string( expr );
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case EPreprocessCond::If:
|
||||||
|
result->Type = ECode::Preprocess_If;
|
||||||
|
case EPreprocessCond::IfDef:
|
||||||
|
result->Type = Preprocess_IfDef;
|
||||||
|
case EPreprocessCond::IfNotDef:
|
||||||
|
result->Type = Preprocess_IfNotDef;
|
||||||
|
case EPreprocessCond::ElIf:
|
||||||
|
result->Type = Preprocess_ElIf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
CodeSpecifiers def_specifier( SpecifierT spec )
|
CodeSpecifiers def_specifier( SpecifierT spec )
|
||||||
{
|
{
|
||||||
CodeSpecifiers
|
CodeSpecifiers
|
||||||
|
@ -22,6 +22,44 @@ global AllocatorInfo Allocator_TypeTable = heap();
|
|||||||
|
|
||||||
#pragma region Constants
|
#pragma region Constants
|
||||||
|
|
||||||
|
global Code access_public;
|
||||||
|
global Code access_protected;
|
||||||
|
global Code access_private;
|
||||||
|
|
||||||
|
global CodeAttributes attrib_api_export;
|
||||||
|
global CodeAttributes attrib_api_import;
|
||||||
|
|
||||||
|
global Code module_global_fragment;
|
||||||
|
global Code module_private_fragment;
|
||||||
|
|
||||||
|
global CodeParam param_varadic;
|
||||||
|
|
||||||
|
global CodePragma pragma_once;
|
||||||
|
|
||||||
|
global CodePreprocessCond preprocess_else;
|
||||||
|
global CodePreprocessCond preprocess_endif;
|
||||||
|
|
||||||
|
global CodeSpecifiers spec_const;
|
||||||
|
global CodeSpecifiers spec_consteval;
|
||||||
|
global CodeSpecifiers spec_constexpr;
|
||||||
|
global CodeSpecifiers spec_constinit;
|
||||||
|
global CodeSpecifiers spec_extern_linkage;
|
||||||
|
global CodeSpecifiers spec_final;
|
||||||
|
global CodeSpecifiers spec_global;
|
||||||
|
global CodeSpecifiers spec_inline;
|
||||||
|
global CodeSpecifiers spec_internal_linkage;
|
||||||
|
global CodeSpecifiers spec_local_persist;
|
||||||
|
global CodeSpecifiers spec_mutable;
|
||||||
|
global CodeSpecifiers spec_override;
|
||||||
|
global CodeSpecifiers spec_ptr;
|
||||||
|
global CodeSpecifiers spec_ref;
|
||||||
|
global CodeSpecifiers spec_register;
|
||||||
|
global CodeSpecifiers spec_rvalue;
|
||||||
|
global CodeSpecifiers spec_static_member;
|
||||||
|
global CodeSpecifiers spec_thread_local;
|
||||||
|
global CodeSpecifiers spec_virtual;
|
||||||
|
global CodeSpecifiers spec_volatile;
|
||||||
|
|
||||||
global CodeType t_empty;
|
global CodeType t_empty;
|
||||||
global CodeType t_auto;
|
global CodeType t_auto;
|
||||||
global CodeType t_void;
|
global CodeType t_void;
|
||||||
@ -52,39 +90,4 @@ global CodeType t_f32;
|
|||||||
global CodeType t_f64;
|
global CodeType t_f64;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
global CodeParam param_varadic;
|
|
||||||
|
|
||||||
global CodeAttributes attrib_api_export;
|
|
||||||
global CodeAttributes attrib_api_import;
|
|
||||||
|
|
||||||
global Code access_public;
|
|
||||||
global Code access_protected;
|
|
||||||
global Code access_private;
|
|
||||||
|
|
||||||
global Code module_global_fragment;
|
|
||||||
global Code module_private_fragment;
|
|
||||||
|
|
||||||
global Code pragma_once;
|
|
||||||
|
|
||||||
global CodeSpecifiers spec_const;
|
|
||||||
global CodeSpecifiers spec_consteval;
|
|
||||||
global CodeSpecifiers spec_constexpr;
|
|
||||||
global CodeSpecifiers spec_constinit;
|
|
||||||
global CodeSpecifiers spec_extern_linkage;
|
|
||||||
global CodeSpecifiers spec_final;
|
|
||||||
global CodeSpecifiers spec_global;
|
|
||||||
global CodeSpecifiers spec_inline;
|
|
||||||
global CodeSpecifiers spec_internal_linkage;
|
|
||||||
global CodeSpecifiers spec_local_persist;
|
|
||||||
global CodeSpecifiers spec_mutable;
|
|
||||||
global CodeSpecifiers spec_override;
|
|
||||||
global CodeSpecifiers spec_ptr;
|
|
||||||
global CodeSpecifiers spec_ref;
|
|
||||||
global CodeSpecifiers spec_register;
|
|
||||||
global CodeSpecifiers spec_rvalue;
|
|
||||||
global CodeSpecifiers spec_static_member;
|
|
||||||
global CodeSpecifiers spec_thread_local;
|
|
||||||
global CodeSpecifiers spec_virtual;
|
|
||||||
global CodeSpecifiers spec_volatile;
|
|
||||||
|
|
||||||
#pragma endregion Constants
|
#pragma endregion Constants
|
||||||
|
@ -8,16 +8,6 @@ using LogFailType = sw(*)(char const*, ...);
|
|||||||
constexpr LogFailType log_failure = fatal;
|
constexpr LogFailType log_failure = fatal;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Used to indicate if enum definitoin is an enum class or regular enum.
|
|
||||||
enum class EnumT : u8
|
|
||||||
{
|
|
||||||
Regular,
|
|
||||||
Class
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr EnumT EnumClass = EnumT::Class;
|
|
||||||
constexpr EnumT EnumRegular = EnumT::Regular;
|
|
||||||
|
|
||||||
enum class AccessSpec : u32
|
enum class AccessSpec : u32
|
||||||
{
|
{
|
||||||
Default,
|
Default,
|
||||||
@ -46,6 +36,17 @@ char const* to_str( AccessSpec type )
|
|||||||
return lookup[ (u32)type ];
|
return lookup[ (u32)type ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used to indicate if enum definitoin is an enum class or regular enum.
|
||||||
|
enum class EnumT : u8
|
||||||
|
{
|
||||||
|
Regular,
|
||||||
|
Class
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr EnumT EnumClass = EnumT::Class;
|
||||||
|
constexpr EnumT EnumRegular = EnumT::Regular;
|
||||||
|
|
||||||
|
|
||||||
enum class ModuleFlag : u32
|
enum class ModuleFlag : u32
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
@ -62,6 +63,19 @@ ModuleFlag operator|( ModuleFlag A, ModuleFlag B)
|
|||||||
return (ModuleFlag)( (u32)A | (u32)B );
|
return (ModuleFlag)( (u32)A | (u32)B );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class EPreprocessCond : u32
|
||||||
|
{
|
||||||
|
If,
|
||||||
|
IfDef,
|
||||||
|
IfNotDef,
|
||||||
|
ElIf
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr EPreprocessCond PreprocessCond_If = EPreprocessCond::If;
|
||||||
|
constexpr EPreprocessCond PreprocessCond_IfDef = EPreprocessCond::IfDef;
|
||||||
|
constexpr EPreprocessCond PreprocessCond_IfNotDef = EPreprocessCond::IfNotDef;
|
||||||
|
constexpr EPreprocessCond PreprocessCond_ElIf = EPreprocessCond::ElIf;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Predefined attributes
|
Predefined attributes
|
||||||
Used for the parser constructors to identify non-standard attributes
|
Used for the parser constructors to identify non-standard attributes
|
||||||
|
@ -32,7 +32,15 @@ Operator_Member_Fwd
|
|||||||
Operator_Cast
|
Operator_Cast
|
||||||
Operator_Cast_Fwd
|
Operator_Cast_Fwd
|
||||||
Parameters
|
Parameters
|
||||||
Preprocessor_Include
|
Preprocess_Define
|
||||||
|
Preprocess_Include
|
||||||
|
Preprocess_If
|
||||||
|
Preprocess_IfDef
|
||||||
|
Preprocess_IfNotDef
|
||||||
|
Preprocess_ElIf
|
||||||
|
Preprocess_Else
|
||||||
|
Preprocess_EndIf
|
||||||
|
Preprocess_Pragma
|
||||||
Specifiers
|
Specifiers
|
||||||
Struct
|
Struct
|
||||||
Struct_Fwd
|
Struct_Fwd
|
||||||
|
|
@ -38,11 +38,14 @@ Module_Export, "export"
|
|||||||
Number, "number"
|
Number, "number"
|
||||||
Operator, "operator"
|
Operator, "operator"
|
||||||
Preprocess_Define, "#define"
|
Preprocess_Define, "#define"
|
||||||
Preprocess_Include, "#include"
|
|
||||||
Preprocess_If, "#if"
|
Preprocess_If, "#if"
|
||||||
Preprocess_ElIF, "#elif"
|
Preprocess_IfDef, "#ifdef"
|
||||||
|
Preprocess_IfNotDef, "#ifndef"
|
||||||
|
Preprocess_ElIf, "#elif"
|
||||||
Preprocess_Else, "#else"
|
Preprocess_Else, "#else"
|
||||||
Preprocess_EndIf, "#endif"
|
Preprocess_EndIf, "#endif"
|
||||||
|
Preprocess_Include, "#include"
|
||||||
|
Preprocess_Pragma, "#pragma"
|
||||||
Spec_Alignas, "alignas"
|
Spec_Alignas, "alignas"
|
||||||
Spec_Const, "const"
|
Spec_Const, "const"
|
||||||
Spec_Consteval, "consteval"
|
Spec_Consteval, "consteval"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user