The following code:
#define NOVALUE  ((unsigned)-1)
#define EXPAND(...)  __VA_ARGS__
#define ADDONE(...)  +1
// -----------------------------------
#define IF_EMPTY_IN(a, ...)  a
#define IF_EMPTY(t, f, ...)  IF_EMPTY_IN(__VA_OPT__(f,) t, )
// --------------------------
#define TREE_VAL(idx, a, b, c, up, down)  \
        [idx] = {a, b, c, up, down},
// -----------------------------------
#define TREE_L4_NEXT(...)
#define TREE_L4_VAL_IN(f, idx, up, a, b, c, ...)  \
        f(idx, a, b, c, up, IF_EMPTY(NOVALUE, idx+1 __VA_OPT__(,) __VA_ARGS__)) \
        TREE_L4_NEXT(f, idx+1, idx __VA_OPT__(,) __VA_ARGS__)
#define TREE_L4_VAL(...)  \
        TREE_L4_VAL_IN(__VA_ARGS__)
#define TREE_L4_0(f, idx, up, a)
#define TREE_L4_1(f, idx, up, a)  \
        TREE_L4_VAL(f, idx, up, EXPAND a)
#define TREE_L4_2(f, idx, up, a, ...)  \
        TREE_L4_1(f, idx, up, a) \
        TREE_L4_1(f, idx TREE_L4_NEXT(ADDONE,,,a), up, __VA_ARGS__)
#define TREE_L4_3(f, idx, up, a, ...)  \
        TREE_L4_1(f, idx, up, a) \
        TREE_L4_2(f, idx TREE_L4_NEXT(ADDONE,,,a), up, __VA_ARGS__)
#define TREE_L4_N(_3,_2,_1,_0,N,...)  \
        TREE_L4##N
#define TREE_L4(f, idx, up, ...)  \
        TREE_L4_N(__VA_OPT__(,) __VA_ARGS__,_3,_2,_1,_0)(f, idx, up, __VA_ARGS__)
#define TREE_L3_NEXT(...)  TREE_L4(__VA_ARGS__)
#define TREE_L3_VAL_IN(f, idx, up, a, b, c, ...)  \
        f(idx, a, b, c, up, IF_EMPTY(NOVALUE, idx+1 __VA_OPT__(,) __VA_ARGS__)) \
        TREE_L3_NEXT(f, idx+1, idx __VA_OPT__(,) __VA_ARGS__)
#define TREE_L3_VAL(...)  \
        TREE_L3_VAL_IN(__VA_ARGS__)
#define TREE_L3_0(f, idx, up, a)
#define TREE_L3_1(f, idx, up, a)  \
        TREE_L3_VAL(f, idx, up, EXPAND a)
#define TREE_L3_2(f, idx, up, a, ...)  \
        TREE_L3_1(f, idx, up, a) \
        TREE_L3_1(f, idx TREE_L3_NEXT(ADDONE,,,a), up, __VA_ARGS__)
#define TREE_L3_3(f, idx, up, a, ...)  \
        TREE_L3_1(f, idx, up, a) \
        TREE_L3_2(f, idx TREE_L3_NEXT(ADDONE,,,a), up, __VA_ARGS__)
#define TREE_L3_N(_3,_2,_1,_0,N,...)  \
        TREE_L3##N
#define TREE_L3(f, idx, up, ...)  \
        TREE_L3_N(__VA_OPT__(,) __VA_ARGS__,_3,_2,_1,_0)(f, idx, up, __VA_ARGS__)
#define TREE_L2_NEXT(...)  TREE_L3(__VA_ARGS__)
#define TREE_L2_VAL_IN(f, idx, up, a, b, c, ...)  \
        f(idx, a, b, c, up, IF_EMPTY(NOVALUE, idx+1 __VA_OPT__(,) __VA_ARGS__)) \
        TREE_L2_NEXT(f, idx+1, idx __VA_OPT__(,) __VA_ARGS__)
#define TREE_L2_VAL(...)  \
        TREE_L2_VAL_IN(__VA_ARGS__)
#define TREE_L2_0(f, idx, up, a)
#define TREE_L2_1(f, idx, up, a)  \
        TREE_L2_VAL(f, idx, up, EXPAND a)
#define TREE_L2_2(f, idx, up, a, ...)  \
        TREE_L2_1(f, idx, up, a) \
        TREE_L2_1(f, idx TREE_L2_NEXT(ADDONE,,,a), up, __VA_ARGS__)
#define TREE_L2_3(f, idx, up, a, ...)  \
        TREE_L2_1(f, idx, up, a) \
        TREE_L2_2(f, idx TREE_L2_NEXT(ADDONE,,,a), up, __VA_ARGS__)
#define TREE_L2_N(_3,_2,_1,_0,N,...)  \
        TREE_L2##N
#define TREE_L2(f, idx, up, ...)  \
        TREE_L2_N(__VA_OPT__(,) __VA_ARGS__,_3,_2,_1,_0)(f, idx, up, __VA_ARGS__)
#define TREE_L1_NEXT(...)  TREE_L2(__VA_ARGS__)
#define TREE_L1_VAL_IN(f, idx, up, a, b, c, ...)  \
        f(idx, a, b, c, up, IF_EMPTY(NOVALUE, idx+1 __VA_OPT__(,) __VA_ARGS__)) \
        TREE_L1_NEXT(f, idx+1, idx __VA_OPT__(,) __VA_ARGS__)
#define TREE_L1_VAL(...)  \
        TREE_L1_VAL_IN(__VA_ARGS__)
#define TREE_L1_0(f, idx, up, a)
#define TREE_L1_1(f, idx, up, a)  \
        TREE_L1_VAL(f, idx, up, EXPAND a)
#define TREE_L1_2(f, idx, up, a, ...)  \
        TREE_L1_1(f, idx, up, a) \
        TREE_L1_1(f, idx TREE_L1_NEXT(ADDONE,,,a), up, __VA_ARGS__)
#define TREE_L1_3(f, idx, up, a, ...)  \
        TREE_L1_1(f, idx, up, a) \
        TREE_L1_2(f, idx TREE_L1_NEXT(ADDONE,,,a), up, __VA_ARGS__)
#define TREE_L1_N(_3,_2,_1,_0,N,...)  \
        TREE_L1##N
#define TREE_L1(f, idx, up, ...)  \
        TREE_L1_N(__VA_OPT__(,) __VA_ARGS__,_3,_2,_1,_0)(f, idx, up, __VA_ARGS__)
// -----------------------------------
#define TREE_SIZE(...)  0 TREE_L1(ADDONE, 0, NOVALUE, __VA_ARGS__)
#define TREE(...)       TREE_L1(TREE_VAL, 0, NOVALUE, __VA_ARGS__)
// -----------------------------------
#include <stdio.h>
#include <string.h>
struct array_s {
    int a;
    int b;
    int c;
    unsigned int top;
    unsigned int first;
};
#define LIST                     \
    (10, -3, 8,                  \
        (-1, -1, 13,             \
            (0, -7, 15)), \
        (-4, 14, 13)),    \
    (17, 0, 1),           \
    (3, 3, 3,                    \
        (1, 1, 0))         \
    /* */
static const struct array_s array[] = { TREE(LIST) };
static const char *snovalue(char *buf, unsigned v) {
    if (v == NOVALUE) {
        strcpy(buf, "NoValue");
    } else {
        sprintf(buf, "%u", v);
    }
    return buf;
}
#define SNOVALUE(v) snovalue((char[200]){0}, v)
int main() {
    for (int i = 0; i < sizeof(array)/sizeof(*array); ++i) {
        const struct array_s *const e = &array[i];
        printf("[%d]={%2d,%2d,%2d,%10s,%10s},\n",
            i, e->a, e->b, e->c, SNOVALUE(e->top), SNOVALUE(e->first));
    }
}
Outputs the content of array[] generated from TREE(LIST) as:
[0]={10,-3, 8,   NoValue,         1},
[1]={-1,-1,13,         0,         2},
[2]={ 0,-7,15,         1,   NoValue},
[3]={-4,14,13,         0,   NoValue},
[4]={17, 0, 1,   NoValue,   NoValue},
[5]={ 3, 3, 3,   NoValue,         6},
[6]={ 1, 1, 0,         5,   NoValue},
I removed EMPTY, I see no value in it. EMPTY, is just nothing, do not pass an argument. Then the macros can detect the number of arguments, and zero arguments, with the help of __VA_OPT__.
I have written the TREE_L* macros so that it is easy to generate them. You can just write a simple loop to generate a lot of them, and the last just has to have TREE_L*_NEXT empty.
On each tree level, calculating the next index has been a challenge. A separate temporary tree is traversed in idx TREE_L*_NEXT(ADDONE in each branch to calculate the current "depth" of the tree to get the index.
The code works like this: on each level, overload on number arguments. For each argument, output an [idx] = {stuff}, and then, if there are children, repeat the overload with incremented "up" index. Each level knows the "up" - the index of the upper level tree. On each traversing level, the TREE_L<num> is incremented because "used up" macros are painted blue by the preprocessor. All in all, this is a recursive algorithm.