Skip to content

Commit

Permalink
feat: allow multiple 'with' fields
Browse files Browse the repository at this point in the history
  • Loading branch information
zaucy committed May 23, 2024
1 parent a7b28ab commit 4ccb569
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 75 deletions.
75 changes: 51 additions & 24 deletions ecsact/detail/grammar.hh
Original file line number Diff line number Diff line change
Expand Up @@ -668,17 +668,25 @@ struct system_component_statement {
static constexpr auto value = lexy::noop;
};

struct with_fields : lexy::token_production {
static constexpr auto rule = lexy::dsl::list(
lexy::dsl::p<field_name>,
lexy::dsl::sep(lexy::dsl::comma)
);
static constexpr auto value = lexy::as_list<std::vector<std::string_view>>;
};

static constexpr auto capability = lexy::dsl::p<filter> |
lexy::dsl::p<access> | lexy::dsl::p<assignment>;

static constexpr auto rule = capability >> lexy::dsl::p<type_name> >>
lexy::dsl::opt(lexy::dsl::p<with_keyword> >> lexy::dsl::p<field_name>);
lexy::dsl::opt(lexy::dsl::p<with_keyword> >> lexy::dsl::p<with_fields>);

static constexpr auto value = lexy::callback<ecsact_statement>(
[](
ecsact_system_capability cap,
std::string_view component_name,
std::optional<std::string_view> with_entity_field_name
ecsact_system_capability cap,
std::string_view component_name,
std::optional<std::vector<std::string_view>> with_entity_field_names
) {
ecsact_statement statement{
.type = ECSACT_STATEMENT_SYSTEM_COMPONENT,
Expand All @@ -691,10 +699,15 @@ struct system_component_statement {
data.component_name.data = component_name.data();
data.component_name.length = static_cast<int>(component_name.size());

if(with_entity_field_name) {
data.with_entity_field_name.data = with_entity_field_name->data();
data.with_entity_field_name.length =
static_cast<int>(with_entity_field_name->size());
if(with_entity_field_names) {
data.with_field_name_list_count =
static_cast<int>(with_entity_field_names->size());
for(int i = 0; data.with_field_name_list_count > i; ++i) {
data.with_field_name_list[i] = ecsact_statement_sv{
.data = (*with_entity_field_names)[i].data(),
.length = static_cast<int>((*with_entity_field_names)[i].size()),
};
}
}

return statement;
Expand Down Expand Up @@ -758,21 +771,35 @@ struct with_statement {
static constexpr auto value = lexy::noop;
};

struct with_fields : lexy::token_production {
static constexpr auto rule = lexy::dsl::list(
lexy::dsl::p<field_name>,
lexy::dsl::sep(lexy::dsl::comma)
);
static constexpr auto value = lexy::as_list<std::vector<std::string_view>>;
};

static constexpr auto rule = lexy::dsl::p<with_keyword> >>
lexy::dsl::p<field_name>;
lexy::dsl::p<with_fields>;

static constexpr auto value = lexy::callback<ecsact_statement>(
[](std::vector<std::string_view> field_names) {
auto data = ecsact_system_with_statement{};
data.with_field_name_list_count = field_names.size();

for(int i = 0; data.with_field_name_list_count > i; ++i) {
data.with_field_name_list[i] = ecsact_statement_sv{
.data = field_names[i].data(),
.length = static_cast<int>(field_names[i].size()),
};
}

static constexpr auto value =
lexy::callback<ecsact_statement>([](std::string_view field_name) {
return ecsact_statement{
.type = ECSACT_STATEMENT_SYSTEM_WITH_ENTITY,
.data{.system_with_entity_statement{
.with_entity_field_name{
.data = field_name.data(),
.length = static_cast<int>(field_name.size()),
},
}},
.type = ECSACT_STATEMENT_SYSTEM_WITH,
.data{.system_with_statement{data}},
};
});
}
);
};

struct system_notify_statement {
Expand Down Expand Up @@ -1003,13 +1030,13 @@ using system_component_level_statement = statement<
system_component_statement,
with_statement>;

constexpr char system_with_entity_level_statement_name[] =
constexpr char system_with_level_statement_name[] =
"system with entity level statement";
constexpr char system_with_entity_level_statement_expected_message[] =
constexpr char system_with_level_statement_expected_message[] =
"expected system with entity level statement";
using system_with_entity_level_statement = statement<
system_with_entity_level_statement_name,
system_with_entity_level_statement_expected_message,
using system_with_level_statement = statement<
system_with_level_statement_name,
system_with_level_statement_expected_message,
system_component_statement,
with_statement>;

Expand Down
4 changes: 2 additions & 2 deletions ecsact/ecsact_parse_statement.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ static auto context_grammar(ecsact_statement_type context_type, Fn&& fn) {
return fn(grammar::entity_field_level_statement{});
case ECSACT_STATEMENT_SYSTEM_COMPONENT:
return fn(grammar::system_component_level_statement{});
case ECSACT_STATEMENT_SYSTEM_WITH_ENTITY:
return fn(grammar::system_with_entity_level_statement{});
case ECSACT_STATEMENT_SYSTEM_WITH:
return fn(grammar::system_with_level_statement{});
case ECSACT_STATEMENT_PACKAGE:
return fn(grammar::package_level_statement{});
case ECSACT_STATEMENT_IMPORT:
Expand Down
15 changes: 10 additions & 5 deletions ecsact/parse/statements.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#include "ecsact/runtime/common.h"
#include "ecsact/runtime/definitions.h"

/** Maximum number of 'with' fields that may be parsed */
#define ECSACT_MAX_WITH_FIELDS 32

typedef enum {
ECSACT_STATEMENT_NONE,
ECSACT_STATEMENT_UNKNOWN,
Expand All @@ -22,7 +25,7 @@ typedef enum {
ECSACT_STATEMENT_ENTITY_FIELD,
ECSACT_STATEMENT_SYSTEM_COMPONENT,
ECSACT_STATEMENT_SYSTEM_GENERATES,
ECSACT_STATEMENT_SYSTEM_WITH_ENTITY,
ECSACT_STATEMENT_SYSTEM_WITH,
ECSACT_STATEMENT_ENTITY_CONSTRAINT,
ECSACT_STATEMENT_SYSTEM_NOTIFY,
ECSACT_STATEMENT_SYSTEM_NOTIFY_COMPONENT,
Expand Down Expand Up @@ -83,12 +86,14 @@ typedef struct {
typedef struct {
ecsact_system_capability capability;
ecsact_statement_sv component_name;
ecsact_statement_sv with_entity_field_name;
int with_field_name_list_count;
ecsact_statement_sv with_field_name_list[ECSACT_MAX_WITH_FIELDS];
} ecsact_system_component_statement;

typedef struct {
ecsact_statement_sv with_entity_field_name;
} ecsact_system_with_entity_statement;
int with_field_name_list_count;
ecsact_statement_sv with_field_name_list[ECSACT_MAX_WITH_FIELDS];
} ecsact_system_with_statement;

typedef struct {
bool optional;
Expand Down Expand Up @@ -143,7 +148,7 @@ typedef union {
ecsact_field_statement field_statement;
ecsact_user_type_field_statement user_type_field_statement;
ecsact_system_component_statement system_component_statement;
ecsact_system_with_entity_statement system_with_entity_statement;
ecsact_system_with_statement system_with_statement;
ecsact_entity_constraint_statement entity_constraint_statement;
ecsact_system_notify_statement system_notify_statement;
ecsact_system_notify_component_statement system_notify_component_statement;
Expand Down
3 changes: 2 additions & 1 deletion test/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
load("@rules_cc//cc:defs.bzl", "cc_test")
load("@ecsact_parse//bazel:copts.bzl", "copts")
load("@rules_cc//cc:defs.bzl", "cc_test")

# keep sorted
_TESTS = [
Expand Down Expand Up @@ -36,6 +36,7 @@ cc_library(
deps = [
":parse_test_util",
"@ecsact_parse",
"@magic_enum",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
Expand Down
8 changes: 6 additions & 2 deletions test/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ module(name = "ecsact_parse_test")

bazel_dep(name = "rules_cc", version = "0.0.9")
bazel_dep(name = "googletest", version = "1.14.0")

bazel_dep(name = "magic_enum", version = "0.9.3")
bazel_dep(name = "ecsact_parse")
local_path_override(module_name = "ecsact_parse", path = "..")
local_path_override(
module_name = "ecsact_parse",
path = "..",
)

bazel_dep(name = "toolchains_llvm", version = "1.0.0", dev_dependency = True)
bazel_dep(name = "hedron_compile_commands", dev_dependency = True)

git_override(
module_name = "hedron_compile_commands",
commit = "204aa593e002cbd177d30f11f54cff3559110bb9",
Expand Down
Loading

0 comments on commit 4ccb569

Please sign in to comment.