From b61ad4a51adaca8db4ee9564bb0eea8628ea4672 Mon Sep 17 00:00:00 2001 From: Doyle Date: Sat, 23 Mar 2019 16:08:12 +1100 Subject: [PATCH] Add support for funciton default param initialiser --- Code/DqnInspect.h | 325 +++++++++++++------------- Data/DqnInspect_TestData.h | 17 +- Data/DqnInspect_TestDataGenerated.cpp | 10 +- 3 files changed, 187 insertions(+), 165 deletions(-) diff --git a/Code/DqnInspect.h b/Code/DqnInspect.h index b741888..51cc5ab 100644 --- a/Code/DqnInspect.h +++ b/Code/DqnInspect.h @@ -265,6 +265,10 @@ struct DqnInspect_Struct int members_len; }; +// NOTE(doyle): For compiler testing +// #include "../Data/DqnInspect_TestData.h" +// #include "../Data/DqnInspect_TestDataGenerated.cpp" + #ifdef DQN_INSPECT_EXECUTABLE_IMPLEMENTATION #define _CRT_SECURE_NO_WARNINGS @@ -1288,9 +1292,41 @@ void ParseCPPStruct(CPPTokeniser *tokeniser) void SkipFunctionParam(CPPTokeniser *tokeniser) { CPPToken token = CPPTokeniser_PeekToken(tokeniser); - while (token.type != CPPTokenType::EndOfStream && token.type != CPPTokenType::Comma && - token.type != CPPTokenType::CloseParen) + while (token.type != CPPTokenType::EndOfStream) { + if (token.type == CPPTokenType::OpenParen) + { + for (int level = 1; level != 0;) + { + CPPTokeniser_NextToken(tokeniser); + token = CPPTokeniser_PeekToken(tokeniser); + if (token.type == CPPTokenType::OpenParen) level++; + if (token.type == CPPTokenType::CloseParen) level--; + } + + CPPTokeniser_NextToken(tokeniser); + token = CPPTokeniser_PeekToken(tokeniser); + } + + if (token.type == CPPTokenType::LeftBrace) + { + for (int level = 1; level != 0;) + { + CPPTokeniser_NextToken(tokeniser); + token = CPPTokeniser_PeekToken(tokeniser); + if (token.type == CPPTokenType::LeftBrace) level++; + if (token.type == CPPTokenType::RightBrace) level--; + } + CPPTokeniser_NextToken(tokeniser); + token = CPPTokeniser_PeekToken(tokeniser); + } + + if (token.type == CPPTokenType::CloseParen) + break; + + if (token.type == CPPTokenType::Comma) + break; + CPPTokeniser_NextToken(tokeniser); token = CPPTokeniser_PeekToken(tokeniser); } @@ -1312,9 +1348,8 @@ void ParseCPPInspectPrototype(CPPTokeniser *tokeniser) MemArenaScopedRegion mem_region = MemArena_MakeScopedRegion(&global_main_arena); { LinkedList *link_iterator = nullptr; - token = CPPTokeniser_PeekToken(tokeniser); - if (!ExpectToken(token, CPPTokenType::OpenParen)) return; - token = CPPTokeniser_NextToken(tokeniser); + if (!CPPTokeniser_AcceptTokenIfType(tokeniser, CPPTokenType::OpenParen, &token)) + return; for (token = CPPTokeniser_NextToken(tokeniser); token.type != CPPTokenType::CloseParen && token.type != CPPTokenType::EndOfStream; @@ -1337,20 +1372,18 @@ void ParseCPPInspectPrototype(CPPTokeniser *tokeniser) continue; } - token = CPPTokeniser_NextToken(tokeniser); - char *default_param_start = token.str; + token = CPPTokeniser_PeekToken(tokeniser); + char *default_value_start = token.str; - // NOTE(doyle): Include the quotes in the param value - CPPToken prev_token = CPPTokeniser_PrevToken(tokeniser); - if (prev_token.type == CPPTokenType::String) - default_param_start--; + if (token.type == CPPTokenType::String) // NOTE(doyle): Include the quotes in the param value + default_value_start--; SkipFunctionParam(tokeniser); CPPToken peek_token = CPPTokeniser_PeekToken(tokeniser); if (peek_token.type != CPPTokenType::Comma && peek_token.type != CPPTokenType::CloseParen) continue; - char *default_param_end = peek_token.str; + char *default_value_end = peek_token.str; auto *link = MEM_ARENA_ALLOC_STRUCT(&global_main_arena, LinkedList); *link = {}; @@ -1359,7 +1392,7 @@ void ParseCPPInspectPrototype(CPPTokeniser *tokeniser) link_iterator = link; link->value.name = default_param_name; - link->value.value = StringLiteral(default_param_start, static_cast(default_param_end - default_param_start)); + link->value.value = StringLiteral(default_value_start, static_cast(default_value_end - default_value_start)); } } @@ -1483,121 +1516,127 @@ enum struct InspectMode char *EnumOrStructOrFunctionLexer(CPPTokeniser *tokeniser, char *ptr, b32 lexing_function) { - int indent_level = 0; - bool started_lexing_brace_scope = false; - bool started_lexing_function = false; - int open_paren_level = 0; - int close_paren_level = 0; - for (; ptr;) + // NOTE(doyle): If we're lexing a function we're doing DQN_INSPECT_GENERATE_PROTOTYPE() + // Where we want to lex the macro and then the function following it, so 2 iterations + int iterations = lexing_function ? 2 : 1; + + for (int i = 0; i < iterations; ++i) { - while (CharIsWhitespace(ptr[0])) ptr++; - if (!ptr[0]) break; - - CPPToken *token = CPPTokeniser_MakeToken(tokeniser); - token->str = ptr++; - token->len = 1; - switch(token->str[0]) + int indent_level = 0; + bool started_lexing_brace_scope = false; + bool started_lexing_function = false; + int paren_level = 0; + for (; ptr;) { - case '{': { token->type = CPPTokenType::LeftBrace; started_lexing_brace_scope = true; indent_level++; } break; - case '}': { token->type = CPPTokenType::RightBrace; indent_level--; } break; - case '[': { token->type = CPPTokenType::LeftSqBracket; } break; - case ']': { token->type = CPPTokenType::RightSqBracket; } break; - case '(': { token->type = CPPTokenType::OpenParen; started_lexing_function = true; open_paren_level++; } break; - case ')': { token->type = CPPTokenType::CloseParen; close_paren_level++; } break; - case ',': { token->type = CPPTokenType::Comma; } break; - case ';': { token->type = CPPTokenType::SemiColon; } break; - case '=': { token->type = CPPTokenType::Equals; } break; - case '<': { token->type = CPPTokenType::LessThan; } break; - case '>': { token->type = CPPTokenType::GreaterThan; } break; - case ':': { token->type = CPPTokenType::Colon; } break; - case '*': { token->type = CPPTokenType::Asterisks; } break; - case '/': + while (CharIsWhitespace(ptr[0])) ptr++; + if (!ptr[0]) break; + + CPPToken *token = CPPTokeniser_MakeToken(tokeniser); + token->str = ptr++; + token->len = 1; + switch(token->str[0]) { - token->type = CPPTokenType::FwdSlash; - if (ptr[0] == '/' || ptr[0] == '*') + case '{': { token->type = CPPTokenType::LeftBrace; started_lexing_brace_scope = true; indent_level++; } break; + case '}': { token->type = CPPTokenType::RightBrace; indent_level--; } break; + case '[': { token->type = CPPTokenType::LeftSqBracket; } break; + case ']': { token->type = CPPTokenType::RightSqBracket; } break; + case '(': { token->type = CPPTokenType::OpenParen; started_lexing_function = true; paren_level++; } break; + case ')': { token->type = CPPTokenType::CloseParen; paren_level--; } break; + case ',': { token->type = CPPTokenType::Comma; } break; + case ';': { token->type = CPPTokenType::SemiColon; } break; + case '=': { token->type = CPPTokenType::Equals; } break; + case '<': { token->type = CPPTokenType::LessThan; } break; + case '>': { token->type = CPPTokenType::GreaterThan; } break; + case ':': { token->type = CPPTokenType::Colon; } break; + case '*': { token->type = CPPTokenType::Asterisks; } break; + case '/': { - token->type = CPPTokenType::Comment; - if (ptr[0] == '/') + token->type = CPPTokenType::FwdSlash; + if (ptr[0] == '/' || ptr[0] == '*') { - while (ptr[0] == ' ' || ptr[0] == '\t') ptr++; - token->str = ptr; - while (ptr[0] != '\n') ptr++; - } - else - { - for (;;) + token->type = CPPTokenType::Comment; + if (ptr[0] == '/') { - while (ptr[0] != '*') ptr++; - ptr++; - if (ptr[0] == '\\') break; - token->len = static_cast(ptr - token->str); + while (ptr[0] == ' ' || ptr[0] == '\t') ptr++; + token->str = ptr; + while (ptr[0] != '\n') ptr++; + } + else + { + for (;;) + { + while (ptr[0] != '*') ptr++; + ptr++; + if (ptr[0] == '\\') break; + token->len = static_cast(ptr - token->str); + } } - } - token->len = static_cast(ptr - token->str); - } - } - break; - - default: - { - ptr--; - if (ptr[0] == '"') - { - token->type = CPPTokenType::String; - for (token->str = ++ptr;;) - { - while (ptr[0] != '"') ptr++; token->len = static_cast(ptr - token->str); - if (ptr[-1] != '\\') - { - ptr++; - break; - } } } - else - { - if (CharIsDigit(ptr[0])) - { - while (CharIsDigit(ptr[0]) || ptr[0] == 'x' || ptr[0] == 'b' || ptr[0] == 'e' || ptr[0] == '.' || ptr[0] == 'f') - ptr++; + break; - token->type = CPPTokenType::Number; + default: + { + ptr--; + if (ptr[0] == '"') + { + token->type = CPPTokenType::String; + for (token->str = ++ptr;;) + { + while (ptr[0] != '"') ptr++; + token->len = static_cast(ptr - token->str); + if (ptr[-1] != '\\') + { + ptr++; + break; + } + } } else { - token->type = CPPTokenType::Identifier; - if (CharIsAlpha(ptr[0]) || ptr[0] == '_') + if (CharIsDigit(ptr[0])) { - ptr++; - while (CharIsAlphaNum(ptr[0]) || ptr[0] == '_') ptr++; + while (CharIsDigit(ptr[0]) || ptr[0] == 'x' || ptr[0] == 'b' || ptr[0] == 'e' || ptr[0] == '.' || ptr[0] == 'f') + ptr++; + + token->type = CPPTokenType::Number; } + else + { + token->type = CPPTokenType::Identifier; + if (CharIsAlpha(ptr[0]) || ptr[0] == '_') + { + ptr++; + while (CharIsAlphaNum(ptr[0]) || ptr[0] == '_') ptr++; + } + } + + token->len = static_cast(ptr - token->str); } - token->len = static_cast(ptr - token->str); } - + break; } - break; - } - if (token->len == 0) - { - *token = {}; - tokeniser->tokens_len--; - } - else - { - if (lexing_function) + if (token->len == 0) { - if (started_lexing_function && open_paren_level == close_paren_level && open_paren_level == 2) - return ptr; + *token = {}; + tokeniser->tokens_len--; } else { - if (started_lexing_brace_scope && indent_level == 0) - return ptr; + if (lexing_function) + { + if (started_lexing_function && paren_level == 0) + break; + } + else + { + if (started_lexing_brace_scope && indent_level == 0) + break; + } } } } @@ -1683,45 +1722,25 @@ int main(int argc, char *argv[]) file_include_contents_hash_define_len = extracted_file_name_len; } - if (mode == InspectMode::Code) - { - fprintf(output_file, - "//\n" - "// %s\n" - "//\n" - "\n" - "#ifndef DQN_INSPECT_%.*s\n" - "#define DQN_INSPECT_%.*s\n" - "\n" - " // NOTE: These macros are undefined at the end of the file so to not pollute namespace\n" - "#define ARRAY_COUNT(array) sizeof(array)/sizeof((array)[0])\n" - "#define CHAR_COUNT(str) (ARRAY_COUNT(str) - 1)\n" - "#define STR_AND_LEN(str) str, CHAR_COUNT(str)\n" - "\n", - file_name, - file_include_contents_hash_define_len, - file_include_contents_hash_define, - file_include_contents_hash_define_len, - file_include_contents_hash_define - ); - } - else - { - fprintf(output_file, - "//\n" - "// %s\n" - "//\n" - "\n" - "#ifndef DQN_INSPECT_%.*s\n" - "#define DQN_INSPECT_%.*s\n" - "\n", - file_name, - file_include_contents_hash_define_len, - file_include_contents_hash_define, - file_include_contents_hash_define_len, - file_include_contents_hash_define - ); - } + fprintf(output_file, + "//\n" + "// %s\n" + "//\n" + "\n" + "#ifndef DQN_INSPECT_%.*s\n" + "#define DQN_INSPECT_%.*s\n" + "\n" + " // NOTE: These macros are undefined at the end of the file so to not pollute namespace\n" + "#define ARRAY_COUNT(array) sizeof(array)/sizeof((array)[0])\n" + "#define CHAR_COUNT(str) (ARRAY_COUNT(str) - 1)\n" + "#define STR_AND_LEN(str) str, CHAR_COUNT(str)\n" + "\n", + file_name, + file_include_contents_hash_define_len, + file_include_contents_hash_define, + file_include_contents_hash_define_len, + file_include_contents_hash_define + ); CPPTokeniser tokeniser = {}; tokeniser.spaces_per_indent = 4; @@ -1809,23 +1828,13 @@ int main(int argc, char *argv[]) break; } - if (mode == InspectMode::Code) - { - fprintf(output_file, - "\n#undef ARRAY_COUNT\n" - "#undef CHAR_COUNT\n" - "#undef STR_AND_LEN\n" - "#endif // DQN_INSPECT_%.*s\n\n", - file_include_contents_hash_define_len, - file_include_contents_hash_define); - } - else - { - fprintf(output_file, - "\n#endif // DQN_INSPECT_%.*s\n\n", - file_include_contents_hash_define_len, - file_include_contents_hash_define); - } + fprintf(output_file, + "\n#undef ARRAY_COUNT\n" + "#undef CHAR_COUNT\n" + "#undef STR_AND_LEN\n" + "#endif // DQN_INSPECT_%.*s\n\n", + file_include_contents_hash_define_len, + file_include_contents_hash_define); } fclose(output_file); diff --git a/Data/DqnInspect_TestData.h b/Data/DqnInspect_TestData.h index 391a5e0..3be767a 100644 --- a/Data/DqnInspect_TestData.h +++ b/Data/DqnInspect_TestData.h @@ -4,12 +4,14 @@ DQN_INSPECT enum struct EnumWithMetadata Count, }; -struct V3 { float test; }; +struct V3 { V3(float a, float b) { (void)a; (void)b; } float test; }; struct V4 { float test; }; template struct Array { T data[Size]; }; +enum struct OpenGLShader { Vertex, Count, }; + DQN_INSPECT struct SampleStruct { // #if 0 @@ -34,10 +36,13 @@ DQN_INSPECT struct SampleStruct }; DQN_INSPECT_GENERATE_PROTOTYPE(b = {}, c = nullptr, e = false, f = 1, g = "Hello world") -void Function1(int a, float b, char const *c, bool e, int f, char *g) { } +void Function1(int a, float b, char const *c, bool e, int f, char *g) +{ + (void)a; (void)b; (void)c; (void)e; (void)f; (void)g; +} + +DQN_INSPECT_GENERATE_PROTOTYPE(foo = V3(10, 20), bar = {120, 150}) +void *Function2(V3 foo, V3 bar) { (void)foo; (void)bar; return nullptr; } DQN_INSPECT_GENERATE_PROTOTYPE() -void *Function2() { } - -DQN_INSPECT_GENERATE_PROTOTYPE() -Array const *const Function3(Array const *foobar) { } +Array const *const Function3(Array const *foobar) { (void)foobar; return {}; } diff --git a/Data/DqnInspect_TestDataGenerated.cpp b/Data/DqnInspect_TestDataGenerated.cpp index 52cdaed..2d029e1 100644 --- a/Data/DqnInspect_TestDataGenerated.cpp +++ b/Data/DqnInspect_TestDataGenerated.cpp @@ -7,6 +7,11 @@ #ifndef DQN_INSPECT_DQNINSPECT_TESTDATA_H #define DQN_INSPECT_DQNINSPECT_TESTDATA_H + // NOTE: These macros are undefined at the end of the file so to not pollute namespace +#define ARRAY_COUNT(array) sizeof(array)/sizeof((array)[0]) +#define CHAR_COUNT(str) (ARRAY_COUNT(str) - 1) +#define STR_AND_LEN(str) str, CHAR_COUNT(str) + char const *DqnInspect_EnumWithMetadata_Strings[] = {"Rect", "Count", }; char const *DqnInspect_EnumString(EnumWithMetadata val) @@ -225,8 +230,11 @@ DqnInspect_Struct const *DqnInspect_GetStruct(SampleStruct const *val) } void Function1(int a, float b = {}, char const *c = nullptr, bool e = false, int f = 1, char *g = "Hello world"); -void *Function2(); +void *Function2(V3 foo = V3(10, 20), V3 bar = {120, 150}); Array const *const Function3(Array const *foobar); +#undef ARRAY_COUNT +#undef CHAR_COUNT +#undef STR_AND_LEN #endif // DQN_INSPECT_DQNINSPECT_TESTDATA_H