+static initializer_t *parse_sub_initializer(type_t *type,
+ expression_t *expression,
+ type_t *expression_type)
+{
+ if(is_type_scalar(type)) {
+ /* there might be extra {} hierarchies */
+ if(token.type == '{') {
+ next_token();
+ if(!had_initializer_brace_warning) {
+ parse_warning("braces around scalar initializer");
+ had_initializer_brace_warning = true;
+ }
+ initializer_t *result = parse_sub_initializer(type, NULL, NULL);
+ if(token.type == ',') {
+ next_token();
+ /* TODO: warn about excessive elements */
+ }
+ expect_block('}');
+ return result;
+ }
+
+ if(expression == NULL) {
+ expression = parse_assignment_expression();
+ }
+ return initializer_from_expression(type, expression);
+ }
+
+ /* TODO: ignore qualifiers, comparing pointers is probably
+ * not correct */
+ if(expression != NULL && expression_type == type) {
+ initializer_t *result = allocate_ast_zero(sizeof(result[0]));
+ result->type = INITIALIZER_VALUE;
+
+ if(type != NULL) {
+ semantic_assign(type, &expression, "initializer");
+ }
+ //result->v.value = expression;
+
+ return result;
+ }
+
+ bool read_paren = false;
+ if(token.type == '{') {
+ next_token();
+ read_paren = true;
+ }
+
+ /* descend into subtype */
+ initializer_t *result = NULL;
+ if(type->type == TYPE_ARRAY) {
+ array_type_t *array_type = (array_type_t*) type;
+ type_t *element_type = array_type->element_type;
+ element_type = skip_typeref(element_type);
+
+ result
+ = parse_sub_initializer(element_type, expression, expression_type);
+ } else {
+ assert(type->type == TYPE_COMPOUND_STRUCT
+ || type->type == TYPE_COMPOUND_UNION);
+ compound_type_t *compound_type = (compound_type_t*) type;
+ context_t *context = & compound_type->declaration->context;
+
+ declaration_t *first = context->declarations;
+ if(first == NULL)
+ return NULL;
+ type_t *first_type = first->type;
+ first_type = skip_typeref(first_type);
+
+ initializer_t *sub;
+ had_initializer_brace_warning = false;
+ if(expression == NULL) {
+ sub = parse_sub_initializer_elem(first_type);