Skip to content

Commit 16e14f0

Browse files
committed
Add query DSL feature that expands R(S, T, Q) into R(S, T), R(T, Q)
1 parent 78305c4 commit 16e14f0

File tree

10 files changed

+346
-40
lines changed

10 files changed

+346
-40
lines changed

flecs.c

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4746,7 +4746,7 @@ ecs_table_t *flecs_traverse_from_expr(
47464746
const char *ptr = expr;
47474747
if (ptr) {
47484748
ecs_term_t term = {0};
4749-
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term))){
4749+
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term, NULL))){
47504750
if (!ecs_term_is_initialized(&term)) {
47514751
break;
47524752
}
@@ -4809,7 +4809,7 @@ void flecs_defer_from_expr(
48094809
const char *ptr = expr;
48104810
if (ptr) {
48114811
ecs_term_t term = {0};
4812-
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term))){
4812+
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term, NULL))) {
48134813
if (!ecs_term_is_initialized(&term)) {
48144814
break;
48154815
}
@@ -11053,23 +11053,48 @@ ecs_filter_t* ecs_filter_init(
1105311053
const char *name = NULL;
1105411054
const char *ptr = desc->expr;
1105511055
ecs_term_t term = {0};
11056+
ecs_term_id_t extra_args[ECS_PARSER_MAX_ARGS] = {0};
1105611057
int32_t expr_size = 0;
1105711058

1105811059
if (entity) {
1105911060
name = ecs_get_name(world, entity);
1106011061
}
1106111062

11062-
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term))){
11063+
while (ptr[0] &&
11064+
(ptr = ecs_parse_term(world, name, expr, ptr, &term, extra_args)))
11065+
{
1106311066
if (!ecs_term_is_initialized(&term)) {
1106411067
break;
1106511068
}
1106611069

11067-
if (expr_count == expr_size) {
11068-
expr_size = expr_size ? expr_size * 2 : 8;
11069-
expr_terms = ecs_os_realloc_n(expr_terms, ecs_term_t, expr_size);
11070-
}
11070+
int32_t arg = 0;
11071+
11072+
do {
11073+
ecs_assert(arg <= ECS_PARSER_MAX_ARGS, ECS_INTERNAL_ERROR, NULL);
11074+
11075+
if (expr_count == expr_size) {
11076+
expr_size = expr_size ? expr_size * 2 : 8;
11077+
expr_terms = ecs_os_realloc_n(expr_terms, ecs_term_t, expr_size);
11078+
}
11079+
11080+
ecs_term_t *expr_term = &expr_terms[expr_count ++];
11081+
*expr_term = term;
11082+
11083+
if (arg) {
11084+
expr_term->src = expr_term[-1].second;
11085+
expr_term->second = extra_args[arg - 1];
11086+
11087+
if (expr_term->first.name != NULL) {
11088+
expr_term->first.name = ecs_os_strdup(
11089+
expr_term->first.name);
11090+
}
11091+
if (expr_term->src.name != NULL) {
11092+
expr_term->src.name = ecs_os_strdup(
11093+
expr_term->src.name);
11094+
}
11095+
}
11096+
} while (ecs_term_id_is_set(&extra_args[arg ++]));
1107111097

11072-
expr_terms[expr_count ++] = term;
1107311098
if (ptr[0] == '\n') {
1107411099
break;
1107511100
}
@@ -30577,15 +30602,24 @@ const char* flecs_parse_arguments(
3057730602
int64_t column,
3057830603
const char *ptr,
3057930604
char *token,
30580-
ecs_term_t *term)
30605+
ecs_term_t *term,
30606+
ecs_term_id_t *extra_args)
3058130607
{
3058230608
(void)column;
3058330609

3058430610
int32_t arg = 0;
3058530611

30612+
if (extra_args) {
30613+
ecs_os_memset_n(extra_args, 0, ecs_term_id_t, ECS_PARSER_MAX_ARGS);
30614+
}
30615+
30616+
if (!term) {
30617+
arg = 2;
30618+
}
30619+
3058630620
do {
3058730621
if (flecs_valid_token_start_char(ptr[0])) {
30588-
if (arg == 2) {
30622+
if ((arg == ECS_PARSER_MAX_ARGS) || (!extra_args && arg == 2)) {
3058930623
ecs_parser_error(name, expr, (ptr - expr),
3059030624
"too many arguments in term");
3059130625
return NULL;
@@ -30602,6 +30636,8 @@ const char* flecs_parse_arguments(
3060230636
term_id = &term->src;
3060330637
} else if (arg == 1) {
3060430638
term_id = &term->second;
30639+
} else {
30640+
term_id = &extra_args[arg - 2];
3060530641
}
3060630642

3060730643
/* If token is a colon, the token is an identifier followed by a
@@ -30643,7 +30679,9 @@ const char* flecs_parse_arguments(
3064330679
if (ptr[0] == TOK_AND) {
3064430680
ptr = ecs_parse_ws(ptr + 1);
3064530681

30646-
term->id_flags = ECS_PAIR;
30682+
if (term) {
30683+
term->id_flags = ECS_PAIR;
30684+
}
3064730685

3064830686
} else if (ptr[0] == TOK_PAREN_CLOSE) {
3064930687
ptr = ecs_parse_ws(ptr + 1);
@@ -30689,7 +30727,8 @@ const char* flecs_parse_term(
3068930727
const ecs_world_t *world,
3069030728
const char *name,
3069130729
const char *expr,
30692-
ecs_term_t *term_out)
30730+
ecs_term_t *term_out,
30731+
ecs_term_id_t *extra_args)
3069330732
{
3069430733
const char *ptr = expr;
3069530734
char token[ECS_MAX_TOKEN_SIZE] = {0};
@@ -30837,7 +30876,7 @@ const char* flecs_parse_term(
3083730876
ptr = ecs_parse_ws(ptr);
3083830877
} else {
3083930878
ptr = flecs_parse_arguments(
30840-
world, name, expr, (ptr - expr), ptr, token, &term);
30879+
world, name, expr, (ptr - expr), ptr, token, &term, extra_args);
3084130880
}
3084230881

3084330882
goto parse_done;
@@ -30955,8 +30994,7 @@ const char* flecs_parse_term(
3095530994
}
3095630995
}
3095730996

30958-
if (ptr[0] == TOK_PAREN_CLOSE) {
30959-
ptr ++;
30997+
if (ptr[0] == TOK_PAREN_CLOSE || ptr[0] == TOK_AND) {
3096030998
goto parse_pair_object;
3096130999
} else {
3096231000
flecs_parser_unexpected_char(name, expr, ptr, ptr[0]);
@@ -30983,6 +31021,17 @@ const char* flecs_parse_term(
3098331021
term.id_flags = ECS_PAIR;
3098431022
}
3098531023

31024+
if (ptr[0] == TOK_AND) {
31025+
ptr = ecs_parse_ws(ptr + 1);
31026+
ptr = flecs_parse_arguments(
31027+
world, name, expr, (ptr - expr), ptr, token, NULL, extra_args);
31028+
if (!ptr) {
31029+
goto error;
31030+
}
31031+
} else {
31032+
ptr ++;
31033+
}
31034+
3098631035
ptr = ecs_parse_ws(ptr);
3098731036
goto parse_done;
3098831037

@@ -31020,7 +31069,8 @@ char* ecs_parse_term(
3102031069
const char *name,
3102131070
const char *expr,
3102231071
const char *ptr,
31023-
ecs_term_t *term)
31072+
ecs_term_t *term,
31073+
ecs_term_id_t *extra_args)
3102431074
{
3102531075
ecs_check(world != NULL, ECS_INVALID_PARAMETER, NULL);
3102631076
ecs_check(ptr != NULL, ECS_INVALID_PARAMETER, NULL);
@@ -31056,7 +31106,7 @@ char* ecs_parse_term(
3105631106
}
3105731107

3105831108
/* Parse next element */
31059-
ptr = flecs_parse_term(world, name, ptr, term);
31109+
ptr = flecs_parse_term(world, name, ptr, term, extra_args);
3106031110
if (!ptr) {
3106131111
goto error;
3106231112
}
@@ -32887,7 +32937,7 @@ const char *plecs_parse_plecs_term(
3288732937
decl_id = state->last_predicate;
3288832938
}
3288932939

32890-
ptr = ecs_parse_term(world, name, expr, ptr, &term);
32940+
ptr = ecs_parse_term(world, name, expr, ptr, &term, NULL);
3289132941
if (!ptr) {
3289232942
return NULL;
3289332943
}

flecs.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15267,6 +15267,9 @@ void ecs_snapshot_free(
1526715267
#ifndef FLECS_PARSER_H
1526815268
#define FLECS_PARSER_H
1526915269

15270+
/** Maximum number of extra arguments in term expression */
15271+
#define ECS_PARSER_MAX_ARGS (16)
15272+
1527015273
#ifdef __cplusplus
1527115274
extern "C" {
1527215275
#endif
@@ -15353,6 +15356,7 @@ const char* ecs_parse_token(
1535315356
* @param expr The expression to parse (optional, improves error logs)
1535415357
* @param ptr The pointer to the current term (must be in expr).
1535515358
* @param term_out Out parameter for the term.
15359+
* @param extra_args Out array for extra args, must be of size ECS_PARSER_MAX_ARGS.
1535615360
* @return pointer to next term if successful, NULL if failed.
1535715361
*/
1535815362
FLECS_API
@@ -15361,7 +15365,8 @@ char* ecs_parse_term(
1536115365
const char *name,
1536215366
const char *expr,
1536315367
const char *ptr,
15364-
ecs_term_t *term_out);
15368+
ecs_term_t *term_out,
15369+
ecs_term_id_t *extra_args);
1536515370

1536615371
#ifdef __cplusplus
1536715372
}

include/flecs/addons/parser.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
#ifndef FLECS_PARSER_H
2020
#define FLECS_PARSER_H
2121

22+
/** Maximum number of extra arguments in term expression */
23+
#define ECS_PARSER_MAX_ARGS (16)
24+
2225
#ifdef __cplusplus
2326
extern "C" {
2427
#endif
@@ -105,6 +108,7 @@ const char* ecs_parse_token(
105108
* @param expr The expression to parse (optional, improves error logs)
106109
* @param ptr The pointer to the current term (must be in expr).
107110
* @param term_out Out parameter for the term.
111+
* @param extra_args Out array for extra args, must be of size ECS_PARSER_MAX_ARGS.
108112
* @return pointer to next term if successful, NULL if failed.
109113
*/
110114
FLECS_API
@@ -113,7 +117,8 @@ char* ecs_parse_term(
113117
const char *name,
114118
const char *expr,
115119
const char *ptr,
116-
ecs_term_t *term_out);
120+
ecs_term_t *term_out,
121+
ecs_term_id_t *extra_args);
117122

118123
#ifdef __cplusplus
119124
}

src/addons/parser.c

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -487,15 +487,24 @@ const char* flecs_parse_arguments(
487487
int64_t column,
488488
const char *ptr,
489489
char *token,
490-
ecs_term_t *term)
490+
ecs_term_t *term,
491+
ecs_term_id_t *extra_args)
491492
{
492493
(void)column;
493494

494495
int32_t arg = 0;
495496

497+
if (extra_args) {
498+
ecs_os_memset_n(extra_args, 0, ecs_term_id_t, ECS_PARSER_MAX_ARGS);
499+
}
500+
501+
if (!term) {
502+
arg = 2;
503+
}
504+
496505
do {
497506
if (flecs_valid_token_start_char(ptr[0])) {
498-
if (arg == 2) {
507+
if ((arg == ECS_PARSER_MAX_ARGS) || (!extra_args && arg == 2)) {
499508
ecs_parser_error(name, expr, (ptr - expr),
500509
"too many arguments in term");
501510
return NULL;
@@ -512,6 +521,8 @@ const char* flecs_parse_arguments(
512521
term_id = &term->src;
513522
} else if (arg == 1) {
514523
term_id = &term->second;
524+
} else {
525+
term_id = &extra_args[arg - 2];
515526
}
516527

517528
/* If token is a colon, the token is an identifier followed by a
@@ -553,7 +564,9 @@ const char* flecs_parse_arguments(
553564
if (ptr[0] == TOK_AND) {
554565
ptr = ecs_parse_ws(ptr + 1);
555566

556-
term->id_flags = ECS_PAIR;
567+
if (term) {
568+
term->id_flags = ECS_PAIR;
569+
}
557570

558571
} else if (ptr[0] == TOK_PAREN_CLOSE) {
559572
ptr = ecs_parse_ws(ptr + 1);
@@ -599,7 +612,8 @@ const char* flecs_parse_term(
599612
const ecs_world_t *world,
600613
const char *name,
601614
const char *expr,
602-
ecs_term_t *term_out)
615+
ecs_term_t *term_out,
616+
ecs_term_id_t *extra_args)
603617
{
604618
const char *ptr = expr;
605619
char token[ECS_MAX_TOKEN_SIZE] = {0};
@@ -747,7 +761,7 @@ const char* flecs_parse_term(
747761
ptr = ecs_parse_ws(ptr);
748762
} else {
749763
ptr = flecs_parse_arguments(
750-
world, name, expr, (ptr - expr), ptr, token, &term);
764+
world, name, expr, (ptr - expr), ptr, token, &term, extra_args);
751765
}
752766

753767
goto parse_done;
@@ -865,8 +879,7 @@ const char* flecs_parse_term(
865879
}
866880
}
867881

868-
if (ptr[0] == TOK_PAREN_CLOSE) {
869-
ptr ++;
882+
if (ptr[0] == TOK_PAREN_CLOSE || ptr[0] == TOK_AND) {
870883
goto parse_pair_object;
871884
} else {
872885
flecs_parser_unexpected_char(name, expr, ptr, ptr[0]);
@@ -893,6 +906,17 @@ const char* flecs_parse_term(
893906
term.id_flags = ECS_PAIR;
894907
}
895908

909+
if (ptr[0] == TOK_AND) {
910+
ptr = ecs_parse_ws(ptr + 1);
911+
ptr = flecs_parse_arguments(
912+
world, name, expr, (ptr - expr), ptr, token, NULL, extra_args);
913+
if (!ptr) {
914+
goto error;
915+
}
916+
} else {
917+
ptr ++;
918+
}
919+
896920
ptr = ecs_parse_ws(ptr);
897921
goto parse_done;
898922

@@ -930,7 +954,8 @@ char* ecs_parse_term(
930954
const char *name,
931955
const char *expr,
932956
const char *ptr,
933-
ecs_term_t *term)
957+
ecs_term_t *term,
958+
ecs_term_id_t *extra_args)
934959
{
935960
ecs_check(world != NULL, ECS_INVALID_PARAMETER, NULL);
936961
ecs_check(ptr != NULL, ECS_INVALID_PARAMETER, NULL);
@@ -966,7 +991,7 @@ char* ecs_parse_term(
966991
}
967992

968993
/* Parse next element */
969-
ptr = flecs_parse_term(world, name, ptr, term);
994+
ptr = flecs_parse_term(world, name, ptr, term, extra_args);
970995
if (!ptr) {
971996
goto error;
972997
}

src/addons/plecs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1711,7 +1711,7 @@ const char *plecs_parse_plecs_term(
17111711
decl_id = state->last_predicate;
17121712
}
17131713

1714-
ptr = ecs_parse_term(world, name, expr, ptr, &term);
1714+
ptr = ecs_parse_term(world, name, expr, ptr, &term, NULL);
17151715
if (!ptr) {
17161716
return NULL;
17171717
}

src/entity.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,7 +1377,7 @@ ecs_table_t *flecs_traverse_from_expr(
13771377
const char *ptr = expr;
13781378
if (ptr) {
13791379
ecs_term_t term = {0};
1380-
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term))){
1380+
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term, NULL))){
13811381
if (!ecs_term_is_initialized(&term)) {
13821382
break;
13831383
}
@@ -1440,7 +1440,7 @@ void flecs_defer_from_expr(
14401440
const char *ptr = expr;
14411441
if (ptr) {
14421442
ecs_term_t term = {0};
1443-
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term))){
1443+
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term, NULL))) {
14441444
if (!ecs_term_is_initialized(&term)) {
14451445
break;
14461446
}

0 commit comments

Comments
 (0)