aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--buildtools/cmake/RTTI.cmake31
-rw-r--r--buildtools/codegen/CodegenDefinition.hpp1
-rw-r--r--buildtools/codegen/CodegenOutput.cpp7
-rw-r--r--buildtools/codegen/CodegenOutput.hpp17
-rw-r--r--buildtools/codegen/main.cpp255
-rw-r--r--buildtools/codegen/tests/examples/TestEnum.hpp8
7 files changed, 177 insertions, 146 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3d349c5..19518bf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,6 +4,8 @@ project(ProjectBrussel LANGUAGES C CXX)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
+include(buildtools/cmake/RTTI.cmake)
+
find_package(OpenGL REQUIRED)
add_subdirectory(3rdparty/glfw)
add_subdirectory(3rdparty/glm)
@@ -53,6 +55,8 @@ target_link_libraries(meta_codegen PRIVATE
commonthings
)
+target_flag_rtti(meta_codegen OFF)
+
# ==============================================================================
# add_executable requires at least one source file
diff --git a/buildtools/cmake/RTTI.cmake b/buildtools/cmake/RTTI.cmake
new file mode 100644
index 0000000..b948497
--- /dev/null
+++ b/buildtools/cmake/RTTI.cmake
@@ -0,0 +1,31 @@
+function(target_flag_rtti_msvc TARGET_NAME ENABLED)
+ if(ENABLED)
+ target_compile_options(${TARGET_NAME} PRIVATE /GR)
+ else()
+ target_compile_options(${TARGET_NAME} PRIVATE /GR-)
+ endif()
+endfunction()
+
+function(target_flag_rtti_gcc TARGET_NAME ENABLED)
+ if(ENABLED)
+ target_compile_options(${TARGET_NAME} PRIVATE -frtti)
+ else()
+ target_compile_options(${TARGET_NAME} PRIVATE -fno-rtti)
+ endif()
+endfunction()
+
+function(target_flag_rtti TARGET_NAME ENABLED)
+ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
+ target_flag_rtti_msvc(${TARGET_NAME} ${ENABLED})
+ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")
+ target_flag_rtti_msvc(${TARGET_NAME} ${ENABLED})
+ elseif(CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "GNU")
+ target_flag_rtti_gcc(${TARGET_NAME} ${ENABLED})
+ endif()
+ elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+ target_flag_rtti_gcc(${TARGET_NAME} ${ENABLED})
+ else()
+ message(FATAL "target_flag_rtti(): Unknown compiler ${CMAKE_CXX_COMPILER_ID}")
+ endif()
+endfunction()
diff --git a/buildtools/codegen/CodegenDefinition.hpp b/buildtools/codegen/CodegenDefinition.hpp
new file mode 100644
index 0000000..6f70f09
--- /dev/null
+++ b/buildtools/codegen/CodegenDefinition.hpp
@@ -0,0 +1 @@
+#pragma once
diff --git a/buildtools/codegen/CodegenOutput.cpp b/buildtools/codegen/CodegenOutput.cpp
new file mode 100644
index 0000000..214ded6
--- /dev/null
+++ b/buildtools/codegen/CodegenOutput.cpp
@@ -0,0 +1,7 @@
+#include "CodegenOutput.hpp"
+
+#include <utility>
+
+void CodegenOutput::AddOutputThing(CodegenOutputThing thing) {
+ mOutThings.push_back(std::move(thing));
+}
diff --git a/buildtools/codegen/CodegenOutput.hpp b/buildtools/codegen/CodegenOutput.hpp
new file mode 100644
index 0000000..660feb1
--- /dev/null
+++ b/buildtools/codegen/CodegenOutput.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <string>
+#include <vector>
+
+// A generic "thing" (could be anything, comments, string-concated functionsm, etc.) to spit into the output file
+struct CodegenOutputThing {
+ std::string text;
+};
+
+class CodegenOutput {
+private:
+ std::vector<CodegenOutputThing> mOutThings;
+
+public:
+ void AddOutputThing(CodegenOutputThing thing);
+};
diff --git a/buildtools/codegen/main.cpp b/buildtools/codegen/main.cpp
index cf31bd8..9f89191 100644
--- a/buildtools/codegen/main.cpp
+++ b/buildtools/codegen/main.cpp
@@ -1,4 +1,5 @@
#include "CodegenLookupTable.h"
+#include "CodegenOutput.hpp"
#include "Macros.hpp"
#include "ScopeGuard.hpp"
#include "Utils.hpp"
@@ -65,124 +66,10 @@ struct InputDefinitionEnum {
EnumUnderlyingType underlyingType;
};
-enum LexedTokenType {
- // stb_c_lexer token types, ported over
- LTT_Identifier,
- LTT_IntLiteral,
- LTT_FloatLiteral,
- LTT_DqString,
- LTT_SqString,
- LTT_CharLiteral,
- LTT_OperEquals,
- LTT_OperNotEquals,
- LTT_OperLessOrEqual,
- LTT_OperGreaterOrEqual,
- LTT_OperAndAnd,
- LTT_OperOrOr,
- LTT_OperShiftLeft,
- LTT_OperShiftRight,
- LTT_OperIncrement,
- LTT_OperDecrement,
- LTT_OperAddAssign,
- LTT_OperSubAssign,
- LTT_OperMulAssign,
- LTT_OperDivAssign,
- LTT_OperModAssign,
- LTT_OperAndAssign,
- LTT_OperOrAssign,
- LTT_OperXorAssign,
- LTT_OperArrow,
- LTT_OperEqualArrow,
- LTT_OperShiftLeflAssign,
- LTT_OperShiftRightAssign,
-
- // Custom token types
- LTT_OperAdd,
- LTT_OperSub,
- LTT_OperMul,
- LTT_OperDiv,
- LTT_OperMod,
- LTT_ParenOpen,
- LTT_ParenClose,
- LTT_BracketOpen,
- LTT_BracketClose,
- LTT_BraceOpen,
- LTT_BraceClose,
-
- LTT_COUNT,
-};
-
-// NOTE: maintain with CLEX_* defined in stb_c_lexer.h
-LUT_DECL_VAR(gClexTokens, int, CLEX_first_unused_token, LexedTokenType, LTT_COUNT) {
- LUT_MAP_FOR(gClexTokens);
- LUT_MAP(CLEX_id, LTT_Identifier);
- LUT_MAP(CLEX_intlit, LTT_IntLiteral);
- LUT_MAP(CLEX_floatlit, LTT_FloatLiteral);
- LUT_MAP(CLEX_dqstring, LTT_DqString);
- LUT_MAP(CLEX_sqstring, LTT_SqString);
- LUT_MAP(CLEX_charlit, LTT_CharLiteral);
- LUT_MAP(CLEX_eq, LTT_OperEquals);
- LUT_MAP(CLEX_noteq, LTT_OperNotEquals);
- LUT_MAP(CLEX_lesseq, LTT_OperLessOrEqual);
- LUT_MAP(CLEX_greatereq, LTT_OperGreaterOrEqual);
- LUT_MAP(CLEX_andand, LTT_OperAndAnd);
- LUT_MAP(CLEX_oror, LTT_OperOrOr);
- LUT_MAP(CLEX_shl, LTT_OperShiftLeft);
- LUT_MAP(CLEX_shr, LTT_OperShiftRight);
- LUT_MAP(CLEX_plusplus, LTT_OperIncrement);
- LUT_MAP(CLEX_minusminus, LTT_OperDecrement);
- LUT_MAP(CLEX_pluseq, LTT_OperAddAssign);
- LUT_MAP(CLEX_minuseq, LTT_OperSubAssign);
- LUT_MAP(CLEX_muleq, LTT_OperMulAssign);
- LUT_MAP(CLEX_diveq, LTT_OperDivAssign);
- LUT_MAP(CLEX_modeq, LTT_OperModAssign);
- LUT_MAP(CLEX_andeq, LTT_OperAndAssign);
- LUT_MAP(CLEX_oreq, LTT_OperOrAssign);
- LUT_MAP(CLEX_xoreq, LTT_OperXorAssign);
- LUT_MAP(CLEX_arrow, LTT_OperArrow);
- LUT_MAP(CLEX_eqarrow, LTT_OperEqualArrow);
- LUT_MAP(CLEX_shleq, LTT_OperShiftLeflAssign);
- LUT_MAP(CLEX_shreq, LTT_OperShiftRightAssign);
-}
-
-LUT_DECL_VAR(gSingleCharTokens, char, std::numeric_limits<char>::max() + 1, LexedTokenType, LTT_COUNT) {
- LUT_MAP_FOR(gSingleCharTokens);
- LUT_MAP('+', LTT_OperAdd);
- LUT_MAP('-', LTT_OperSub);
- LUT_MAP('*', LTT_OperMul);
- LUT_MAP('/', LTT_OperDiv);
- LUT_MAP('%', LTT_OperMod);
- LUT_MAP('(', LTT_ParenOpen);
- LUT_MAP(')', LTT_ParenClose);
- LUT_MAP('[', LTT_BracketOpen);
- LUT_MAP(']', LTT_BracketClose);
- LUT_MAP('{', LTT_BraceOpen);
- LUT_MAP('}', LTT_BraceClose);
-}
-
-// See stb_c_lexer.h's comments, here are a few additinos that aren't made clear in the file:
-// - `lexer->token` (noted as "token" below) after calling stb_c_lexer_get_token() contains either:
-// 1. 0 <= token < 256: an ASCII character (more precisely a single char that the lexer ate; technically can be an incomplete code unit)
-// 2. token < 0: an unknown token
-// 3. One of the `CLEX_*` enums: a special, recognized token such as an operator
-LexedTokenType MapFromStb(const stb_lexer& lexer) {
- if (lexer.token >= 0 && lexer.token < 256) {
- // Single char token
- char c = lexer.token;
- return LUT_LOOKUP(gSingleCharTokens, lexer.token);
- }
-
- return LUT_LOOKUP(gClexTokens, lexer.token);
-}
-int MapToStb(LexedTokenType token) {
- // TODO
-
- return LUT_REV_LOOKUP(gClexTokens, token);
-}
-
struct StbLexerToken {
std::string text;
- LexedTokenType type;
+ // Can either be CLEX_* values, or just chars for single character tokens
+ int type;
};
void CheckBraceDepth(int braceDpeth) {
@@ -200,17 +87,37 @@ void HandleInputFile(std::string_view source) {
std::vector<StbLexerToken> tokens;
std::vector<InputDefinitionStruct> foundStructs;
+ InputDefinitionStruct currStruct;
std::vector<InputDefinitionEnum> foundEnums;
+ InputDefinitionEnum currEnum;
+
+ auto PushFoundStruct = [&]() {
+ foundStructs.push_back(std::move(currStruct));
+ currStruct = {};
+ };
+ auto PushFoundEnum = [&]() {
+ foundEnums.push_back(std::move(currEnum));
+ currEnum = {};
+ };
enum NextMatchingConstruct {
NMC_None,
NMC_Enum,
NMC_StructClass,
} matchingConstruct = NMC_None;
+ bool matchingConstructInBody = false;
+
+ bool matchingDirectiveParams = false;
int bracePairDepth = 0;
while (true) {
+ // See stb_c_lexer.h's comments, here are a few additinos that aren't made clear in the file:
+ // - `lexer->token` (noted as "token" below) after calling stb_c_lexer_get_token() contains either:
+ // 1. 0 <= token < 256: an ASCII character (more precisely a single char that the lexer ate; technically can be an incomplete code unit)
+ // 2. token < 0: an unknown token
+ // 3. One of the `CLEX_*` enums: a special, recognized token such as an operator
+
int stbToken = stb_c_lexer_get_token(&lexer);
if (stbToken == 0) {
// EOF
@@ -225,13 +132,53 @@ void HandleInputFile(std::string_view source) {
switch (lexer.token) {
case CLEX_id: {
- std::string_view idenText(lexer.string, lexer.string_len);
- if (idenText == "struct"sv || idenText == "class"sv) {
- // TODO
- matchingConstruct = NMC_StructClass;
- } else if (idenText == "enum"sv) {
- // TODO
- matchingConstruct = NMC_Enum;
+ // WORKAROUND: stb_c_lexer doens't set string_len properly when parsing identifiers
+ std::string_view idenText(lexer.string);
+ // std::string_view idenText(lexer.string, lexer.string_len);
+ switch (matchingConstruct) {
+ case NMC_StructClass: {
+ if (matchingConstructInBody) {
+ // TODO
+ }
+ } break;
+
+ case NMC_Enum: {
+ if (matchingConstructInBody) {
+ printf("[DEBUG] found enum element '%s'\n", lexer.string);
+ currEnum.elements.push_back(InputDefinitionEnumElement{
+ .name = std::string(idenText),
+ .value = 0, // TODO parse
+ });
+ } else {
+ currEnum.name = std::string(idenText);
+ }
+ } break;
+
+ default: {
+ if (idenText == "struct"sv || idenText == "class"sv) {
+ printf("[DEBUG] found struct named\n");
+ matchingConstruct = NMC_StructClass;
+ } else if (idenText == "enum"sv) {
+ printf("[DEBUG] found enum\n");
+ matchingConstruct = NMC_Enum;
+ } else if (idenText == "BRUSSEL_CLASS"sv) {
+ // TODO
+ printf("[DEBUG] found BRUSSEL_CLASS\n");
+ } else if (idenText == "BRUSSEL_ENUM"sv) {
+ matchingDirectiveParams = true;
+ printf("[DEBUG] found BRUSSEL_ENUM\n");
+ }
+
+ if (matchingDirectiveParams) {
+ for (auto& foundEnum : foundEnums) {
+ if (foundEnum.name == idenText) {
+ // TODO generate data
+ break;
+ }
+ }
+ matchingDirectiveParams = false;
+ }
+ } break;
}
} break;
@@ -265,30 +212,49 @@ void HandleInputFile(std::string_view source) {
} break;
- case CLEX_parse_error: {
- fprintf(stderr, "[ERROR] stb_c_lexer countered a parse error.");
- // TODO how to handle?
+ case '{': {
+ bracePairDepth++;
+ CheckBraceDepth(bracePairDepth);
+
+ switch (matchingConstruct) {
+ case NMC_StructClass:
+ case NMC_Enum: {
+ matchingConstructInBody = true;
+ } break;
+
+ default: break;
+ }
} break;
- default: {
- if (lexer.token >= 0 && lexer.token < 256) {
- // Single char token
- char c = lexer.token;
- switch (c) {
- case '{': {
- bracePairDepth++;
- CheckBraceDepth(bracePairDepth);
- } break;
+ case '}': {
+ bracePairDepth--;
+ CheckBraceDepth(bracePairDepth);
+
+ switch (matchingConstruct) {
+ case NMC_StructClass: {
+ matchingConstruct = NMC_None;
+ matchingConstructInBody = false;
+ } break;
- case '}': {
- bracePairDepth--;
- CheckBraceDepth(bracePairDepth);
- } break;
- }
- } else {
- fprintf(stderr, "[ERROR] Encountered unknown token %ld.", lexer.token);
+ case NMC_Enum: {
+ printf("[DEBUG] committed enum '%s'\n", currEnum.name.c_str());
+ for (auto& elm : currEnum.elements) {
+ printf(" - element %s = %" PRId64 "\n", elm.name.c_str(), elm.value);
+ }
+
+ matchingConstruct = NMC_None;
+ matchingConstructInBody = false;
+ PushFoundEnum();
+ } break;
+
+ default: break;
}
} break;
+
+ case CLEX_parse_error: {
+ fprintf(stderr, "[ERROR] stb_c_lexer countered a parse error.");
+ // TODO how to handle?
+ } break;
}
}
@@ -345,9 +311,6 @@ void HandleArgument(InputOpcode opcode, std::string_view operand) {
}
int main(int argc, char* argv[]) {
- LUT_INIT(gClexTokens);
- LUT_INIT(gSingleCharTokens);
-
// TODO better arg parser
// option 1: use cxxopts and positional arguments
// option 1: take one argument only, being a json objecet
@@ -359,7 +322,7 @@ int main(int argc, char* argv[]) {
auto separatorLoc = arg.find(':');
if (separatorLoc != std::string_view::npos) {
auto opcode = ParseInputOpcode(arg.substr(0, separatorLoc));
- auto operand = arg.substr(separatorLoc);
+ auto operand = arg.substr(separatorLoc + 1);
HandleArgument(opcode, operand);
}
}
diff --git a/buildtools/codegen/tests/examples/TestEnum.hpp b/buildtools/codegen/tests/examples/TestEnum.hpp
new file mode 100644
index 0000000..aaa3d74
--- /dev/null
+++ b/buildtools/codegen/tests/examples/TestEnum.hpp
@@ -0,0 +1,8 @@
+#include "MacrosCodegen.hpp"
+
+enum MyEnum {
+ EnumElement1,
+ EnumElement2,
+ EnumElement3,
+};
+BRUSSEL_ENUM(MyEnum, GenInfo);