mirror of
https://github.com/Ed94/gencpp.git
synced 2024-12-22 07:44:45 -08:00
Started to generate the enums from csv (ECode, EOperator, ESpecifier).
- Changed the zpl csv parser to only accept hex values with 0x perfix. it was messing with the add term. - Small changes to the clang format config.
This commit is contained in:
parent
8232e79aac
commit
cf65638979
@ -0,0 +1,2 @@
|
||||
API_Export, GEN_API_Export_Code
|
||||
API_Import, GEN_API_Import_Code
|
|
@ -0,0 +1,46 @@
|
||||
Untyped
|
||||
Comment
|
||||
Access_Private
|
||||
Access_Protected
|
||||
Access_Public
|
||||
PlatformAttributes
|
||||
Class
|
||||
Class_Fwd
|
||||
Class_Body
|
||||
Enum
|
||||
Enum_Fwd
|
||||
Enum_Body
|
||||
Enum_Class
|
||||
Enum_Class_Fwd
|
||||
Execution
|
||||
Export_Body
|
||||
Extern_Linkage
|
||||
Extern_Linkage_Body
|
||||
Friend
|
||||
Function
|
||||
Function_Fwd
|
||||
Function_Body
|
||||
Global_Body
|
||||
Module
|
||||
Namespace
|
||||
Namespace_Body
|
||||
Operator
|
||||
Operator_Fwd
|
||||
Operator_Member
|
||||
Operator_Member_Fwd
|
||||
Operator_Cast
|
||||
Operator_Cast_Fwd
|
||||
Parameters
|
||||
Preprocessor_Include
|
||||
Specifiers
|
||||
Struct
|
||||
Struct_Fwd
|
||||
Struct_Body
|
||||
Template
|
||||
Typedef
|
||||
Typename
|
||||
Union
|
||||
Union_Body
|
||||
Using
|
||||
Using_Namespace
|
||||
Variable
|
|
@ -0,0 +1,42 @@
|
||||
Assign, "="
|
||||
Assign_Add, "+="
|
||||
Assign_Subtract, "-="
|
||||
Assign_Multiply, "*="
|
||||
Assign_Divide, "/="
|
||||
Assign_Modulo, "%="
|
||||
Assign_BAnd, "&="
|
||||
Assign_BOr, "|="
|
||||
Assign_BXOr, "^="
|
||||
Assign_LShift, "<<="
|
||||
Assign_RShift, ">>="
|
||||
Increment, "++"
|
||||
Decrement, "--"
|
||||
Unary_Plus, "+"
|
||||
Unary_Minus, "-"
|
||||
UnaryNot, "!"
|
||||
Add, "+"
|
||||
Subtract, "-"
|
||||
Multiply, "*"
|
||||
Divide, "/"
|
||||
Modulo, "%"
|
||||
BNot, "~"
|
||||
BAnd, "&"
|
||||
BOr, "|"
|
||||
BXOr, "^"
|
||||
LShift, "<<"
|
||||
RShift, ">>"
|
||||
LAnd, "&&"
|
||||
LOr, "||"
|
||||
LEqual, "=="
|
||||
LNot, "!="
|
||||
Lesser, "<"
|
||||
Greater, ">"
|
||||
LesserEqual, "<="
|
||||
GreaterEqual, ">="
|
||||
Subscript, "[]"
|
||||
Indirection, "*"
|
||||
AddressOf, "&"
|
||||
MemberOfPointer, "->"
|
||||
PtrToMemOfPtr, "->*"
|
||||
FunctionCall, "()"
|
||||
Comma, ","
|
|
@ -0,0 +1,22 @@
|
||||
Invalid, INVALID
|
||||
Consteval, consteval
|
||||
Constexpr, constexpr
|
||||
Constinit, constinit
|
||||
Explicit, explicit
|
||||
External_Linkage, extern
|
||||
Global, global
|
||||
Inline, inline
|
||||
Internal_Linkage, internal
|
||||
Local_Persist, local_persist
|
||||
Mutable, mutable
|
||||
Ptr, *
|
||||
Ref, &
|
||||
Register, register
|
||||
RValue, &&
|
||||
Static, static
|
||||
Thread_Local, thread_local
|
||||
Volatile, volatile
|
||||
Virtual, virtual
|
||||
Const, const
|
||||
Final, final
|
||||
Override, override
|
|
@ -0,0 +1,69 @@
|
||||
Access_Private, "private"
|
||||
Access_Protected, "protected"
|
||||
Access_Public, "public"
|
||||
Access_MemberSymbol, "."
|
||||
Access_StaticSymbol, "::"
|
||||
Ampersand, "&"
|
||||
Ampersand_DBL, "&&"
|
||||
Assign_Classifer, ":"
|
||||
Attribute_Open, "[["
|
||||
Attribute_Close, "]]"
|
||||
BraceCurly_Open, "{"
|
||||
BraceCurly_Close, "}"
|
||||
BraceSquare_Open, "["
|
||||
BraceSquare_Close, "]"
|
||||
Capture_Start, "("
|
||||
Capture_End, ")"
|
||||
Comment, "__comment__"
|
||||
Char, "__char__"
|
||||
Comma, ","
|
||||
Decl_Class, "class"
|
||||
Decl_GNU_Attribute, "__attribute__"
|
||||
Decl_MSVC_Attribute, "__declspec"
|
||||
Decl_Enum, "enum"
|
||||
Decl_Extern_Linkage, "extern"
|
||||
Decl_Friend, "friend"
|
||||
Decl_Module, "module"
|
||||
Decl_Namespace, "namespace"
|
||||
Decl_Operator, "operator"
|
||||
Decl_Struct, "struct"
|
||||
Decl_Template, "template"
|
||||
Decl_Typedef, "typedef"
|
||||
Decl_Using, "using"
|
||||
Decl_Union, "union"
|
||||
Identifier, "__identifier__"
|
||||
Module_Import, "import"
|
||||
Module_Export, "export"
|
||||
Number, "number"
|
||||
Operator, "operator"
|
||||
Preprocessor_Directive, "#"
|
||||
Preprocessor_Include, "include"
|
||||
Spec_Alignas, "alignas"
|
||||
Spec_Const, "const"
|
||||
Spec_Consteval, "consteval"
|
||||
Spec_Constexpr, "constexpr"
|
||||
Spec_Constinit, "constinit"
|
||||
Spec_Explicit, "explicit"
|
||||
Spec_Extern, "extern"
|
||||
Spec_Final, "final"
|
||||
Spec_Global, "global"
|
||||
Spec_Inline, "inline"
|
||||
Spec_Internal_Linkage, "internal"
|
||||
Spec_LocalPersist, "local_persist"
|
||||
Spec_Mutable, "mutable"
|
||||
Spec_Override, "override"
|
||||
Spec_Static, "static"
|
||||
Spec_ThreadLocal, "thread_local"
|
||||
Spec_Volatile, "volatile"
|
||||
Star, "*"
|
||||
Statement_End, ";"
|
||||
String, "__string__"
|
||||
Type_Unsigned, "unsigned"
|
||||
Type_Signed, "signed"
|
||||
Type_Short, "short"
|
||||
Type_Long, "long"
|
||||
Type_char, "char"
|
||||
Type_int, "int"
|
||||
Type_double, "double"
|
||||
Varadic_Argument, "..."
|
||||
Attributes_Start, "__attrib_start__"
|
|
@ -1,3 +1,5 @@
|
||||
#pragma region AST
|
||||
|
||||
Code Code::Global;
|
||||
Code Code::Invalid;
|
||||
|
||||
@ -5,215 +7,11 @@ AST* AST::duplicate()
|
||||
{
|
||||
using namespace ECode;
|
||||
|
||||
AST*
|
||||
result = make_code().ast;
|
||||
#ifndef GEN_USE_RECURSIVE_AST_DUPLICATION
|
||||
AST* result = make_code().ast;
|
||||
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
result->Parent = nullptr;
|
||||
#else
|
||||
// TODO : Stress test this...
|
||||
switch ( Type )
|
||||
{
|
||||
case Invalid:
|
||||
log_failure("Attempted to duplicate invalid code! - \n%s", Parent ? Parent->debug_str() : Name );
|
||||
return nullptr
|
||||
case Untyped:
|
||||
case Comment:
|
||||
case Execution:
|
||||
case Access_Private:
|
||||
case Access_Protected:
|
||||
case Access_Public:
|
||||
case PlatformAttributes:
|
||||
case Preprocessor_Include:
|
||||
case Module:
|
||||
case Specifiers:
|
||||
case Using_Namespace:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
break;
|
||||
|
||||
case Extern_Linkage:
|
||||
case Friend:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
if (Value)
|
||||
result->Value = Value->duplicate();
|
||||
break;
|
||||
|
||||
case Class:
|
||||
case Struct:
|
||||
case Enum:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
if ( Attributes)
|
||||
result->Attributes = Attributes->duplicate();
|
||||
|
||||
if ( ParentType )
|
||||
result->ParentType = ParentType->duplicate();
|
||||
|
||||
result->Body = Body->duplicate();
|
||||
break;
|
||||
|
||||
case Enum_Fwd:
|
||||
case Class_Fwd:
|
||||
case Struct_Fwd:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
if ( Attributes)
|
||||
result->Attributes = Attributes->duplicate();
|
||||
|
||||
if ( ParentType )
|
||||
result->ParentType = ParentType->duplicate();
|
||||
break;
|
||||
|
||||
case Function:
|
||||
case Operator:
|
||||
case Operator_Member:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
if ( Attributes)
|
||||
result->Attributes = Attributes->duplicate();
|
||||
|
||||
if ( Specs )
|
||||
result->ParentType = ParentType->duplicate();
|
||||
|
||||
if ( ReturnType )
|
||||
result->ReturnType = ReturnType->duplicate();
|
||||
|
||||
if ( Params )
|
||||
result->Params = Params->duplicate();
|
||||
|
||||
result->Body = Body->duplicate();
|
||||
break;
|
||||
|
||||
case Function_Fwd:
|
||||
case Operator_Fwd:
|
||||
case Operator_Member_Fwd:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
if ( Attributes)
|
||||
result->Attributes = Attributes->duplicate();
|
||||
|
||||
if ( Specs )
|
||||
result->ParentType = ParentType->duplicate();
|
||||
|
||||
if ( ReturnType )
|
||||
result->ReturnType = ReturnType->duplicate();
|
||||
|
||||
if ( Params )
|
||||
result->Params = Params->duplicate();
|
||||
break;
|
||||
|
||||
case Namespace:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
result->Body = Body->duplicate();
|
||||
break;
|
||||
|
||||
case Operator_Cast:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
result->ValueType = ValueType->duplicate();
|
||||
result->Body = Body->duplicate();
|
||||
break;
|
||||
case Operator_Cast_Fwd:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
result->ValueType = ValueType->duplicate();
|
||||
break;
|
||||
|
||||
case Parameters:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
result->NumEntries = 0;
|
||||
result->Last = nullptr;
|
||||
result->Next = nullptr;
|
||||
|
||||
if ( NumEntries - 1 > 0 )
|
||||
{
|
||||
CodeParam parent = result->cast<CodeParam>();
|
||||
for ( CodeParam param : Next->cast<CodeParam>() )
|
||||
{
|
||||
parent.append( param );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Template:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
result->Params = Params->duplicate();
|
||||
result->Declaration = Declaration->duplicate();
|
||||
break;
|
||||
|
||||
case Typename:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
if (Attributes)
|
||||
result->Attributes = Attributes->duplicate();
|
||||
|
||||
if ( Specs )
|
||||
result->Specs = Specs->duplicate();
|
||||
|
||||
if ( ArrExpr )
|
||||
result->ArrExpr = ArrExpr->duplicate();
|
||||
break;
|
||||
|
||||
case Typedef:
|
||||
case Using:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
if (Attributes)
|
||||
result->Attributes = Attributes->duplicate();
|
||||
|
||||
if ( UnderlyingType )
|
||||
result->UnderlyingType = UnderlyingType->duplicate();
|
||||
break;
|
||||
|
||||
case Union:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
if ( Attributes)
|
||||
result->Attributes = Attributes->duplicate();
|
||||
|
||||
result->Body = Body->duplicate();
|
||||
break;
|
||||
|
||||
case Variable:
|
||||
mem_copy( result, this, sizeof( AST ) );
|
||||
|
||||
if (Attributes)
|
||||
result->Attributes = Attributes->duplicate();
|
||||
|
||||
if ( Specs )
|
||||
result->Specs = Specs->duplicate();
|
||||
|
||||
result->ValueType = UnderlyingType->duplicate();
|
||||
|
||||
if ( Value )
|
||||
result->Value = Value->duplicate();
|
||||
break;
|
||||
|
||||
case Class_Body:
|
||||
case Enum_Body:
|
||||
case Export_Body:
|
||||
case Extern_Linkage_Body:
|
||||
case Function_Body:
|
||||
case Global_Body:
|
||||
case Namespace_Body:
|
||||
case Struct_Body:
|
||||
case Union_Body:
|
||||
CodeBody
|
||||
body = cast<CodeBody>();
|
||||
body->Name = Name;
|
||||
body->Type = Type;
|
||||
for ( Code entry : cast<CodeBody>() )
|
||||
{
|
||||
result->append( entry.ast );
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1028,3 +826,5 @@ bool AST::validate_body()
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma endregion AST
|
||||
|
@ -1,3 +1,5 @@
|
||||
#pragma region Data Structures
|
||||
|
||||
// Implements basic string interning. Data structure is based off the ZPL Hashtable.
|
||||
using StringTable = HashTable<String const>;
|
||||
|
||||
@ -1011,3 +1013,4 @@ struct AST_Var
|
||||
static_assert( sizeof(AST_Var) == sizeof(AST), "ERROR: AST_Var is not the same size as AST");
|
||||
#pragma endregion Filtered ASTs
|
||||
|
||||
#pragma endregion Data Structures
|
||||
|
78
project/components/gen.ecode.hpp
Normal file
78
project/components/gen.ecode.hpp
Normal file
@ -0,0 +1,78 @@
|
||||
// This is the non-bootstraped version of the ECode. This will be obsolete once bootstrap is stress tested.
|
||||
|
||||
namespace ECode
|
||||
{
|
||||
# define Define_Types \
|
||||
Entry( Untyped ) \
|
||||
Entry( Comment ) \
|
||||
Entry( Access_Private ) \
|
||||
Entry( Access_Protected ) \
|
||||
Entry( Access_Public ) \
|
||||
Entry( PlatformAttributes ) \
|
||||
Entry( Class ) \
|
||||
Entry( Class_Fwd ) \
|
||||
Entry( Class_Body ) \
|
||||
Entry( Enum ) \
|
||||
Entry( Enum_Fwd ) \
|
||||
Entry( Enum_Body ) \
|
||||
Entry( Enum_Class ) \
|
||||
Entry( Enum_Class_Fwd ) \
|
||||
Entry( Execution ) \
|
||||
Entry( Export_Body ) \
|
||||
Entry( Extern_Linkage ) \
|
||||
Entry( Extern_Linkage_Body ) \
|
||||
Entry( Friend ) \
|
||||
Entry( Function ) \
|
||||
Entry( Function_Fwd ) \
|
||||
Entry( Function_Body ) \
|
||||
Entry( Global_Body ) \
|
||||
Entry( Module ) \
|
||||
Entry( Namespace ) \
|
||||
Entry( Namespace_Body ) \
|
||||
Entry( Operator ) \
|
||||
Entry( Operator_Fwd ) \
|
||||
Entry( Operator_Member ) \
|
||||
Entry( Operator_Member_Fwd ) \
|
||||
Entry( Operator_Cast ) \
|
||||
Entry( Operator_Cast_Fwd ) \
|
||||
Entry( Parameters ) \
|
||||
Entry( Preprocessor_Include ) \
|
||||
Entry( Specifiers ) \
|
||||
Entry( Struct ) \
|
||||
Entry( Struct_Fwd ) \
|
||||
Entry( Struct_Body ) \
|
||||
Entry( Template ) \
|
||||
Entry( Typedef ) \
|
||||
Entry( Typename ) \
|
||||
Entry( Union ) \
|
||||
Entry( Union_Body) \
|
||||
Entry( Using ) \
|
||||
Entry( Using_Namespace ) \
|
||||
Entry( Variable )
|
||||
|
||||
enum Type : u32
|
||||
{
|
||||
# define Entry( Type ) Type,
|
||||
Define_Types
|
||||
# undef Entry
|
||||
|
||||
Num_Types,
|
||||
Invalid
|
||||
};
|
||||
|
||||
inline
|
||||
StrC to_str( Type type )
|
||||
{
|
||||
static
|
||||
StrC lookup[Num_Types] = {
|
||||
# define Entry( Type ) { sizeof(stringize(Type)), stringize(Type) },
|
||||
Define_Types
|
||||
# undef Entry
|
||||
};
|
||||
|
||||
return lookup[ type ];
|
||||
}
|
||||
|
||||
# undef Define_Types
|
||||
}
|
||||
using CodeT = ECode::Type;
|
75
project/components/gen.eoperator.hpp
Normal file
75
project/components/gen.eoperator.hpp
Normal file
@ -0,0 +1,75 @@
|
||||
// This is the non-bootstraped version of the EOperator. This will be obsolete once bootstrap is stress tested.
|
||||
|
||||
namespace EOperator
|
||||
{
|
||||
# define Define_Operators \
|
||||
Entry( Assign, = ) \
|
||||
Entry( Assign_Add, += ) \
|
||||
Entry( Assign_Subtract, -= ) \
|
||||
Entry( Assign_Multiply, *= ) \
|
||||
Entry( Assign_Divide, /= ) \
|
||||
Entry( Assign_Modulo, %= ) \
|
||||
Entry( Assign_BAnd, &= ) \
|
||||
Entry( Assign_BOr, |= ) \
|
||||
Entry( Assign_BXOr, ^= ) \
|
||||
Entry( Assign_LShift, <<= ) \
|
||||
Entry( Assign_RShift, >>= ) \
|
||||
Entry( Increment, ++ ) \
|
||||
Entry( Decrement, -- ) \
|
||||
Entry( Unary_Plus, + ) \
|
||||
Entry( Unary_Minus, - ) \
|
||||
Entry( UnaryNot, ! ) \
|
||||
Entry( Add, + ) \
|
||||
Entry( Subtract, - ) \
|
||||
Entry( Multiply, * ) \
|
||||
Entry( Divide, / ) \
|
||||
Entry( Modulo, % ) \
|
||||
Entry( BNot, ~ ) \
|
||||
Entry( BAnd, & ) \
|
||||
Entry( BOr, | ) \
|
||||
Entry( BXOr, ^ ) \
|
||||
Entry( LShift, << ) \
|
||||
Entry( RShift, >> ) \
|
||||
Entry( LAnd, && ) \
|
||||
Entry( LOr, || ) \
|
||||
Entry( LEqual, == ) \
|
||||
Entry( LNot, != ) \
|
||||
Entry( Lesser, < ) \
|
||||
Entry( Greater, > ) \
|
||||
Entry( LesserEqual, <= ) \
|
||||
Entry( GreaterEqual, >= ) \
|
||||
Entry( Subscript, [] ) \
|
||||
Entry( Indirection, * ) \
|
||||
Entry( AddressOf, & ) \
|
||||
Entry( MemberOfPointer, -> ) \
|
||||
Entry( PtrToMemOfPtr, ->* ) \
|
||||
Entry( FunctionCall, () )
|
||||
|
||||
enum Type : u32
|
||||
{
|
||||
# define Entry( Type_, Token_ ) Type_,
|
||||
Define_Operators
|
||||
# undef Entry
|
||||
Comma,
|
||||
|
||||
Num_Ops,
|
||||
Invalid
|
||||
};
|
||||
|
||||
inline
|
||||
char const* to_str( Type op )
|
||||
{
|
||||
local_persist
|
||||
char const* lookup[ Num_Ops ] = {
|
||||
# define Entry( Type_, Token_ ) stringize(Token_),
|
||||
Define_Operators
|
||||
# undef Entry
|
||||
","
|
||||
};
|
||||
|
||||
return lookup[ op ];
|
||||
}
|
||||
|
||||
# undef Define_Operators
|
||||
}
|
||||
using OperatorT = EOperator::Type;
|
104
project/components/gen.especifier.hpp
Normal file
104
project/components/gen.especifier.hpp
Normal file
@ -0,0 +1,104 @@
|
||||
// This is the non-bootstraped version of the ESpecifier. This will be obsolete once bootstrap is stress tested.
|
||||
|
||||
namespace ESpecifier
|
||||
{
|
||||
/*
|
||||
Note: The following are handled separately:
|
||||
attributes
|
||||
alignas
|
||||
*/
|
||||
|
||||
# define Define_Specifiers \
|
||||
Entry( Invalid, INVALID ) \
|
||||
Entry( Consteval, consteval ) \
|
||||
Entry( Constexpr, constexpr ) \
|
||||
Entry( Constinit, constinit ) \
|
||||
Entry( Explicit, explicit ) \
|
||||
Entry( External_Linkage, extern ) \
|
||||
Entry( Global, global ) \
|
||||
Entry( Inline, inline ) \
|
||||
Entry( Internal_Linkage, internal ) \
|
||||
Entry( Local_Persist, local_persist ) \
|
||||
Entry( Mutable, mutable ) \
|
||||
Entry( Ptr, * ) \
|
||||
Entry( Ref, & ) \
|
||||
Entry( Register, register ) \
|
||||
Entry( RValue, && ) \
|
||||
Entry( Static, static ) \
|
||||
Entry( Thread_Local, thread_local ) \
|
||||
Entry( Volatile, volatile ) \
|
||||
Entry( Virtual, virtual ) \
|
||||
Entry( Const, const ) \
|
||||
Entry( Final, final ) \
|
||||
Entry( Override, override )
|
||||
|
||||
enum Type : u32
|
||||
{
|
||||
# define Entry( Specifier, Code ) Specifier,
|
||||
Define_Specifiers
|
||||
# undef Entry
|
||||
|
||||
Num_Specifiers,
|
||||
};
|
||||
|
||||
inline
|
||||
bool is_trailing( Type specifier )
|
||||
{
|
||||
return specifier > Virtual;
|
||||
}
|
||||
|
||||
// Specifier to string
|
||||
inline
|
||||
StrC to_str( Type specifier )
|
||||
{
|
||||
local_persist
|
||||
StrC lookup[ Num_Specifiers ] = {
|
||||
# pragma push_macro( "global" )
|
||||
# pragma push_macro( "internal" )
|
||||
# pragma push_macro( "local_persist" )
|
||||
# undef global
|
||||
# undef internal
|
||||
# undef local_persist
|
||||
|
||||
# define Entry( Spec_, Code_ ) { sizeof(stringize(Code_)), stringize(Code_) },
|
||||
Define_Specifiers
|
||||
# undef Entry
|
||||
|
||||
# pragma pop_macro( "global" )
|
||||
# pragma pop_macro( "internal" )
|
||||
# pragma pop_macro( "local_persist" )
|
||||
};
|
||||
|
||||
return lookup[ specifier ];
|
||||
}
|
||||
|
||||
inline
|
||||
Type to_type( StrC str )
|
||||
{
|
||||
local_persist
|
||||
u32 keymap[ Num_Specifiers ];
|
||||
do_once_start
|
||||
for ( u32 index = 0; index < Num_Specifiers; index++ )
|
||||
{
|
||||
StrC enum_str = to_str( (Type)index );
|
||||
|
||||
// We subtract 1 to remove the null terminator
|
||||
// This is because the tokens lexed are not null terminated.
|
||||
keymap[index] = crc32( enum_str.Ptr, enum_str.Len - 1);
|
||||
}
|
||||
do_once_end
|
||||
|
||||
u32 hash = crc32( str.Ptr, str.Len );
|
||||
|
||||
for ( u32 index = 0; index < Num_Specifiers; index++ )
|
||||
{
|
||||
if ( keymap[index] == hash )
|
||||
return (Type)index;
|
||||
}
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
# undef Define_Specifiers
|
||||
}
|
||||
using SpecifierT = ESpecifier::Type;
|
@ -1,3 +1,5 @@
|
||||
#pragma region Gen Interface
|
||||
|
||||
// Initialize the library.
|
||||
// This currently just initializes the CodePool.
|
||||
void init();
|
||||
@ -32,6 +34,7 @@ void set_allocator_string_table( AllocatorInfo string_allocator );
|
||||
void set_allocator_type_table ( AllocatorInfo type_reg_allocator );
|
||||
|
||||
#pragma region Upfront
|
||||
|
||||
CodeAttributes def_attributes( StrC content );
|
||||
CodeComment def_comment ( StrC content );
|
||||
|
||||
@ -122,9 +125,11 @@ CodeBody def_struct_body ( s32 num, ... );
|
||||
CodeBody def_struct_body ( s32 num, Code* codes );
|
||||
CodeBody def_union_body ( s32 num, ... );
|
||||
CodeBody def_union_body ( s32 num, Code* codes );
|
||||
|
||||
#pragma endregion Upfront
|
||||
|
||||
#pragma region Parsing
|
||||
|
||||
CodeClass parse_class ( StrC class_def );
|
||||
CodeEnum parse_enum ( StrC enum_def );
|
||||
CodeBody parse_export_body ( StrC export_def );
|
||||
@ -142,13 +147,18 @@ CodeTypedef parse_typedef ( StrC typedef_def );
|
||||
CodeUnion parse_union ( StrC union_def );
|
||||
CodeUsing parse_using ( StrC using_def );
|
||||
CodeVar parse_variable ( StrC var_def );
|
||||
|
||||
#pragma endregion Parsing
|
||||
|
||||
#pragma region Untyped text
|
||||
|
||||
sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va );
|
||||
StrC token_fmt_impl( sw, ... );
|
||||
|
||||
Code untyped_str ( StrC content);
|
||||
Code untyped_fmt ( char const* fmt, ... );
|
||||
Code untyped_token_fmt( char const* fmt, s32 num_tokens, ... );
|
||||
|
||||
#pragma endregion Untyped text
|
||||
|
||||
#pragma endregion Gen Interface
|
||||
|
@ -8,83 +8,6 @@ using LogFailType = sw(*)(char const*, ...);
|
||||
constexpr LogFailType log_failure = fatal;
|
||||
#endif
|
||||
|
||||
namespace ECode
|
||||
{
|
||||
# define Define_Types \
|
||||
Entry( Untyped ) \
|
||||
Entry( Comment ) \
|
||||
Entry( Access_Private ) \
|
||||
Entry( Access_Protected ) \
|
||||
Entry( Access_Public ) \
|
||||
Entry( PlatformAttributes ) \
|
||||
Entry( Class ) \
|
||||
Entry( Class_Fwd ) \
|
||||
Entry( Class_Body ) \
|
||||
Entry( Enum ) \
|
||||
Entry( Enum_Fwd ) \
|
||||
Entry( Enum_Body ) \
|
||||
Entry( Enum_Class ) \
|
||||
Entry( Enum_Class_Fwd ) \
|
||||
Entry( Execution ) \
|
||||
Entry( Export_Body ) \
|
||||
Entry( Extern_Linkage ) \
|
||||
Entry( Extern_Linkage_Body ) \
|
||||
Entry( Friend ) \
|
||||
Entry( Function ) \
|
||||
Entry( Function_Fwd ) \
|
||||
Entry( Function_Body ) \
|
||||
Entry( Global_Body ) \
|
||||
Entry( Module ) \
|
||||
Entry( Namespace ) \
|
||||
Entry( Namespace_Body ) \
|
||||
Entry( Operator ) \
|
||||
Entry( Operator_Fwd ) \
|
||||
Entry( Operator_Member ) \
|
||||
Entry( Operator_Member_Fwd ) \
|
||||
Entry( Operator_Cast ) \
|
||||
Entry( Operator_Cast_Fwd ) \
|
||||
Entry( Parameters ) \
|
||||
Entry( Preprocessor_Include ) \
|
||||
Entry( Specifiers ) \
|
||||
Entry( Struct ) \
|
||||
Entry( Struct_Fwd ) \
|
||||
Entry( Struct_Body ) \
|
||||
Entry( Template ) \
|
||||
Entry( Typedef ) \
|
||||
Entry( Typename ) \
|
||||
Entry( Union ) \
|
||||
Entry( Union_Body) \
|
||||
Entry( Using ) \
|
||||
Entry( Using_Namespace ) \
|
||||
Entry( Variable )
|
||||
|
||||
enum Type : u32
|
||||
{
|
||||
# define Entry( Type ) Type,
|
||||
Define_Types
|
||||
# undef Entry
|
||||
|
||||
Num_Types,
|
||||
Invalid
|
||||
};
|
||||
|
||||
inline
|
||||
StrC to_str( Type type )
|
||||
{
|
||||
static
|
||||
StrC lookup[Num_Types] = {
|
||||
# define Entry( Type ) { sizeof(stringize(Type)), stringize(Type) },
|
||||
Define_Types
|
||||
# undef Entry
|
||||
};
|
||||
|
||||
return lookup[ type ];
|
||||
}
|
||||
|
||||
# undef Define_Types
|
||||
}
|
||||
using CodeT = ECode::Type;
|
||||
|
||||
// Used to indicate if enum definitoin is an enum class or regular enum.
|
||||
enum class EnumT : u8
|
||||
{
|
||||
@ -95,183 +18,6 @@ enum class EnumT : u8
|
||||
constexpr EnumT EnumClass = EnumT::Class;
|
||||
constexpr EnumT EnumRegular = EnumT::Regular;
|
||||
|
||||
namespace EOperator
|
||||
{
|
||||
# define Define_Operators \
|
||||
Entry( Assign, = ) \
|
||||
Entry( Assign_Add, += ) \
|
||||
Entry( Assign_Subtract, -= ) \
|
||||
Entry( Assign_Multiply, *= ) \
|
||||
Entry( Assign_Divide, /= ) \
|
||||
Entry( Assign_Modulo, %= ) \
|
||||
Entry( Assign_BAnd, &= ) \
|
||||
Entry( Assign_BOr, |= ) \
|
||||
Entry( Assign_BXOr, ^= ) \
|
||||
Entry( Assign_LShift, <<= ) \
|
||||
Entry( Assign_RShift, >>= ) \
|
||||
Entry( Increment, ++ ) \
|
||||
Entry( Decrement, -- ) \
|
||||
Entry( Unary_Plus, + ) \
|
||||
Entry( Unary_Minus, - ) \
|
||||
Entry( UnaryNot, ! ) \
|
||||
Entry( Add, + ) \
|
||||
Entry( Subtract, - ) \
|
||||
Entry( Multiply, * ) \
|
||||
Entry( Divide, / ) \
|
||||
Entry( Modulo, % ) \
|
||||
Entry( BNot, ~ ) \
|
||||
Entry( BAnd, & ) \
|
||||
Entry( BOr, | ) \
|
||||
Entry( BXOr, ^ ) \
|
||||
Entry( LShift, << ) \
|
||||
Entry( RShift, >> ) \
|
||||
Entry( LAnd, && ) \
|
||||
Entry( LOr, || ) \
|
||||
Entry( LEqual, == ) \
|
||||
Entry( LNot, != ) \
|
||||
Entry( Lesser, < ) \
|
||||
Entry( Greater, > ) \
|
||||
Entry( LesserEqual, <= ) \
|
||||
Entry( GreaterEqual, >= ) \
|
||||
Entry( Subscript, [] ) \
|
||||
Entry( Indirection, * ) \
|
||||
Entry( AddressOf, & ) \
|
||||
Entry( MemberOfPointer, -> ) \
|
||||
Entry( PtrToMemOfPtr, ->* ) \
|
||||
Entry( FunctionCall, () )
|
||||
|
||||
enum Type : u32
|
||||
{
|
||||
# define Entry( Type_, Token_ ) Type_,
|
||||
Define_Operators
|
||||
# undef Entry
|
||||
Comma,
|
||||
|
||||
Num_Ops,
|
||||
Invalid
|
||||
};
|
||||
|
||||
inline
|
||||
char const* to_str( Type op )
|
||||
{
|
||||
local_persist
|
||||
char const* lookup[ Num_Ops ] = {
|
||||
# define Entry( Type_, Token_ ) stringize(Token_),
|
||||
Define_Operators
|
||||
# undef Entry
|
||||
","
|
||||
};
|
||||
|
||||
return lookup[ op ];
|
||||
}
|
||||
|
||||
# undef Define_Operators
|
||||
}
|
||||
using OperatorT = EOperator::Type;
|
||||
|
||||
namespace ESpecifier
|
||||
{
|
||||
/*
|
||||
Note: The following are handled separately:
|
||||
attributes
|
||||
alignas
|
||||
*/
|
||||
|
||||
# define Define_Specifiers \
|
||||
Entry( Invalid, INVALID ) \
|
||||
Entry( Consteval, consteval ) \
|
||||
Entry( Constexpr, constexpr ) \
|
||||
Entry( Constinit, constinit ) \
|
||||
Entry( Explicit, explicit ) \
|
||||
Entry( External_Linkage, extern ) \
|
||||
Entry( Global, global ) \
|
||||
Entry( Inline, inline ) \
|
||||
Entry( Internal_Linkage, internal ) \
|
||||
Entry( Local_Persist, local_persist ) \
|
||||
Entry( Mutable, mutable ) \
|
||||
Entry( Ptr, * ) \
|
||||
Entry( Ref, & ) \
|
||||
Entry( Register, register ) \
|
||||
Entry( RValue, && ) \
|
||||
Entry( Static, static ) \
|
||||
Entry( Thread_Local, thread_local ) \
|
||||
Entry( Volatile, volatile ) \
|
||||
Entry( Virtual, virtual ) \
|
||||
Entry( Const, const ) \
|
||||
Entry( Final, final ) \
|
||||
Entry( Override, override )
|
||||
|
||||
enum Type : u32
|
||||
{
|
||||
# define Entry( Specifier, Code ) Specifier,
|
||||
Define_Specifiers
|
||||
# undef Entry
|
||||
|
||||
Num_Specifiers,
|
||||
};
|
||||
|
||||
inline
|
||||
bool is_trailing( Type specifier )
|
||||
{
|
||||
return specifier > Virtual;
|
||||
}
|
||||
|
||||
// Specifier to string
|
||||
inline
|
||||
StrC to_str( Type specifier )
|
||||
{
|
||||
local_persist
|
||||
StrC lookup[ Num_Specifiers ] = {
|
||||
# pragma push_macro( "global" )
|
||||
# pragma push_macro( "internal" )
|
||||
# pragma push_macro( "local_persist" )
|
||||
# undef global
|
||||
# undef internal
|
||||
# undef local_persist
|
||||
|
||||
# define Entry( Spec_, Code_ ) { sizeof(stringize(Code_)), stringize(Code_) },
|
||||
Define_Specifiers
|
||||
# undef Entry
|
||||
|
||||
# pragma pop_macro( "global" )
|
||||
# pragma pop_macro( "internal" )
|
||||
# pragma pop_macro( "local_persist" )
|
||||
};
|
||||
|
||||
return lookup[ specifier ];
|
||||
}
|
||||
|
||||
inline
|
||||
Type to_type( StrC str )
|
||||
{
|
||||
local_persist
|
||||
u32 keymap[ Num_Specifiers ];
|
||||
do_once_start
|
||||
for ( u32 index = 0; index < Num_Specifiers; index++ )
|
||||
{
|
||||
StrC enum_str = to_str( (Type)index );
|
||||
|
||||
// We subtract 1 to remove the null terminator
|
||||
// This is because the tokens lexed are not null terminated.
|
||||
keymap[index] = crc32( enum_str.Ptr, enum_str.Len - 1);
|
||||
}
|
||||
do_once_end
|
||||
|
||||
u32 hash = crc32( str.Ptr, str.Len );
|
||||
|
||||
for ( u32 index = 0; index < Num_Specifiers; index++ )
|
||||
{
|
||||
if ( keymap[index] == hash )
|
||||
return (Type)index;
|
||||
}
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
# undef Define_Specifiers
|
||||
}
|
||||
using SpecifierT = ESpecifier::Type;
|
||||
|
||||
enum class AccessSpec : u32
|
||||
{
|
||||
Default,
|
||||
|
@ -507,6 +507,13 @@ char* adt_parse_number( ADT_Node* node, char* base_str )
|
||||
{
|
||||
node_props = EADT_PROPS_IS_HEX;
|
||||
}
|
||||
|
||||
/* bail if ZPL_ADT_PROPS_IS_HEX is unset but we get 'x' on input */
|
||||
if ( char_to_lower( *e ) == 'x' && ( node_props != EADT_PROPS_IS_HEX ) )
|
||||
{
|
||||
return ++base_str;
|
||||
}
|
||||
|
||||
while ( char_is_hex_digit( *e ) || char_to_lower( *e ) == 'x' )
|
||||
{
|
||||
buf[ ib++ ] = *e++;
|
||||
@ -795,155 +802,185 @@ ADT_Error adt_str_to_number_strict( ADT_Node* node )
|
||||
|
||||
u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b32 has_header, char delim )
|
||||
{
|
||||
CSV_Error err = ECSV_Error__NONE;
|
||||
CSV_Error error = ECSV_Error__NONE;
|
||||
GEN_ASSERT_NOT_NULL( root );
|
||||
GEN_ASSERT_NOT_NULL( text );
|
||||
zero_item( root );
|
||||
|
||||
adt_make_branch( root, allocator, NULL, has_header ? false : true );
|
||||
|
||||
char* p = text;
|
||||
char* b = p;
|
||||
char* e = p;
|
||||
char* currentChar = text;
|
||||
char* beginChar;
|
||||
char* endChar;
|
||||
|
||||
sw colc = 0;
|
||||
sw total_colc = 0;
|
||||
sw columnIndex = 0;
|
||||
sw totalColumnIndex = 0;
|
||||
|
||||
do
|
||||
{
|
||||
char d = 0;
|
||||
p = zpl_cast( char* ) str_trim( p, false );
|
||||
if ( *p == 0 )
|
||||
char delimiter = 0;
|
||||
currentChar = zpl_cast( char* ) str_trim( currentChar, false );
|
||||
|
||||
if ( *currentChar == 0 )
|
||||
break;
|
||||
ADT_Node row_item = { 0 };
|
||||
row_item.type = EADT_TYPE_STRING;
|
||||
#ifndef GEN_PARSER_DISABLE_ANALYSIS
|
||||
row_item.name_style = EADT_NAME_STYLE_NO_QUOTES;
|
||||
#endif
|
||||
|
||||
ADT_Node rowItem = { 0 };
|
||||
rowItem.type = EADT_TYPE_STRING;
|
||||
|
||||
#ifndef GEN_PARSER_DISABLE_ANALYSIS
|
||||
rowItem.name_style = EADT_NAME_STYLE_NO_QUOTES;
|
||||
#endif
|
||||
|
||||
/* handle string literals */
|
||||
if ( *p == '"' )
|
||||
if ( *currentChar == '"' )
|
||||
{
|
||||
p = b = e = p + 1;
|
||||
row_item.string = b;
|
||||
#ifndef GEN_PARSER_DISABLE_ANALYSIS
|
||||
row_item.name_style = EADT_NAME_STYLE_DOUBLE_QUOTE;
|
||||
#endif
|
||||
currentChar += 1;
|
||||
beginChar = currentChar;
|
||||
endChar = currentChar;
|
||||
rowItem.string = beginChar;
|
||||
#ifndef GEN_PARSER_DISABLE_ANALYSIS
|
||||
rowItem.name_style = EADT_NAME_STYLE_DOUBLE_QUOTE;
|
||||
#endif
|
||||
do
|
||||
{
|
||||
e = zpl_cast( char* ) str_skip( e, '"' );
|
||||
if ( *e && *( e + 1 ) == '"' )
|
||||
endChar = zpl_cast( char* ) str_skip( endChar, '"' );
|
||||
|
||||
if ( *endChar && *( endChar + 1 ) == '"' )
|
||||
{
|
||||
e += 2;
|
||||
endChar += 2;
|
||||
}
|
||||
else
|
||||
break;
|
||||
} while ( *e );
|
||||
if ( *e == 0 )
|
||||
}
|
||||
while ( *endChar );
|
||||
|
||||
if ( *endChar == 0 )
|
||||
{
|
||||
GEN_CSV_ASSERT( "unmatched quoted string" );
|
||||
err = ECSV_Error__UNEXPECTED_END_OF_INPUT;
|
||||
return err;
|
||||
error = ECSV_Error__UNEXPECTED_END_OF_INPUT;
|
||||
return error;
|
||||
}
|
||||
*e = 0;
|
||||
p = zpl_cast( char* ) str_trim( e + 1, true );
|
||||
d = *p;
|
||||
|
||||
*endChar = 0;
|
||||
currentChar = zpl_cast( char* ) str_trim( endChar + 1, true );
|
||||
delimiter = * currentChar;
|
||||
|
||||
/* unescape escaped quotes (so that unescaped text escapes :) */
|
||||
{
|
||||
char* ep = b;
|
||||
char* escapedChar = beginChar;
|
||||
do
|
||||
{
|
||||
if ( *ep == '"' && *( ep + 1 ) == '"' )
|
||||
if ( *escapedChar == '"' && *( escapedChar + 1 ) == '"' )
|
||||
{
|
||||
mem_move( ep, ep + 1, str_len( ep ) );
|
||||
mem_move( escapedChar, escapedChar + 1, str_len( escapedChar ) );
|
||||
}
|
||||
ep++;
|
||||
} while ( *ep );
|
||||
escapedChar++;
|
||||
}
|
||||
while ( *escapedChar );
|
||||
}
|
||||
}
|
||||
else if ( *p == delim )
|
||||
else if ( *currentChar == delim )
|
||||
{
|
||||
d = *p;
|
||||
row_item.string = "";
|
||||
delimiter = * currentChar;
|
||||
rowItem.string = "";
|
||||
}
|
||||
else if ( *p )
|
||||
else if ( *currentChar )
|
||||
{
|
||||
/* regular data */
|
||||
b = e = p;
|
||||
row_item.string = b;
|
||||
beginChar = currentChar;
|
||||
endChar = currentChar;
|
||||
rowItem.string = beginChar;
|
||||
|
||||
do
|
||||
{
|
||||
e++;
|
||||
} while ( *e && *e != delim && *e != '\n' );
|
||||
if ( *e )
|
||||
endChar++;
|
||||
}
|
||||
while ( * endChar && * endChar != delim && * endChar != '\n' );
|
||||
|
||||
if ( * endChar )
|
||||
{
|
||||
p = zpl_cast( char* ) str_trim( e, true );
|
||||
while ( char_is_space( *( e - 1 ) ) )
|
||||
currentChar = zpl_cast( char* ) str_trim( endChar, true );
|
||||
|
||||
while ( char_is_space( *( endChar - 1 ) ) )
|
||||
{
|
||||
e--;
|
||||
endChar--;
|
||||
}
|
||||
d = *p;
|
||||
*e = 0;
|
||||
|
||||
delimiter = * currentChar;
|
||||
* endChar = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
d = 0;
|
||||
p = e;
|
||||
delimiter = 0;
|
||||
currentChar = endChar;
|
||||
}
|
||||
|
||||
/* check if number and process if so */
|
||||
b32 skip_number = false;
|
||||
char* num_p = b;
|
||||
do
|
||||
{
|
||||
if ( ! char_is_hex_digit( *num_p ) && ( ! str_find( "+-.eExX", *num_p ) ) )
|
||||
{
|
||||
skip_number = true;
|
||||
break;
|
||||
}
|
||||
} while ( *num_p++ );
|
||||
char* num_p = beginChar;
|
||||
|
||||
if ( ! skip_number )
|
||||
// We only consider hexadecimal values if they start with 0x
|
||||
if ( str_len(num_p) > 2 && num_p[0] == '0' && (num_p[1] == 'x' || num_p[1] == 'X') )
|
||||
{
|
||||
adt_str_to_number( &row_item );
|
||||
num_p += 2; // skip '0x' prefix
|
||||
do
|
||||
{
|
||||
if (!char_is_hex_digit(*num_p))
|
||||
{
|
||||
skip_number = true;
|
||||
break;
|
||||
}
|
||||
} while (*num_p++);
|
||||
}
|
||||
else
|
||||
{
|
||||
skip_number = true;
|
||||
}
|
||||
|
||||
if (!skip_number)
|
||||
{
|
||||
adt_str_to_number(&rowItem);
|
||||
}
|
||||
}
|
||||
|
||||
if ( colc >= root->nodes.num() )
|
||||
if ( columnIndex >= root->nodes.num() )
|
||||
{
|
||||
adt_append_arr( root, NULL );
|
||||
}
|
||||
|
||||
root->nodes[ colc ].nodes.append( row_item );
|
||||
root->nodes[ columnIndex ].nodes.append( rowItem );
|
||||
|
||||
if ( d == delim )
|
||||
if ( delimiter == delim )
|
||||
{
|
||||
colc++;
|
||||
p++;
|
||||
columnIndex++;
|
||||
currentChar++;
|
||||
}
|
||||
else if ( d == '\n' || d == 0 )
|
||||
else if ( delimiter == '\n' || delimiter == 0 )
|
||||
{
|
||||
/* check if number of rows is not mismatched */
|
||||
if ( total_colc < colc )
|
||||
total_colc = colc;
|
||||
else if ( total_colc != colc )
|
||||
if ( totalColumnIndex < columnIndex )
|
||||
totalColumnIndex = columnIndex;
|
||||
|
||||
else if ( totalColumnIndex != columnIndex )
|
||||
{
|
||||
GEN_CSV_ASSERT( "mismatched rows" );
|
||||
err = ECSV_Error__MISMATCHED_ROWS;
|
||||
return err;
|
||||
error = ECSV_Error__MISMATCHED_ROWS;
|
||||
return error;
|
||||
}
|
||||
colc = 0;
|
||||
if ( d != 0 )
|
||||
p++;
|
||||
|
||||
columnIndex = 0;
|
||||
|
||||
if ( delimiter != 0 )
|
||||
currentChar++;
|
||||
}
|
||||
} while ( *p );
|
||||
}
|
||||
while ( *currentChar );
|
||||
|
||||
if ( root->nodes.num() == 0 )
|
||||
{
|
||||
GEN_CSV_ASSERT( "unexpected end of input. stream is empty." );
|
||||
err = ECSV_Error__UNEXPECTED_END_OF_INPUT;
|
||||
return err;
|
||||
error = ECSV_Error__UNEXPECTED_END_OF_INPUT;
|
||||
return error;
|
||||
}
|
||||
|
||||
/* consider first row as a header. */
|
||||
@ -958,7 +995,7 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
return error;
|
||||
}
|
||||
|
||||
void csv_free( CSV_Object* obj )
|
||||
|
@ -3,6 +3,7 @@
|
||||
#define GEN_EXPOSE_BACKEND
|
||||
#include "gen.cpp"
|
||||
#include "filesystem/gen.scanner.hpp"
|
||||
#include "helpers/gen.helper.hpp"
|
||||
|
||||
using namespace gen;
|
||||
|
||||
@ -46,7 +47,7 @@ int gen_main()
|
||||
Code string_ops = scan_file( "dependencies/gen.string_ops.hpp" );
|
||||
Code printing = scan_file( "dependencies/gen.printing.hpp" );
|
||||
Code containers = scan_file( "dependencies/gen.containers.hpp" );
|
||||
Core hashing = scan_file( "dependencies/gen.hashing.hpp" );
|
||||
Code hashing = scan_file( "dependencies/gen.hashing.hpp" );
|
||||
Code string = scan_file( "dependencies/gen.string.hpp" );
|
||||
Code file_handling = scan_file( "dependencies/gen.file_handling.hpp" );
|
||||
Code parsing = scan_file( "dependencies/gen.parsing.hpp" );
|
||||
@ -60,18 +61,20 @@ int gen_main()
|
||||
deps_header.print( header_start );
|
||||
deps_header.print( nspace_macro );
|
||||
deps_header.print_fmt( "GEN_NS_BEGIN\n\n");
|
||||
deps_header.print( macros );
|
||||
deps_header.print( basic_types );
|
||||
deps_header.print( debug );
|
||||
deps_header.print( memory );
|
||||
deps_header.print( string_ops );
|
||||
deps_header.print( printing );
|
||||
deps_header.print( containers );
|
||||
deps_header.print( hashing );
|
||||
deps_header.print( string );
|
||||
deps_header.print( file_handling );
|
||||
deps_header.print( parsing );
|
||||
deps_header.print( timing );
|
||||
|
||||
deps_header.print( macros );
|
||||
deps_header.print( basic_types );
|
||||
deps_header.print( debug );
|
||||
deps_header.print( memory );
|
||||
deps_header.print( string_ops );
|
||||
deps_header.print( printing );
|
||||
deps_header.print( containers );
|
||||
deps_header.print( hashing );
|
||||
deps_header.print( string );
|
||||
deps_header.print( file_handling );
|
||||
deps_header.print( parsing );
|
||||
deps_header.print( timing );
|
||||
|
||||
deps_header.print_fmt( "GEN_NS_END\n\n");
|
||||
deps_header.write();
|
||||
}
|
||||
@ -96,13 +99,16 @@ int gen_main()
|
||||
deps_impl.print( impl_start );
|
||||
deps_impl.print( header );
|
||||
deps_impl.print_fmt( "\nGEN_NS_BEGIN\n");
|
||||
deps_impl.print( debug );
|
||||
deps_impl.print( string_ops );
|
||||
deps_impl.print( printing );
|
||||
deps_impl.print( memory );
|
||||
deps_impl.print( parsing );
|
||||
deps_impl.print( string );
|
||||
deps_impl.print( timing );
|
||||
|
||||
deps_impl.print( debug );
|
||||
deps_impl.print( string_ops );
|
||||
deps_impl.print( printing );
|
||||
deps_impl.print( hashing );
|
||||
deps_impl.print( memory );
|
||||
deps_impl.print( parsing );
|
||||
deps_impl.print( string );
|
||||
deps_impl.print( timing );
|
||||
|
||||
deps_impl.print_fmt( "GEN_NS_END\n\n");
|
||||
deps_impl.write();
|
||||
}
|
||||
@ -116,6 +122,10 @@ int gen_main()
|
||||
Code interface = scan_file( "components/gen.interface.hpp" );
|
||||
Code header_end = scan_file( "components/gen.header_end.hpp" );
|
||||
|
||||
CodeBody ecode = gen_ecode( "./components/ECode.csv" );
|
||||
CodeBody eoperator = gen_eoperator( "./components/EOperator.csv" );
|
||||
CodeBody especifier = gen_especifier( "./components/ESpecifier.csv" );
|
||||
|
||||
Code builder = scan_file( "filesystem/gen.builder.hpp" );
|
||||
|
||||
Builder
|
||||
@ -126,11 +136,20 @@ int gen_main()
|
||||
header.print( header_start );
|
||||
header.print( nspace_macro );
|
||||
header.print_fmt( "GEN_NS_BEGIN\n\n");
|
||||
header.print( types );
|
||||
header.print( data_structs );
|
||||
header.print( interface );
|
||||
header.print( header_end );
|
||||
header.print( builder );
|
||||
|
||||
header.print_fmt("#pragma region Types");
|
||||
header.print( types );
|
||||
header.print( ecode );
|
||||
header.print( eoperator );
|
||||
header.print( especifier );
|
||||
header.print_fmt("#pragma endregion Types");
|
||||
|
||||
header.print( data_structs );
|
||||
header.print( interface );
|
||||
header.print( header_end );
|
||||
|
||||
header.print( builder );
|
||||
|
||||
header.print_fmt( "GEN_NS_END\n\n");
|
||||
header.print( pop_ignores );
|
||||
header.write();
|
||||
@ -157,14 +176,16 @@ int gen_main()
|
||||
impl.print( impl_start );
|
||||
impl.print( header );
|
||||
impl.print_fmt( "\nGEN_NS_BEGIN\n\n");
|
||||
impl.print( data );
|
||||
impl.print( ast_case_macros );
|
||||
impl.print( ast );
|
||||
impl.print( interface );
|
||||
impl.print( upfront );
|
||||
impl.print( parsing );
|
||||
impl.print( untyped );
|
||||
impl.print( builder );
|
||||
|
||||
impl.print( data );
|
||||
impl.print( ast_case_macros );
|
||||
impl.print( ast );
|
||||
impl.print( interface );
|
||||
impl.print( upfront );
|
||||
impl.print( parsing );
|
||||
impl.print( untyped );
|
||||
|
||||
impl.print( builder );
|
||||
impl.print_fmt( "GEN_NS_END\n\n");
|
||||
impl.print( pop_ignores );
|
||||
impl.write();
|
||||
|
@ -22,6 +22,9 @@
|
||||
GEN_NS_BEGIN
|
||||
|
||||
#include "components/gen.types.hpp"
|
||||
#include "components/gen.ecode.hpp"
|
||||
#include "components/gen.eoperator.hpp"
|
||||
#include "components/gen.especifier.hpp"
|
||||
#include "components/gen.data_structures.hpp"
|
||||
#include "components/gen.interface.hpp"
|
||||
#include "components/gen.header_end.hpp"
|
||||
|
215
project/helpers/gen.helper.hpp
Normal file
215
project/helpers/gen.helper.hpp
Normal file
@ -0,0 +1,215 @@
|
||||
#pragma once
|
||||
|
||||
#include "gen.hpp"
|
||||
|
||||
using namespace gen;
|
||||
|
||||
CodeBody gen_ecode( char const* path )
|
||||
{
|
||||
char scratch_mem[kilobytes(1)];
|
||||
Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) );
|
||||
|
||||
file_read_contents( scratch, zero_terminate, path );
|
||||
|
||||
CSV_Object csv_nodes;
|
||||
csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false );
|
||||
|
||||
Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes;
|
||||
|
||||
String enum_entries = String::make_reserve( GlobalAllocator, kilobytes(1) );
|
||||
String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(1) );
|
||||
|
||||
for ( ADT_Node node : enum_strs )
|
||||
{
|
||||
char const* code = node.string;
|
||||
enum_entries.append_fmt( "%s,\n", code );
|
||||
to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", code, code );
|
||||
}
|
||||
|
||||
CodeEnum enum_code = parse_enum( token_fmt( "entries", (StrC)enum_entries, stringize(
|
||||
enum Type : u32
|
||||
{
|
||||
<entries>
|
||||
NumTypes
|
||||
};
|
||||
)));
|
||||
|
||||
#pragma push_macro( "local_persist" )
|
||||
#undef local_persist
|
||||
CodeFn to_str = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize(
|
||||
StrC to_str( Type type )
|
||||
{
|
||||
local_persist
|
||||
StrC lookup[] {
|
||||
<entries>
|
||||
};
|
||||
|
||||
return lookup[ type ];
|
||||
}
|
||||
)));
|
||||
#pragma pop_macro( "local_persist" )
|
||||
|
||||
CodeNamespace nspace = def_namespace( name(ECode), def_namespace_body( args( enum_code, to_str ) ) );
|
||||
|
||||
CodeUsing code_t = def_using( name(CodeT), def_type( name(ECode::Type) ) );
|
||||
|
||||
return def_global_body( args( nspace, code_t ) );
|
||||
}
|
||||
|
||||
CodeBody gen_eoperator( char const* path )
|
||||
{
|
||||
char scratch_mem[kilobytes(1)];
|
||||
Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) );
|
||||
|
||||
file_read_contents( scratch, zero_terminate, path );
|
||||
|
||||
CSV_Object csv_nodes;
|
||||
csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false );
|
||||
|
||||
Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes;
|
||||
Array<ADT_Node> str_strs = csv_nodes.nodes[1].nodes;
|
||||
|
||||
String enum_entries = String::make_reserve( GlobalAllocator, kilobytes(1) );
|
||||
String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(1) );
|
||||
|
||||
for (uw idx = 0; idx < enum_strs.num(); idx++)
|
||||
{
|
||||
char const* enum_str = enum_strs[idx].string;
|
||||
char const* entry_to_str = str_strs [idx].string;
|
||||
|
||||
enum_entries.append_fmt( "%s,\n", enum_str );
|
||||
to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str);
|
||||
}
|
||||
|
||||
CodeEnum enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, stringize(
|
||||
enum Type : u32
|
||||
{
|
||||
<entries>
|
||||
NumOps
|
||||
};
|
||||
)));
|
||||
|
||||
#pragma push_macro( "local_persist" )
|
||||
#undef local_persist
|
||||
CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, stringize(
|
||||
StrC to_str( Type op )
|
||||
{
|
||||
local_persist
|
||||
StrC lookup[] {
|
||||
<entries>
|
||||
};
|
||||
|
||||
return lookup[ op ];
|
||||
}
|
||||
)));
|
||||
#pragma pop_macro( "local_persist" )
|
||||
|
||||
CodeNamespace nspace = def_namespace( name(EOperator), def_namespace_body( args( enum_code, to_str ) ) );
|
||||
|
||||
CodeUsing operator_t = def_using( name(OperatorT), def_type( name(EOperator::Type) ) );
|
||||
|
||||
return def_global_body( args( nspace, operator_t ) );
|
||||
}
|
||||
|
||||
CodeBody gen_especifier( char const* path )
|
||||
{
|
||||
char scratch_mem[kilobytes(1)];
|
||||
Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) );
|
||||
|
||||
file_read_contents( scratch, zero_terminate, path );
|
||||
|
||||
CSV_Object csv_nodes;
|
||||
csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false );
|
||||
|
||||
Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes;
|
||||
Array<ADT_Node> str_strs = csv_nodes.nodes[1].nodes;
|
||||
|
||||
String enum_entries = String::make_reserve( GlobalAllocator, kilobytes(1) );
|
||||
String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(1) );
|
||||
|
||||
for (uw idx = 0; idx < enum_strs.num(); idx++)
|
||||
{
|
||||
char const* enum_str = enum_strs[idx].string;
|
||||
char const* entry_to_str = str_strs [idx].string;
|
||||
|
||||
enum_entries.append_fmt( "%s,\n", enum_str );
|
||||
to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str);
|
||||
}
|
||||
|
||||
CodeEnum enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, stringize(
|
||||
enum Type : u32
|
||||
{
|
||||
<entries>
|
||||
NumSpecifiers
|
||||
};
|
||||
)));
|
||||
|
||||
CodeFn is_trailing = parse_function(token_fmt("specifier", (StrC)to_str_entries, stringize(
|
||||
bool is_trailing( Type specifier )
|
||||
{
|
||||
return specifier > Virtual;
|
||||
}
|
||||
)));
|
||||
|
||||
#pragma push_macro( "local_persist" )
|
||||
#pragma push_macro( "do_once_start" )
|
||||
#pragma push_macro( "do_once_end" )
|
||||
#undef local_persist
|
||||
#undef do_once_start
|
||||
#undef do_once_end
|
||||
|
||||
CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, stringize(
|
||||
StrC to_str( Type type )
|
||||
{
|
||||
local_persist
|
||||
StrC lookup[] {
|
||||
<entries>
|
||||
};
|
||||
|
||||
return lookup[ type ];
|
||||
}
|
||||
)));
|
||||
|
||||
CodeFn to_type = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize(
|
||||
Type to_type( StrC str )
|
||||
{
|
||||
local_persist
|
||||
u32 keymap[ NumSpecifiers ];
|
||||
do_once_start
|
||||
for ( u32 index = 0; index < NumSpecifiers; index++ )
|
||||
{
|
||||
StrC enum_str = to_str( (Type)index );
|
||||
|
||||
// We subtract 1 to remove the null terminator
|
||||
// This is because the tokens lexed are not null terminated.
|
||||
keymap[index] = crc32( enum_str.Ptr, enum_str.Len - 1);
|
||||
}
|
||||
do_once_end
|
||||
|
||||
u32 hash = crc32( str.Ptr, str.Len );
|
||||
|
||||
for ( u32 index = 0; index < NumSpecifiers; index++ )
|
||||
{
|
||||
if ( keymap[index] == hash )
|
||||
return (Type)index;
|
||||
}
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
)));
|
||||
|
||||
#pragma pop_macro( "local_persist" )
|
||||
#pragma pop_macro( "do_once_start" )
|
||||
#pragma pop_macro( "do_once_end" )
|
||||
|
||||
CodeNamespace nspace = def_namespace( name(ESpecifier), def_namespace_body( args( enum_code, is_trailing, to_str, to_type ) ) );
|
||||
|
||||
CodeUsing specifier_t = def_using( name(SpecifierT), def_type( name(ESpecifier::Type) ) );
|
||||
|
||||
return def_global_body( args( nspace, specifier_t ) );
|
||||
}
|
||||
|
||||
CodeBody gen_etoktype()
|
||||
{
|
||||
return CodeInvalid;
|
||||
}
|
@ -12,8 +12,11 @@ AlignConsecutiveAssignments:
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields: AcrossComments
|
||||
AlignConsecutiveDeclarations: AcrossComments
|
||||
AlignConsecutiveMacros: AcrossComments
|
||||
AlignEscapedNewlines: Right
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: true
|
||||
AcrossComments: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: DontAlign
|
||||
|
||||
AlignTrailingComments: true
|
||||
@ -90,10 +93,10 @@ FixNamespaceComments: true
|
||||
IncludeBlocks: Preserve
|
||||
|
||||
|
||||
IndentCaseBlocks: true
|
||||
IndentCaseLabels: true
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: true
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentRequires: true
|
||||
IndentWidth: 4
|
||||
|
@ -3,6 +3,7 @@
|
||||
#define GEN_EXPOSE_BACKEND
|
||||
#include "gen.cpp"
|
||||
#include "filesystem/gen.scanner.hpp"
|
||||
#include "helpers/gen.helper.hpp"
|
||||
|
||||
using namespace gen;
|
||||
|
||||
@ -87,6 +88,7 @@ int gen_main()
|
||||
Code string_ops = scan_file( project_dir "dependencies/gen.string_ops.hpp" );
|
||||
Code printing = scan_file( project_dir "dependencies/gen.printing.hpp" );
|
||||
Code containers = scan_file( project_dir "dependencies/gen.containers.hpp" );
|
||||
Code hashing = scan_file( project_dir "dependencies/gen.hashing.hpp" );
|
||||
Code string = scan_file( project_dir "dependencies/gen.string.hpp" );
|
||||
Code file_handling = scan_file( project_dir "dependencies/gen.file_handling.hpp" );
|
||||
Code parsing = scan_file( project_dir "dependencies/gen.parsing.hpp" );
|
||||
@ -101,6 +103,7 @@ int gen_main()
|
||||
header.print( string_ops );
|
||||
header.print( printing );
|
||||
header.print( containers );
|
||||
header.print( hashing );
|
||||
header.print( string );
|
||||
header.print( file_handling );
|
||||
header.print( parsing );
|
||||
@ -115,10 +118,21 @@ int gen_main()
|
||||
Code interface = scan_file( project_dir "components/gen.interface.hpp" );
|
||||
Code header_end = scan_file( project_dir "components/gen.header_end.hpp" );
|
||||
|
||||
CodeBody ecode = gen_ecode( project_dir "components/ECode.csv" );
|
||||
CodeBody eoperator = gen_eoperator( project_dir "components/EOperator.csv" );
|
||||
CodeBody especifier = gen_especifier( project_dir "components/ESpecifier.csv" );
|
||||
|
||||
Code builder = scan_file( project_dir "filesystem/gen.builder.hpp" );
|
||||
|
||||
header.print_fmt( "GEN_NS_BEGIN\n\n" );
|
||||
|
||||
header.print_fmt("#pragma region Types");
|
||||
header.print( types );
|
||||
header.print( ecode );
|
||||
header.print( eoperator );
|
||||
header.print( especifier );
|
||||
header.print_fmt("#pragma endregion Types");
|
||||
|
||||
header.print( data_structs );
|
||||
header.print( interface );
|
||||
header.print( header_end );
|
||||
|
@ -1,163 +0,0 @@
|
||||
# Format Style Options - Created with Clang Power Tools
|
||||
---
|
||||
AccessModifierOffset: -4
|
||||
|
||||
AlignAfterOpenBracket: BlockIndent
|
||||
AlignArrayOfStructures: Right
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: true
|
||||
AlignCompound: true
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields: AcrossComments
|
||||
AlignConsecutiveDeclarations: AcrossComments
|
||||
AlignConsecutiveMacros: AcrossComments
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: DontAlign
|
||||
|
||||
AlignTrailingComments: true
|
||||
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: None
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
|
||||
BitFieldColonSpacing: Both
|
||||
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
|
||||
# BreakAfterAttributes: Always
|
||||
# BreakArrays: false
|
||||
# BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Allman
|
||||
BreakBeforeInheritanceComma: true
|
||||
BreakInheritanceList: BeforeComma
|
||||
BreakBeforeConceptDeclarations: true
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakStringLiterals: true
|
||||
|
||||
ColumnLimit: 180
|
||||
|
||||
CompactNamespaces: true
|
||||
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth : 4
|
||||
|
||||
ContinuationIndentWidth: 4
|
||||
|
||||
Cpp11BracedListStyle: false
|
||||
|
||||
DeriveLineEnding: true
|
||||
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
|
||||
FixNamespaceComments: true
|
||||
|
||||
IncludeBlocks: Preserve
|
||||
|
||||
|
||||
IndentCaseBlocks: true
|
||||
IndentCaseLabels: true
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentRequires: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
|
||||
# InsertNewlineAtEOF: true
|
||||
InsertTrailingCommas: Wrapped
|
||||
|
||||
LambdaBodyIndentation: OuterScope
|
||||
|
||||
Language: Cpp
|
||||
|
||||
MaxEmptyLinesToKeep: 4
|
||||
|
||||
NamespaceIndentation: All
|
||||
|
||||
PointerAlignment: Left
|
||||
|
||||
QualifierAlignment: Leave
|
||||
|
||||
ReferenceAlignment: Left
|
||||
|
||||
ReflowComments: true
|
||||
|
||||
# RequiresExpressionIndentation: OuterScope
|
||||
|
||||
SeparateDefinitionBlocks: Always
|
||||
|
||||
ShortNamespaceLines: 40
|
||||
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: true
|
||||
SpaceAfterTemplateKeyword: false
|
||||
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: true
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatementsExceptControlMacros
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpacesBeforeTrailingComments: 4
|
||||
|
||||
SpaceInEmptyBlock: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInAngles: true
|
||||
SpacesInCStyleCastParentheses: true
|
||||
SpacesInConditionalStatement: true
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: 20
|
||||
SpacesInParentheses: true
|
||||
SpacesInSquareBrackets: true
|
||||
|
||||
Standard: c++17
|
||||
|
||||
TabWidth: 4
|
||||
|
||||
UseTab: ForIndentation
|
||||
...
|
Loading…
Reference in New Issue
Block a user