improve initializer handling
authorMatthias Braun <matze@braunis.de>
Fri, 28 Sep 2007 21:33:25 +0000 (21:33 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 28 Sep 2007 21:33:25 +0000 (21:33 +0000)
[r18367]

ast.c
ast.h
ast_t.h
parser.c
type.c
write_fluffy.c

diff --git a/ast.c b/ast.c
index 0d283f8..3cdc374 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -467,6 +467,25 @@ static void print_storage_class(storage_class_t storage_class)
        }
 }
 
+void print_initializer(const initializer_t *initializer)
+{
+       if(initializer->type == INITIALIZER_VALUE) {
+               print_expression(initializer->v.value);
+               return;
+       }
+
+       assert(initializer->type == INITIALIZER_LIST);
+       fputs("{ ", out);
+       initializer_t *iter = initializer->v.list;
+       for( ; iter != NULL; iter = iter->next) {
+               print_initializer(iter);
+               if(iter->next != NULL) {
+                       fputs(", ", out);
+               }
+       }
+       fputs("}", out);
+}
+
 static void print_declaration(const declaration_t *declaration)
 {
        print_storage_class(declaration->storage_class);
@@ -477,7 +496,7 @@ static void print_declaration(const declaration_t *declaration)
                print_statement(declaration->statement);
        } else if(declaration->initializer != NULL) {
                fputs(" = ", out);
-               print_expression(declaration->initializer);
+               print_initializer(declaration->initializer);
                fprintf(out, ";\n");
        } else {
                fprintf(out, ";\n");
diff --git a/ast.h b/ast.h
index e599dc8..88d99c3 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -22,11 +22,12 @@ typedef struct conditional_expression_t     conditional_expression_t;
 typedef struct expression_list_element_t    expression_list_element_t;
 typedef struct comma_expression_t           comma_expression_t;
 typedef struct statement_expression_t       statement_expression_t;
-typedef struct member_designator_t          member_designator_t;
+typedef struct designator_t                 designator_t;
 typedef struct offsetof_expression_t        offsetof_expression_t;
 typedef struct va_arg_expression_t          va_arg_expression_t;
 typedef struct builtin_symbol_expression_t  builtin_symbol_expression_t;
 
+typedef struct initializer_t                initializer_t;
 typedef struct declaration_t                declaration_t;
 
 typedef struct statement_t                  statement_t;
@@ -52,6 +53,7 @@ void  exit_ast(void);
 
 void  ast_set_output(FILE *out);
 void  print_expression(const expression_t *expression);
+void  print_initializer(const initializer_t *initializer);
 void  print_ast(const translation_unit_t *unit);
 void *allocate_ast(size_t size);
 
diff --git a/ast_t.h b/ast_t.h
index 5cddf05..9778d36 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -160,16 +160,16 @@ struct sizeof_expression_t {
        expression_t *size_expression;
 };
 
-struct member_designator_t {
-       symbol_t            *symbol;
-       expression_t        *array_access;
-       member_designator_t *next;
+struct designator_t {
+       symbol_t     *symbol;
+       expression_t *array_access;
+       designator_t *next;
 };
 
 struct offsetof_expression_t {
-       expression_t         expression;
-       type_t              *type;
-       member_designator_t *member_designators;
+       expression_t  expression;
+       type_t       *type;
+       designator_t *designator;
 };
 
 struct va_arg_expression_t {
@@ -200,12 +200,27 @@ typedef enum {
        STORAGE_CLASS_ENUM_ENTRY
 } storage_class_t;
 
+typedef enum {
+       INITIALIZER_VALUE,
+       INITIALIZER_LIST,
+} initializer_type_t;
+
+struct initializer_t {
+       initializer_type_t type;
+       designator_t      *designator;
+       union {
+               initializer_t *list;
+               expression_t  *value;
+       } v;
+       initializer_t *next;
+};
+
 struct declaration_t {
        storage_class_t     storage_class;
        type_t             *type;
        symbol_t           *symbol;
        statement_t        *statement;
-       expression_t       *initializer;
+       initializer_t      *initializer;
        source_position_t   source_position;
        context_t           context;
 
index 033033e..1c627a3 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -493,6 +493,105 @@ attributes_finished:
        ;
 }
 
+static designator_t *parse_designation(void)
+{
+       if(token.type != '[' && token.type != '.')
+               return NULL;
+
+       designator_t *result = NULL;
+       designator_t *last   = NULL;
+
+       while(1) {
+               designator_t *designator;
+               switch(token.type) {
+               case '[':
+                       designator = allocate_ast_zero(sizeof(designator[0]));
+                       next_token();
+                       designator->array_access = parse_constant_expression();
+                       expect(']');
+                       break;
+               case '.':
+                       designator = allocate_ast_zero(sizeof(designator[0]));
+                       next_token();
+                       if(token.type != T_IDENTIFIER) {
+                               parse_error_expected("problem while parsing designator",
+                                                    T_IDENTIFIER, 0);
+                               return NULL;
+                       }
+                       designator->symbol = token.v.symbol;
+                       next_token();
+                       break;
+               default:
+                       expect('=');
+                       return result;
+               }
+
+               assert(designator != NULL);
+               if(last != NULL) {
+                       last->next = designator;
+               } else {
+                       result = designator;
+               }
+               last = designator;
+       }
+}
+
+static initializer_t *parse_initializer_list(void);
+
+static initializer_t *parse_initializer(void)
+{
+       designator_t *designator = parse_designation();
+
+       initializer_t *result;
+       if(token.type == '{') {
+               result = parse_initializer_list();
+       } else {
+               result          = allocate_ast_zero(sizeof(result[0]));
+               result->type    = INITIALIZER_VALUE;
+               result->v.value = parse_assignment_expression();
+       }
+       result->designator = designator;
+
+       return result;
+}
+
+static initializer_t *parse_initializer_list(void)
+{
+       eat('{');
+
+       initializer_t *result = allocate_ast_zero(sizeof(result[0]));
+       result->type = INITIALIZER_LIST;
+
+       initializer_t *last = NULL;
+       while(1) {
+               initializer_t *initializer = parse_initializer();
+               if(last != NULL) {
+                       last->next = initializer;
+               } else {
+                       result->v.list = initializer;
+               }
+               last = initializer;
+
+               if(token.type == '}')
+                       break;
+
+               if(token.type != ',') {
+                       parse_error_expected("problem while parsing initializer list",
+                                            ',', '}', 0);
+                       eat_block();
+                       return result;
+               }
+               eat(',');
+
+               if(token.type == '}')
+                       break;
+       }
+
+       expect('}');
+
+       return result;
+}
+
 static compound_type_t *find_compound_type(compound_type_t *types,
                                            const symbol_t *symbol)
 {
@@ -601,7 +700,7 @@ static void parse_enum_entries(void)
 
                if(token.type == '=') {
                        next_token();
-                       entry->initializer = parse_constant_expression();
+                       entry->initializer = parse_initializer();
                }
 
                record_declaration(entry);
@@ -1432,66 +1531,6 @@ static void parser_error_multiple_definition(declaration_t *previous,
        error();
 }
 
-static void parse_designation(void)
-{
-       if(token.type != '[' && token.type != '.')
-               return;
-
-       while(1) {
-               switch(token.type) {
-               case '[':
-                       next_token();
-                       parse_constant_expression();
-                       expect_void(']');
-                       break;
-               case '.':
-                       next_token();
-                       expect_void(T_IDENTIFIER);
-                       break;
-               default:
-                       expect_void('=');
-                       return;
-               }
-       }
-}
-
-static void parse_initializer_list(void);
-
-static void parse_initializer(void)
-{
-       parse_designation();
-
-       if(token.type == '{') {
-               parse_initializer_list();
-       } else {
-               parse_assignment_expression();
-       }
-}
-
-static void parse_initializer_list(void)
-{
-       eat('{');
-
-       while(1) {
-               parse_initializer();
-               if(token.type == '}')
-                       break;
-
-               if(token.type != ',') {
-                       parse_error_expected("problem while parsing initializer list",
-                                            ',', '}', 0);
-                       eat_block();
-                       return;
-               }
-               eat(',');
-
-               if(token.type == '}')
-                       break;
-       }
-
-       expect_void('}');
-}
-
 static void parse_init_declarators(const declaration_specifiers_t *specifiers)
 {
        while(true) {
@@ -1510,7 +1549,7 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers)
                                parser_error_multiple_definition(declaration, ndeclaration);
                        }
 
-                       parse_initializer();
+                       ndeclaration->initializer = parse_initializer();
                } else if(token.type == '{') {
                        if(declaration->type->type != TYPE_METHOD) {
                                parser_print_error_prefix();
@@ -1878,9 +1917,9 @@ static expression_t *parse_pretty_function_keyword(void)
        return (expression_t*) expression;
 }
 
-static member_designator_t *parse_member_designators(void)
+static designator_t *parse_designator(void)
 {
-       member_designator_t *result = allocate_ast_zero(sizeof(result[0]));
+       designator_t *result = allocate_ast_zero(sizeof(result[0]));
 
        if(token.type != T_IDENTIFIER) {
                parse_error_expected("problem while parsing member designator",
@@ -1891,7 +1930,7 @@ static member_designator_t *parse_member_designators(void)
        result->symbol = token.v.symbol;
        next_token();
 
-       member_designator_t *last_designator = result;
+       designator_t *last_designator = result;
        while(true) {
                if(token.type == '.') {
                        next_token();
@@ -1901,9 +1940,8 @@ static member_designator_t *parse_member_designators(void)
                                eat_brace();
                                return NULL;
                        }
-                       member_designator_t *designator
-                               = allocate_ast_zero(sizeof(result[0]));
-                       designator->symbol = token.v.symbol;
+                       designator_t *designator = allocate_ast_zero(sizeof(result[0]));
+                       designator->symbol       = token.v.symbol;
                        next_token();
 
                        last_designator->next = designator;
@@ -1912,8 +1950,7 @@ static member_designator_t *parse_member_designators(void)
                }
                if(token.type == '[') {
                        next_token();
-                       member_designator_t *designator
-                               = allocate_ast_zero(sizeof(result[0]));
+                       designator_t *designator = allocate_ast_zero(sizeof(result[0]));
                        designator->array_access = parse_expression();
                        if(designator->array_access == NULL) {
                                eat_brace();
@@ -1943,7 +1980,7 @@ static expression_t *parse_offsetof(void)
        expect('(');
        expression->type = parse_typename();
        expect(',');
-       expression->member_designators = parse_member_designators();
+       expression->designator = parse_designator();
        expect(')');
 
        return (expression_t*) expression;
diff --git a/type.c b/type.c
index d241abf..4d538eb 100644 (file)
--- a/type.c
+++ b/type.c
@@ -162,7 +162,7 @@ static void print_type_enum(const enum_type_t *type)
                        fprintf(out, "\t%s", entry->symbol->string);
                        if(entry->initializer != NULL) {
                                fprintf(out, " = ");
-                               print_expression(entry->initializer);
+                               print_initializer(entry->initializer);
                        }
                        fprintf(out, ",\n");
                }
index e9db530..c33b546 100644 (file)
@@ -231,6 +231,15 @@ static void write_expression(const expression_t *expression)
        }
 }
 
+static void write_initializer(const initializer_t *initializer)
+{
+       if(initializer->type != INITIALIZER_VALUE) {
+               panic("list initializers not supported yet");
+       }
+
+       write_expression(initializer->v.value);
+}
+
 static void write_enum(const symbol_t *symbol, const enum_type_t *type)
 {
        fprintf(out, "enum %s:\n", symbol->string);
@@ -240,7 +249,7 @@ static void write_enum(const symbol_t *symbol, const enum_type_t *type)
                fprintf(out, "\t%s", entry->symbol->string);
                if(entry->initializer != NULL) {
                        fprintf(out, " <- ");
-                       write_expression(entry->initializer);
+                       write_initializer(entry->initializer);
                }
                fputc('\n', out);
        }