From 1d51cf6fc5ce9903f58d2181aacbc472a697c8a8 Mon Sep 17 00:00:00 2001 From: Andrew MacDonald Date: Sat, 23 Aug 2025 15:36:39 -0300 Subject: [PATCH] Structs basic parse implementation --- FxScript.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ FxScript.hpp | 14 ++++++++++++++ Main.fxS | 6 ++++++ 3 files changed, 60 insertions(+) diff --git a/FxScript.cpp b/FxScript.cpp index 8110624..bf1328c 100644 --- a/FxScript.cpp +++ b/FxScript.cpp @@ -164,6 +164,9 @@ FxAstNode* FxConfigScript::TryParseKeyword(FxAstBlock* parent_block) // global [type] [name] ; constexpr FxHash kw_global = FxHashStr("global"); + // struct [name] { } + constexpr FxHash kw_struct = FxHashStr("struct"); + // return ; constexpr FxHash kw_return = FxHashStr("return"); @@ -183,6 +186,27 @@ FxAstNode* FxConfigScript::TryParseKeyword(FxAstBlock* parent_block) EatToken(TT::Identifier); return ParseVarDeclare(&mScopes[0]); } + if (hash == kw_struct) { + EatToken(TT::Identifier); + Token& name = EatToken(TT::Identifier); + FxAstStructDecl* struct_decl = FX_SCRIPT_ALLOC_NODE(FxAstStructDecl); + struct_decl->Name = &name; + + EatToken(TT::LBrace); + + while (GetToken().Type != TT::RBrace && mTokenIndex < mTokens.Size()) { + FxAstVarDecl* member = ParseVarDeclare(); + + // Expect a semicolon after each member declaration + EatToken(TT::Semicolon); + + struct_decl->Members.push_back(member); + } + + EatToken(TT::RBrace); + + return struct_decl; + } if (hash == kw_return) { EatToken(TT::Identifier); @@ -1552,6 +1576,22 @@ void FxScriptInterpreter::Visit(FxAstNode* node) Visit(vardecl->Assignment); } + else if (node->NodeType == FX_AST_STRUCTDECL) { + FxAstStructDecl* structdecl = reinterpret_cast(node); + + // Visit all member variable declarations to ensure they are valid + for (FxAstNode* member_node : structdecl->Members) { + if (member_node->NodeType != FX_AST_VARDECL) { + continue; + } + + FxAstVarDecl* member_decl = reinterpret_cast(member_node); + Visit(member_decl); + } + + FxScriptScope* scope = mCurrentScope; + scope->Structs.Insert(*structdecl); + } else if (node->NodeType == FX_AST_ASSIGN) { FxAstAssign* assign = reinterpret_cast(node); VisitAssignment(assign); diff --git a/FxScript.hpp b/FxScript.hpp index 8e1c216..b9dd4d6 100644 --- a/FxScript.hpp +++ b/FxScript.hpp @@ -118,6 +118,9 @@ enum FxAstType FX_AST_VARDECL, FX_AST_ASSIGN, + // Type defs + FX_AST_STRUCTDECL, + // Actions FX_AST_ACTIONDECL, FX_AST_ACTIONCALL, @@ -205,6 +208,16 @@ struct FxAstVarDecl : public FxAstNode bool DefineAsGlobal = false; }; +struct FxAstStructDecl : public FxAstNode +{ + FxAstStructDecl() + { + this->NodeType = FX_AST_STRUCTDECL; + } + FxTokenizer::Token* Name = nullptr; + std::vector Members; +}; + struct FxAstDocComment : public FxAstNode { FxAstDocComment() @@ -374,6 +387,7 @@ struct FxScriptScope { FxMPPagedArray Vars; FxMPPagedArray Actions; + FxMPPagedArray Structs; FxScriptScope* Parent = nullptr; diff --git a/Main.fxS b/Main.fxS index bd1b66a..64a9ef0 100644 --- a/Main.fxS +++ b/Main.fxS @@ -10,4 +10,10 @@ action test_action(int x, int y) #log("Value: ", value); } +struct TestStruct +{ + int a; + int b; +}; + test_action(2, 3);