improved union/struct parsing
authorMatthias Braun <matze@braunis.de>
Fri, 14 Sep 2007 19:36:14 +0000 (19:36 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 14 Sep 2007 19:36:14 +0000 (19:36 +0000)
[r18349]

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

diff --git a/ast.h b/ast.h
index 9e5aef1..aee5067 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -34,7 +34,6 @@ typedef struct goto_statement_t           goto_statement_t;
 typedef struct label_statement_t          label_statement_t;
 
 typedef struct translation_unit_t         translation_unit_t;
-typedef struct method_parameter_t         method_parameter_t;
 typedef struct method_t                   method_t;
 typedef struct global_variable_t          global_variable_t;
 
diff --git a/ast_t.h b/ast_t.h
index 53ea232..92a8c88 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -23,7 +23,10 @@ typedef enum {
 } expresion_type_t;
 
 struct context_t {
-       declaration_t *declarations;
+       declaration_t   *declarations;
+       compound_type_t *structs;
+       compound_type_t *unions;
+       compound_type_t *enums;
 };
 
 struct expression_t {
@@ -170,8 +173,9 @@ struct declaration_t {
        type_t             *type;
        symbol_t           *symbol;
        statement_t        *statement;
+       expression_t       *initializer;
        source_position_t   source_position;
-       //context_t           context;
+       context_t           context;
 
        declaration_t      *next;
 };
index efb6799..2249d4c 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -195,6 +195,20 @@ static void set_context(context_t *new_context)
        last_declaration = declaration;
 }
 
+#if 0
+/**
+ * called when we find a 2nd declarator for an identifier we already have a
+ * declarator for
+ */
+static void multiple_occurence(declaration_t *declaration,
+                              declaration_t *previous)
+{
+       if(declaration->type != previous->type) {
+
+       }
+}
+#endif
+
 /**
  * pushs an environment_entry on the environment stack and links the
  * corresponding symbol to the new entry
@@ -290,69 +304,85 @@ struct declaration_specifiers_t {
        type_t          *type;
 };
 
-static type_t *parse_struct_specifier(void)
+static compound_type_t *find_compound_type(compound_type_t *types,
+                                           const symbol_t *symbol)
 {
-       eat(T_struct);
+       compound_type_t *type = types;
+       for( ; type != NULL; type = type->next) {
+               if(type->symbol == symbol)
+                       return type;
+       }
+
+       return NULL;
+}
 
-       compound_type_t *struct_type = allocate_type_zero(sizeof(struct_type[0]));
-       struct_type->type.type       = TYPE_COMPOUND_STRUCT;
-       struct_type->source_position = token.source_position;
+static type_t *parse_compound_type_specifier(int is_struct)
+{
+       if(is_struct) {
+               eat(T_struct);
+       } else {
+               eat(T_union);
+       }
 
-       int         top          = environment_top();
-       context_t  *last_context = context;
-       set_context(&struct_type->context);
+       symbol_t        *symbol        = NULL;
+       compound_type_t *compound_type = NULL;
 
        if(token.type == T_IDENTIFIER) {
+               symbol = token.v.symbol;
                next_token();
-               if(token.type == '{') {
-                       parse_compound_type_entries();
+
+               if(context != NULL) {
+                       if(is_struct) {
+                               compound_type = find_compound_type(context->structs, symbol);
+                       } else {
+                               compound_type = find_compound_type(context->unions, symbol);
+                       }
                }
-       } else if(token.type == '{') {
-               parse_compound_type_entries();
-       } else {
-               parse_error_expected("problem while parsing struct type specifiers",
-                                    T_IDENTIFIER, '{', 0);
-               struct_type = NULL;
+       } else if(token.type != '{') {
+               if(is_struct) {
+                       parse_error_expected("problem while parsing struct type specifiers",
+                                            T_IDENTIFIER, '{', 0);
+               } else {
+                       parse_error_expected("problem while parsing union type specifiers",
+                                            T_IDENTIFIER, '{', 0);
+               }
+
+               return NULL;
        }
 
-       assert(context == &struct_type->context);
-       set_context(last_context);
-       environment_pop_to(top);
+       if(compound_type == NULL) {
+               compound_type = allocate_type_zero(sizeof(compound_type[0]));
 
-       return (type_t*) struct_type;
-}
-
-static type_t *parse_union_specifier(void)
-{
-       eat(T_union);
+               if(is_struct) {
+                       compound_type->type.type = TYPE_COMPOUND_STRUCT;
+               } else {
+                       compound_type->type.type = TYPE_COMPOUND_UNION;
+               }
+               compound_type->source_position = token.source_position;
+               compound_type->symbol          = symbol;
+       }
 
-       compound_type_t *union_type = allocate_type_zero(sizeof(union_type[0]));
-       union_type->type.type       = TYPE_COMPOUND_UNION;
-       union_type->source_position = token.source_position;
+       if(token.type == '{') {
+               if(compound_type->defined) {
+                       parser_print_error_prefix();
+                       fprintf(stderr, "multiple definition of %s %s\n",
+                                       is_struct ? "struct" : "union", symbol->string);
+                       compound_type->context.declarations = NULL;
+               }
+               compound_type->defined = 1;
 
-       int         top          = environment_top();
-       context_t  *last_context = context;
-       set_context(&union_type->context);
+               int         top          = environment_top();
+               context_t  *last_context = context;
+               set_context(&compound_type->context);
 
-       if(token.type == T_IDENTIFIER) {
-               union_type->symbol = token.v.symbol;
-               next_token();
-               if(token.type == '{') {
-                       parse_compound_type_entries();
-               }
-       } else if(token.type == '{') {
                parse_compound_type_entries();
-       } else {
-               parse_error_expected("problem while parsing union type specifiers",
-                                    T_IDENTIFIER, '{');
-               union_type = NULL;
-       }
 
-       assert(context == &union_type->context);
-       set_context(last_context);
-       environment_pop_to(top);
+               assert(context == &compound_type->context);
+               set_context(last_context);
+               environment_pop_to(top);
+       }
 
-       return (type_t*) union_type;
+       return (type_t*) compound_type;
 }
 
 static enum_entry_t *parse_enum_type_entries(void)
@@ -659,10 +689,10 @@ void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
 
                /* TODO: if type != NULL for the following rules issue an error */
                case T_struct:
-                       type = parse_struct_specifier();
+                       type = parse_compound_type_specifier(1);
                        break;
                case T_union:
-                       type = parse_union_specifier();
+                       type = parse_compound_type_specifier(0);
                        break;
                case T_enum:
                        type = parse_enum_specifier();
@@ -927,54 +957,64 @@ declaration_t *parse_parameter(void)
 }
 
 static
-void parse_parameters(method_type_t *type)
+declaration_t *parse_parameters(method_type_t *type)
 {
        if(token.type == T_IDENTIFIER) {
                symbol_t      *symbol      = token.v.symbol;
                declaration_t *declaration = symbol->declaration;
                if(declaration == NULL
                                || declaration->storage_class != STORAGE_CLASS_TYPEDEF) {
+                       /* TODO */
                        parse_identifier_list();
-                       return;
+                       return NULL;
                }
        }
 
        if(token.type == ')') {
                type->unspecified_parameters = 1;
-               return;
+               return NULL;
        }
        if(token.type == T_void && la(1)->type == ')') {
                next_token();
-               return;
+               return NULL;
        }
 
-       declaration_t *parameter;
-       declaration_t *last_parameter = NULL;
+       declaration_t      *declarations = NULL;
+       declaration_t      *declaration;
+       declaration_t      *last_declaration = NULL;
+       method_parameter_t *parameter;
+       method_parameter_t *last_parameter = NULL;
 
        while(1) {
                switch(token.type) {
                case T_DOTDOTDOT:
                        next_token();
                        type->variadic = 1;
-                       return;
+                       return declarations;
 
                case T_IDENTIFIER:
                DECLARATION_START
-                       parameter = parse_parameter();
+                       declaration = parse_parameter();
+
+                       parameter       = allocate_type_zero(sizeof(parameter[0]));
+                       parameter->type = declaration->type;
 
                        if(last_parameter != NULL) {
-                               last_parameter->next = parameter;
+                               last_declaration->next = declaration;
+                               last_parameter->next   = parameter;
                        } else {
                                type->parameters = parameter;
+                               declarations     = declaration;
                        }
-                       last_parameter = parameter;
+                       last_parameter   = parameter;
+                       last_declaration = declaration;
                        break;
 
                default:
-                       return;
+                       return declarations;
                }
                if(token.type != ',')
-                       return;
+                       return declarations;
                next_token();
        }
 }
@@ -1030,7 +1070,7 @@ declarator_part *parse_inner_declarator(declaration_t *declaration,
                                = allocate_type_zero(sizeof(method_type[0]));
                        method_type->type.type   = TYPE_METHOD;
 
-                       parse_parameters(method_type);
+                       declaration->context.declarations = parse_parameters(method_type);
 
                        part->method_type = method_type;
 
@@ -1152,7 +1192,7 @@ void parse_init_declarators(const declaration_specifiers_t *specifiers)
                                // TODO
                                expect_void('}');
                        } else {
-                               parse_assignment_expression();
+                               declaration->initializer = parse_assignment_expression();
                        }
                } else if(token.type == '{') {
                        statement_t *statement = parse_compound_statement();
diff --git a/type.c b/type.c
index f9419da..36ca1c5 100644 (file)
--- a/type.c
+++ b/type.c
@@ -89,15 +89,15 @@ void print_method_type_post(const method_type_t *type)
 
        fputc('(', out);
 
-       declaration_t *parameter = type->parameters;
-       int            first     = 1;
+       method_parameter_t *parameter = type->parameters;
+       int                 first     = 1;
        for( ; parameter != NULL; parameter = parameter->next) {
                if(first) {
                        first = 0;
                } else {
                        fputs(", ", out);
                }
-               print_type(parameter->type, parameter->symbol);
+               print_type(parameter->type, NULL);
        }
        if(type->variadic) {
                if(first) {
diff --git a/type.h b/type.h
index 276846e..b3700a8 100644 (file)
--- a/type.h
+++ b/type.h
@@ -7,7 +7,7 @@
 typedef struct type_t                   type_t;
 typedef struct atomic_type_t            atomic_type_t;
 typedef struct pointer_type_t           pointer_type_t;
-typedef struct method_parameter_type_t  method_parameter_type_t;
+typedef struct method_parameter_t       method_parameter_t;
 typedef struct method_type_t            method_type_t;
 typedef struct compound_type_t          compound_type_t;
 typedef struct enum_entry_t             enum_entry_t;
index 3f84c5d..9606d4f 100644 (file)
@@ -52,7 +52,7 @@ unsigned hash_method_type(const method_type_t *type)
 {
        unsigned result = hash_ptr(type->result_type);
 
-       declaration_t *parameter = type->parameters;
+       method_parameter_t *parameter = type->parameters;
        while(parameter != NULL) {
                result ^= hash_ptr(parameter);
                parameter = parameter->next;
@@ -122,6 +122,18 @@ int compound_types_equal(const compound_type_t *type1,
        if(type1->symbol != type2->symbol)
                return 0;
 
+       if(type1->symbol == NULL) {
+               /* previous tests should already have checked for this */
+               assert(type1 != type2);
+               /* anonymous types are only equal if they are the very same type */
+               return 0;
+       } else {
+               /* non-anonymous types are equal if they have the same symbol */
+               /* TODO: is this correct */
+               return 1;
+       }
+
+#if 0
        declaration_t *entry1 = type1->context.declarations;
        declaration_t *entry2 = type2->context.declarations;
 
@@ -135,6 +147,7 @@ int compound_types_equal(const compound_type_t *type1,
        }
        if(entry1 != NULL || entry2 != NULL)
                return 0;
+#endif
 
        return 1;
 }
@@ -145,8 +158,8 @@ int method_types_equal(const method_type_t *type1, const method_type_t *type2)
        if(type1->result_type != type2->result_type)
                return 0;
 
-       declaration_t *param1 = type1->parameters;
-       declaration_t *param2 = type2->parameters;
+       method_parameter_t *param1 = type1->parameters;
+       method_parameter_t *param2 = type2->parameters;
        while(param1 != NULL && param2 != NULL) {
                if(param1->type != param2->type)
                        return 0;
index f4f9592..5fc4a3e 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -83,6 +83,7 @@ struct enum_type_t {
        symbol_t          *symbol;
        enum_entry_t      *entries;
        source_position_t  source_position;
+       enum_type_t       *next;
 };
 
 struct pointer_type_t {
@@ -90,12 +91,17 @@ struct pointer_type_t {
        type_t  *points_to;
 };
 
+struct method_parameter_t {
+       type_t             *type;
+       method_parameter_t *next;
+};
+
 struct method_type_t {
-       type_t         type;
-       type_t        *result_type;
-       declaration_t *parameters;
-       int            variadic;
-       int            unspecified_parameters;
+       type_t              type;
+       type_t             *result_type;
+       method_parameter_t *parameters;
+       int                 variadic;
+       int                 unspecified_parameters;
 };
 
 struct compound_type_t {
@@ -103,6 +109,8 @@ struct compound_type_t {
        symbol_t          *symbol;
        context_t          context;
        source_position_t  source_position;
+       int                defined;
+       compound_type_t   *next;
 };
 
 #endif
index ee1793b..1d6aeff 100644 (file)
@@ -103,8 +103,8 @@ static void write_method_type(const method_type_t *type)
 {
        fprintf(out, "(func(");
 
-       declaration_t *parameter = type->parameters;
-       int            first     = 1;
+       method_parameter_t *parameter = type->parameters;
+       int                 first     = 1;
        while(parameter != NULL) {
                if(!first) {
                        fprintf(out, ", ");
@@ -112,12 +112,15 @@ static void write_method_type(const method_type_t *type)
                        first = 0;
                }
 
+#if 0
                if(parameter->symbol != NULL) {
                        fprintf(out, "%s : ", parameter->symbol->string);
                } else {
                        /* TODO make up some unused names (or allow _ in fluffy?) */
                        fprintf(out, "_ : ");
                }
+#endif
+               fputs("_ : ", out);
                write_type(parameter->type);
 
                parameter = parameter->next;
@@ -260,7 +263,7 @@ static void write_function(const declaration_t *declaration)
 
        const method_type_t *method_type = (const method_type_t*) declaration->type;
 
-       declaration_t *parameter = method_type->parameters;
+       declaration_t *parameter = declaration->context.declarations;
        int            first     = 1;
        for( ; parameter != NULL; parameter = parameter->next) {
                if(!first) {