From 74a17ec093fc824f45fa5547a65155c93c907b88 Mon Sep 17 00:00:00 2001 From: tyfkda Date: Sun, 3 Dec 2023 09:13:10 +0900 Subject: [PATCH] Refactoring for initializer --- src/cc/frontend/initializer.c | 20 +++++++---- src/cc/frontend/parser.c | 67 ++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 35 deletions(-) diff --git a/src/cc/frontend/initializer.c b/src/cc/frontend/initializer.c index 2ca2eab85..969aa4da8 100644 --- a/src/cc/frontend/initializer.c +++ b/src/cc/frontend/initializer.c @@ -163,6 +163,10 @@ static int compare_desig_start(const void *a, const void *b) { return d > 0 ? 1 : d < 0 ? -1 : 0; } +typedef struct { + int index; +} InitFlattener; + static Initializer *flatten_array_initializer(Initializer *init) { // Check whether IK_DOT or IK_ARR exists. int i = 0, len = init->multi->len; @@ -238,7 +242,9 @@ static bool is_multi_type(enum TypeKind kind) { static Initializer *flatten_initializer_multi0(Type *type, Initializer *init); -static Initializer *flatten_initializer_multi(Type *type, Initializer *init, int *pindex) { +static Initializer *flatten_initializer_multi(InitFlattener *flattener, Type *type, Initializer *init) { + int *const pindex = &flattener->index; + assert(init != NULL); switch (init->kind) { case IK_SINGLE: @@ -342,7 +348,7 @@ static Initializer *flatten_initializer_multi(Type *type, Initializer *init, int assert(mt->kind == TY_ARRAY); mt->pa.length = -1; } - value = flatten_initializer_multi(mt, init, pindex); + value = flatten_initializer_multi(flattener, mt, init); } values[midx++] = value; @@ -381,7 +387,7 @@ static Initializer *flatten_initializer_multi(Type *type, Initializer *init, int } else { if (type->pa.length >= 0 && eidx >= type->pa.length) break; - elem_init = flatten_initializer_multi(elem_type, init, pindex); + elem_init = flatten_initializer_multi(flattener, elem_type, init); } vec_push(elems, elem_init); ++eidx; @@ -400,14 +406,14 @@ static Initializer *flatten_initializer_multi0(Type *type, Initializer *init) { if (type->kind == TY_ARRAY) init = flatten_array_initializer(init); - int index = -1; - Initializer *flat = flatten_initializer_multi(type, init, &index); + InitFlattener flattener = { .index = -1 }; + Initializer *flat = flatten_initializer_multi(&flattener, type, init); switch (type->kind) { case TY_ARRAY: case TY_STRUCT: - if (index < init->multi->len) { + if (flattener.index < init->multi->len) { const char *tstr = type->kind == TY_ARRAY ? "array" : "struct"; - parse_error(PE_WARNING, ((Initializer*)init->multi->data[index])->token, + parse_error(PE_WARNING, ((Initializer*)init->multi->data[flattener.index])->token, "Excess elements in %s initializer", tstr); } break; diff --git a/src/cc/frontend/parser.c b/src/cc/frontend/parser.c index 606eb1e06..73813d38d 100644 --- a/src/cc/frontend/parser.c +++ b/src/cc/frontend/parser.c @@ -77,6 +77,41 @@ extern inline void check_goto_labels(Function *func) { // +static Initializer *parse_initializer_multi(void) { + Initializer *init = NULL; + const Token *tok; + if (match(TK_DOT)) { // .member=value + Token *ident = consume(TK_IDENT, "ident expected for dotted initializer"); + Initializer *value = parse_initializer_multi(); + if (value == NULL) { + consume(TK_ASSIGN, "`=' expected for dotted initializer"); + value = parse_initializer(); + } + if (ident != NULL) { + init = new_initializer(IK_DOT, ident); + init->dot.name = ident->ident; + init->dot.value = value; + } + } else if ((tok = match(TK_LBRACKET)) != NULL) { + Expr *expr = parse_const_fixnum(); + size_t index = 0; + if (expr->fixnum < 0) + parse_error(PE_NOFATAL, expr->token, "non negative integer required"); + else + index = expr->fixnum; + consume(TK_RBRACKET, "`]' expected"); + Initializer *value = parse_initializer_multi(); + if (value == NULL) { + match(TK_ASSIGN); // both accepted: `[1] = 2`, and `[1] 2` + value = parse_initializer(); + } + init = new_initializer(IK_ARR, tok); + init->arr.index = index; + init->arr.value = value; + } + return init; +} + Initializer *parse_initializer(void) { Initializer *result; const Token *lblace_tok; @@ -84,35 +119,11 @@ Initializer *parse_initializer(void) { Vector *multi = new_vector(); if (!match(TK_RBRACE)) { for (;;) { - Initializer *init = NULL; - const Token *tok; - if (match(TK_DOT)) { // .member=value - Token *ident = consume(TK_IDENT, "ident expected for dotted initializer"); - consume(TK_ASSIGN, "`=' expected for dotted initializer"); - Initializer *value = parse_initializer(); - if (ident != NULL) { - init = new_initializer(IK_DOT, ident); - init->dot.name = ident->ident; - init->dot.value = value; - } - } else if ((tok = match(TK_LBRACKET)) != NULL) { - Expr *expr = parse_const_fixnum(); - size_t index = 0; - if (expr->fixnum < 0) - parse_error(PE_NOFATAL, expr->token, "non negative integer required"); - else - index = expr->fixnum; - consume(TK_RBRACKET, "`]' expected"); - match(TK_ASSIGN); // both accepted: `[1] = 2`, and `[1] 2` - Initializer *value = parse_initializer(); - init = new_initializer(IK_ARR, tok); - init->arr.index = index; - init->arr.value = value; - } else { + Initializer *init = parse_initializer_multi(); + if (init == NULL) init = parse_initializer(); - } - if (init != NULL) - vec_push(multi, init); + assert(init != NULL); + vec_push(multi, init); if (match(TK_COMMA)) { if (match(TK_RBRACE))