X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=parser.c;h=e6326a9498d3cf259152082c48f31b7c93c1e21f;hb=b30368f026e4e1bf27e5beb943d693dbd2268457;hp=e92cb6e6326c82faf2822e0c421ca3fbfaa453af;hpb=0eab97283f30db40344105a699440d7b5fbd2f96;p=xonotic%2Fgmqcc.git diff --git a/parser.c b/parser.c index e92cb6e..e6326a9 100644 --- a/parser.c +++ b/parser.c @@ -4917,32 +4917,44 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var) return NULL; } - cexp = parse_expression_leave(parser, true, false, false); + if (parser->tok != ']') { + cexp = parse_expression_leave(parser, true, false, false); - if (!cexp || !ast_istype(cexp, ast_value)) { - if (cexp) - ast_unref(cexp); - ast_delete(var); - parseerror(parser, "expected array-size as constant positive integer"); - return NULL; + if (!cexp || !ast_istype(cexp, ast_value)) { + if (cexp) + ast_unref(cexp); + ast_delete(var); + parseerror(parser, "expected array-size as constant positive integer"); + return NULL; + } + cval = (ast_value*)cexp; + } + else { + cexp = NULL; + cval = NULL; } - cval = (ast_value*)cexp; tmp = ast_value_new(ctx, "", TYPE_ARRAY); tmp->expression.next = (ast_expression*)var; var = tmp; - if (cval->expression.vtype == TYPE_INTEGER) - tmp->expression.count = cval->constval.vint; - else if (cval->expression.vtype == TYPE_FLOAT) - tmp->expression.count = cval->constval.vfloat; - else { + if (cval) { + if (cval->expression.vtype == TYPE_INTEGER) + tmp->expression.count = cval->constval.vint; + else if (cval->expression.vtype == TYPE_FLOAT) + tmp->expression.count = cval->constval.vfloat; + else { + ast_unref(cexp); + ast_delete(var); + parseerror(parser, "array-size must be a positive integer constant"); + return NULL; + } + ast_unref(cexp); - ast_delete(var); - parseerror(parser, "array-size must be a positive integer constant"); - return NULL; + } else { + var->expression.count = -1; + var->expression.flags |= AST_FLAG_ARRAY_INIT; } - ast_unref(cexp); if (parser->tok != ']') { ast_delete(var); @@ -5192,6 +5204,65 @@ static bool parser_check_qualifiers(parser_t *parser, const ast_value *var, cons return true; } +static bool create_array_accessors(parser_t *parser, ast_value *var) +{ + char name[1024]; + util_snprintf(name, sizeof(name), "%s##SET", var->name); + if (!parser_create_array_setter(parser, var, name)) + return false; + util_snprintf(name, sizeof(name), "%s##GET", var->name); + if (!parser_create_array_getter(parser, var, var->expression.next, name)) + return false; + return true; +} + +static bool parse_array(parser_t *parser, ast_value *array) +{ + if (!parser_next(parser)) { + parseerror(parser, "parse error in array initializer"); + return false; + } + while (parser->tok != '}') { + ast_value *v = (ast_value*)parse_expression_leave(parser, true, false, false); + if (!v) + return false; + if (!ast_istype(v, ast_value) || !v->hasvalue || v->cvq != CV_CONST) { + ast_unref(v); + parseerror(parser, "initializing element must be a compile time constant"); + return false; + } + vec_push(array->initlist, v->constval); + ast_unref(v); + if (parser->tok == '}') + break; + if (parser->tok != ',' || !parser_next(parser)) { + parseerror(parser, "expected comma or '}' in element list"); + return false; + } + } + if (!parser_next(parser) || parser->tok != ';') { + parseerror(parser, "expected semicolon after initializer, got %s"); + return false; + } + /* + if (!parser_next(parser)) { + parseerror(parser, "parse error after initializer"); + return false; + } + */ + + if (array->expression.flags & AST_FLAG_ARRAY_INIT) { + if (array->expression.count != (size_t)-1) { + parseerror(parser, "array `%s' has already been initialized with %u elements", + array->name, (unsigned)array->expression.count); + } + array->expression.count = vec_size(array->initlist); + if (!create_array_accessors(parser, array)) + return false; + } + return true; +} + static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool is_static, uint32_t qflags, char *vstring) { ast_value *var; @@ -5625,13 +5696,10 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield * deal with arrays */ if (var->expression.vtype == TYPE_ARRAY) { - char name[1024]; - util_snprintf(name, sizeof(name), "%s##SET", var->name); - if (!parser_create_array_setter(parser, var, name)) - goto cleanup; - util_snprintf(name, sizeof(name), "%s##GET", var->name); - if (!parser_create_array_getter(parser, var, var->expression.next, name)) - goto cleanup; + if (var->expression.count != (size_t)-1) { + if (!create_array_accessors(parser, var)) + goto cleanup; + } } else if (!localblock && !nofields && var->expression.vtype == TYPE_FIELD && @@ -5803,11 +5871,10 @@ skipvar: parseerror(parser, "TODO: initializers for local arrays"); break; } - /* -static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma, bool truthvalue, bool with_labels); -*/ - parseerror(parser, "TODO: initializing global arrays is not supported yet!"); - break; + + var->hasvalue = true; + if (!parse_array(parser, var)) + break; } else if (var->expression.vtype == TYPE_FUNCTION && (parser->tok == '{' || parser->tok == '[')) {