more work on parser
authorMatthias Braun <matze@braunis.de>
Sun, 17 Jun 2007 10:06:29 +0000 (10:06 +0000)
committerMatthias Braun <matze@braunis.de>
Sun, 17 Jun 2007 10:06:29 +0000 (10:06 +0000)
[r18329]

Makefile
main.c
parser.c
type.c
type.h
type_hash.c [new file with mode: 0644]
type_hash.h [new file with mode: 0644]
type_t.h

index 0cb59fc..ea97557 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -23,7 +23,8 @@ SOURCES := \
        parser.c \
        symbol_table.c \
        token.c \
-       type.c
+       type.c \
+       type_hash.c
 
 OBJECTS = $(SOURCES:%.c=build/%.o)
 
diff --git a/main.c b/main.c
index 6ac6625..eb0c479 100644 (file)
--- a/main.c
+++ b/main.c
@@ -7,6 +7,7 @@
 
 #include "lexer_t.h"
 #include "token_t.h"
+#include "type_hash.h"
 #include "parser.h"
 
 #if 0
@@ -65,6 +66,8 @@ int main(int argc, char **argv)
        init_symbol_table();
        init_tokens();
        init_lexer();
+       init_types();
+       init_typehash();
        init_ast();
        init_parser();
 
@@ -74,6 +77,8 @@ int main(int argc, char **argv)
 
        exit_parser();
        exit_ast();
+       exit_typehash();
+       exit_types();
        exit_lexer();
        exit_tokens();
        exit_symbol_table();
index f823725..4d67fc3 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -6,6 +6,7 @@
 #include "lexer_t.h"
 #include "token_t.h"
 #include "type_t.h"
+#include "type_hash.h"
 #include "ast_t.h"
 #include "adt/bitfiddle.h"
 #include "adt/error.h"
@@ -104,6 +105,15 @@ void eat_until_semi(void)
     }                                              \
     next_token();
 
+#define expect_void(expected)                      \
+    if(UNLIKELY(token.type != (expected))) {       \
+        parse_error_expected(NULL, (expected), 0); \
+        eat_until_semi();                          \
+        return;                                    \
+    }                                              \
+    next_token();
+
+
 typedef enum {
        SPECIFIER_SIGNED    = 1 << 0,
        SPECIFIER_UNSIGNED  = 1 << 1,
@@ -124,13 +134,6 @@ typedef enum {
 #endif
 } specifiers_t;
 
-typedef enum {
-       TYPE_QUALIFIER_CONST    = 1 << 0,
-       TYPE_QUALIFIER_RESTRICT = 1 << 1,
-       TYPE_QUALIFIER_VOLATILE = 1 << 2,
-       TYPE_QUALIFIER_INLINE   = 1 << 3,
-} type_qualifier_t;
-
 typedef enum {
        STORAGE_CLASS_NONE,
        STORAGE_CLASS_TYPEDEF,
@@ -143,7 +146,7 @@ typedef enum {
 typedef struct declaration_specifiers_t  declaration_specifiers_t;
 struct declaration_specifiers_t {
        storage_class_t  storage_class;
-       int              type_qualifiers;
+       type_t          *type;
 };
 
 static
@@ -151,6 +154,7 @@ void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
 {
        type_type_t        type_type       = TYPE_INVALID;
        atomic_type_type_t atomic_type     = ATOMIC_TYPE_INVALID;
+       unsigned           type_qualifiers = 0;
        unsigned           type_specifiers = 0;
 
        while(1) {
@@ -176,7 +180,7 @@ void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                /* type qualifiers */
 #define MATCH_TYPE_QUALIFIER(token, qualifier)                          \
                case token:                                                     \
-                       specifiers->type_qualifiers |= qualifier;                   \
+                       type_qualifiers |= qualifier;                               \
                        next_token();                                               \
                        break;
 
@@ -230,10 +234,11 @@ void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
 
                /* function specifier */
                default:
-                       return;;
+                       goto finish_specifiers;
                }
        }
 
+finish_specifiers:
        if(type_type == TYPE_INVALID) {
                /* match valid basic types */
                switch(type_specifiers) {
@@ -334,7 +339,25 @@ void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                        } else {
                                parse_error("multiple datatypes in declaration");
                        }
+                       atomic_type = ATOMIC_TYPE_INVALID;
+               }
+
+               atomic_type_t *type = obstack_alloc(type_obst, sizeof(type[0]));
+               memset(type, 0, sizeof(type[0]));
+               type->type.type       = TYPE_ATOMIC;
+               type->type.qualifiers = type_qualifiers;
+               type->atype           = atomic_type;
+
+               type_t *result = typehash_insert((type_t*) type);
+               if(result != (type_t*) type) {
+                       obstack_free(type_obst, type);
                }
+
+               specifiers->type = result;
+
+               fprintf(stderr, "Specifiers type: ");
+               print_type(stderr, result);
+               fprintf(stderr, "\n");
        } else {
                if(type_specifiers != 0) {
                        parse_error("multiple datatypes in declaration");
@@ -342,35 +365,60 @@ void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
        }
 }
 
-typedef struct declarator_t declarator_t;
-struct declarator_t {
-       /* pointer stuff... */
-       symbol_t     *symbol;
+static
+unsigned parse_type_qualifiers()
+{
+       unsigned type_qualifiers = 0;
 
-       declarator_t *next;
-};
+       while(1) {
+               switch(token.type) {
+               /* type qualifiers */
+               MATCH_TYPE_QUALIFIER(T_const,    TYPE_QUALIFIER_CONST);
+               MATCH_TYPE_QUALIFIER(T_restrict, TYPE_QUALIFIER_RESTRICT);
+               MATCH_TYPE_QUALIFIER(T_volatile, TYPE_QUALIFIER_VOLATILE);
+               MATCH_TYPE_QUALIFIER(T_inline,   TYPE_QUALIFIER_INLINE);
+
+               default:
+                       return type_qualifiers;
+               }
+       }
+}
 
-declarator_t *parse_declarator(void)
+static
+void parse_declarator(const declaration_specifiers_t *specifiers)
 {
+       type_t *type = specifiers->type;
+
        while(token.type == '*') {
                /* pointer */
                next_token();
-               //parse_type_qualifiers();
-       }
 
-       declarator_t *declarator;
+               pointer_type_t *pointer_type
+                       = obstack_alloc(type_obst, sizeof(pointer_type[0]));
+               memset(pointer_type, 0, sizeof(pointer_type[0]));
+               pointer_type->type.type = TYPE_POINTER;
+               pointer_type->points_to = type;
+
+               pointer_type->type.qualifiers = parse_type_qualifiers();
+
+               type_t *result = typehash_insert((type_t*) pointer_type);
+               if(result != (type_t*) pointer_type) {
+                       obstack_free(type_obst, pointer_type);
+               }
+
+               type = result;
+       }
 
        switch(token.type) {
        case T_IDENTIFIER:
-               declarator = allocate_ast_zero(sizeof(declarator[0]));
-               declarator->symbol = token.v.symbol;
+               (void) token.v.symbol;
                next_token();
-               return declarator;
+               break;
        case '(':
                next_token();
-               declarator = parse_declarator();
-               expect(')')
-               return declarator;
+               parse_declarator(specifiers);
+               expect_void(')');
+               return;
        default:
                parse_error("problem while parsing declarator");
        }
@@ -380,7 +428,7 @@ declarator_t *parse_declarator(void)
 
                /* parse parameter-type-list or identifier-list */
 
-               expect(')');
+               expect_void(')');
        } else if(token.type == '[') {
                next_token();
 
@@ -388,29 +436,23 @@ declarator_t *parse_declarator(void)
 
                /* assignment_expression or '*' or nothing */
 
-               expect(']');
+               expect_void(']');
        }
 
-       return declarator;
+       fprintf(stderr, "Declarator type: ");
+       print_type(stderr, type);
+       fprintf(stderr, "\n");
 }
 
 void parse_init_declarators(const declaration_specifiers_t *specifiers)
 {
-       (void) specifiers;
-       declarator_t *declarator = parse_declarator();
+       parse_declarator(specifiers);
        if(token.type == '=') {
                next_token();
                //parse_initialize();
        }
-       (void) declarator;
 }
 
-typedef struct declaration_t declaration_t;
-struct declaration_t {
-       declaration_specifiers_t  specifiers;
-       declaration_t            *declarators;
-};
-
 void parse_declaration(void)
 {
        declaration_specifiers_t specifiers;
@@ -420,15 +462,6 @@ void parse_declaration(void)
        parse_init_declarators(&specifiers);
 }
 
-#if 0
-namespace_t *parse(FILE *in, const char *input_name)
-{
-       namespace_t *namespace = parse_namespace();
-
-       return namespace;
-}
-#endif
-
 
 
 static
@@ -1069,9 +1102,11 @@ statement_t *parse_compound_statement(void)
 static
 void parse_translation_unit(void)
 {
+       /*
        declaration_specifiers_t specifiers;
        memset(&specifiers, 0, sizeof(specifiers));
        parse_declaration_specifiers(&specifiers);
+       */
 
        while(token.type != T_EOF) {
                if(token.type == '{') {
diff --git a/type.c b/type.c
index 7f64f86..9ac9f2e 100644 (file)
--- a/type.c
+++ b/type.c
@@ -6,19 +6,39 @@
 static struct obstack  _type_obst;
 struct obstack        *type_obst = &_type_obst;
 
-void init_type_module()
+void init_types()
 {
        obstack_init(type_obst);
 }
 
-void exit_type_module()
+void exit_types()
 {
        obstack_free(type_obst, NULL);
 }
 
+static
+void print_type_qualifiers(FILE *out, const type_t *type)
+{
+       unsigned qualifiers = type->qualifiers;
+       if(qualifiers & TYPE_QUALIFIER_CONST) {
+               fputs("const ", out);
+       }
+       if(qualifiers & TYPE_QUALIFIER_VOLATILE) {
+               fputs("volatile ", out);
+       }
+       if(qualifiers & TYPE_QUALIFIER_RESTRICT) {
+               fputs("restrict ", out);
+       }
+       if(qualifiers & TYPE_QUALIFIER_INLINE) {
+               fputs("inline ", out);
+       }
+}
+
 static
 void print_atomic_type(FILE *out, const atomic_type_t *type)
 {
+       print_type_qualifiers(out, & type->type);
+
        switch(type->atype) {
        case ATOMIC_TYPE_INVALID:   fputs("INVALIDATOMIC", out); break;
        case ATOMIC_TYPE_BOOL:      fputs("bool", out); break;
@@ -42,6 +62,8 @@ void print_atomic_type(FILE *out, const atomic_type_t *type)
 static
 void print_method_type(FILE *out, const method_type_t *type)
 {
+       print_type_qualifiers(out, & type->type);
+
        fputs("<", out);
        print_type(out, type->result_type);
        fputs(" ", out);
@@ -69,6 +91,7 @@ void print_pointer_type(FILE *out, const pointer_type_t *type)
 {
        print_type(out, type->points_to);
        fputs("*", out);
+       print_type_qualifiers(out, &type->type);
 }
 
 void print_type(FILE *out, const type_t *type)
@@ -83,7 +106,7 @@ void print_type(FILE *out, const type_t *type)
                fputs("invalid", out);
                return;
        case TYPE_ENUM:
-       case TYPE_TYPEDEF:
+               print_type_qualifiers(out, type);
                fputs("TODO", out);
                return;
        case TYPE_ATOMIC:
@@ -91,6 +114,7 @@ void print_type(FILE *out, const type_t *type)
                return;
        case TYPE_COMPOUND_STRUCT:
        case TYPE_COMPOUND_UNION:
+               print_type_qualifiers(out, type);
                fprintf(out, "%s", ((const compound_type_t*) type)->symbol->string);
                return;
        case TYPE_METHOD:
diff --git a/type.h b/type.h
index 5325463..e1f5444 100644 (file)
--- a/type.h
+++ b/type.h
@@ -10,9 +10,10 @@ typedef struct method_parameter_type_t  method_parameter_type_t;
 typedef struct method_type_t            method_type_t;
 typedef struct compound_entry_t         compound_entry_t;
 typedef struct compound_type_t          compound_type_t;
+typedef struct enum_type_t              enum_type_t;
 
-void init_type_module(void);
-void exit_type_module(void);
+void init_types(void);
+void exit_types(void);
 
 /**
  * prints a human readable form of @p type to a stream
diff --git a/type_hash.c b/type_hash.c
new file mode 100644 (file)
index 0000000..b3ae801
--- /dev/null
@@ -0,0 +1,246 @@
+#include <config.h>
+
+#include "type_hash.h"
+
+#include "adt/error.h"
+#include "type_t.h"
+
+#include <assert.h>
+
+#define HashSet         type_hash_t
+#define HashSetIterator type_hash_iterator_t
+#define ValueType       type_t*
+#include "adt/hashset.h"
+#undef ValueType
+#undef HashSetIterator
+#undef HashSet
+
+static
+unsigned hash_ptr(const void *ptr)
+{
+       unsigned ptr_int = (ptr - NULL);
+       return ptr_int >> 3;
+}
+
+static
+unsigned hash_atomic_type(const atomic_type_t *type)
+{
+       unsigned some_prime = 27644437;
+
+       return type->atype * some_prime;
+}
+
+static
+unsigned hash_pointer_type(const pointer_type_t *type)
+{
+       return hash_ptr(type->points_to);
+}
+
+static
+unsigned hash_compound_type(const compound_type_t *type)
+{
+       unsigned result = hash_ptr(type->symbol);
+
+       return result;
+}
+
+static
+unsigned hash_type(const type_t *type);
+
+static
+unsigned hash_method_type(const method_type_t *type)
+{
+       unsigned result = hash_ptr(type->result_type);
+
+       method_parameter_type_t *parameter = type->parameter_types;
+       while(parameter != NULL) {
+               result ^= hash_ptr(parameter->type);
+               parameter = parameter->next;
+       }
+       result ^= hash_ptr(type->abi_style);
+
+       return result;
+}
+
+static
+unsigned hash_enum_type(const enum_type_t *type)
+{
+       unsigned result = hash_ptr(type->symbol);
+
+       /* TODO */
+
+       return result;
+}
+
+static
+unsigned hash_type(const type_t *type)
+{
+       unsigned hash;
+
+       switch(type->type) {
+       case TYPE_INVALID:
+               panic("internalizing void or invalid types not possible");
+               return 0;
+       case TYPE_ATOMIC:
+               hash = hash_atomic_type((const atomic_type_t*) type);
+               break;
+       case TYPE_ENUM:
+               hash = hash_enum_type((const enum_type_t*) type);
+               break;
+       case TYPE_COMPOUND_STRUCT:
+       case TYPE_COMPOUND_UNION:
+               hash = hash_compound_type((const compound_type_t*) type);
+               break;
+       case TYPE_METHOD:
+               hash = hash_method_type((const method_type_t*) type);
+               break;
+       case TYPE_POINTER:
+               hash = hash_pointer_type((const pointer_type_t*) type);
+               break;
+       }
+
+       unsigned some_prime = 99991;
+       hash ^= some_prime * type->qualifiers;
+
+       return hash;
+}
+
+static
+int atomic_types_equal(const atomic_type_t *type1, const atomic_type_t *type2)
+{
+       return type1->atype == type2->atype;
+}
+
+static
+int compound_types_equal(const compound_type_t *type1,
+                         const compound_type_t *type2)
+{
+       if(type1->symbol != type2->symbol)
+               return 0;
+
+#if 0
+       struct_entry_t *entry1 = type1->entries;
+       struct_entry_t *entry2 = type2->entries;
+
+       while(entry1 != NULL && entry2 != NULL) {
+               if(entry1->type != entry2->type)
+                       return 0;
+               entry1 = entry1->next;
+               entry2 = entry2->next;
+       }
+       if(entry1 != NULL || entry2 != NULL)
+               return 0;
+#endif
+
+       return 1;
+}
+
+static
+int method_types_equal(const method_type_t *type1, const method_type_t *type2)
+{
+       if(type1->result_type != type2->result_type)
+               return 0;
+
+       if(type1->abi_style != type2->abi_style)
+               return 0;
+
+       method_parameter_type_t *param1 = type1->parameter_types;
+       method_parameter_type_t *param2 = type2->parameter_types;
+       while(param1 != NULL && param2 != NULL) {
+               if(param1->type != param2->type)
+                       return 0;
+               param1 = param1->next;
+               param2 = param2->next;
+       }
+       if(param1 != NULL || param2 != NULL)
+               return 0;
+
+       return 1;
+}
+
+static
+int pointer_types_equal(const pointer_type_t *type1,
+                        const pointer_type_t *type2)
+{
+       return type1->points_to == type2->points_to;
+}
+
+static
+int enum_types_equal(const enum_type_t *type1, const enum_type_t *type2)
+{
+       /* TODO */
+       return type1->symbol == type2->symbol;
+}
+
+static
+int types_equal(const type_t *type1, const type_t *type2)
+{
+       if(type1 == type2)
+               return 1;
+       if(type1->type != type2->type)
+               return 0;
+       if(type1->qualifiers != type2->qualifiers)
+               return 0;
+
+       switch(type1->type) {
+       case TYPE_INVALID:
+               return 0;
+       case TYPE_ATOMIC:
+               return atomic_types_equal((const atomic_type_t*) type1,
+                                         (const atomic_type_t*) type2);
+       case TYPE_COMPOUND_STRUCT:
+       case TYPE_COMPOUND_UNION:
+               return compound_types_equal((const compound_type_t*) type1,
+                                           (const compound_type_t*) type2);
+       case TYPE_ENUM:
+               return enum_types_equal((const enum_type_t*) type1,
+                                       (const enum_type_t*) type2);
+       case TYPE_METHOD:
+               return method_types_equal((const method_type_t*) type1,
+                                         (const method_type_t*) type2);
+       case TYPE_POINTER:
+               return pointer_types_equal((const pointer_type_t*) type1,
+                                          (const pointer_type_t*) type2);
+       }
+
+       abort();
+}
+
+#define HashSet                    type_hash_t
+#define HashSetIterator            type_hash_iterator_t
+#define ValueType                  type_t*
+#define NullValue                  NULL
+#define DeletedValue               ((type_t*)-1)
+#define Hash(this, key)            hash_type(key)
+#define KeysEqual(this,key1,key2)  types_equal(key1, key2)
+#define SetRangeEmpty(ptr,size)    memset(ptr, 0, (size) * sizeof(*(ptr)))
+
+#define hashset_init             _typehash_init
+#define hashset_init_size        _typehash_init_size
+#define hashset_destroy          _typehash_destroy
+#define hashset_insert           _typehash_insert
+#define hashset_remove           typehash_remove
+#define hashset_find             typehash_find
+#define hashset_size             typehash_size
+#define hashset_iterator_init    typehash_iterator_init
+#define hashset_iterator_next    typehash_iterator_next
+#define hashset_remove_iterator  typehash_remove_iterator
+
+#include "adt/hashset.c"
+
+static type_hash_t typehash;
+
+void init_typehash(void)
+{
+       _typehash_init(&typehash);
+}
+
+void exit_typehash(void)
+{
+       _typehash_destroy(&typehash);
+}
+
+type_t *typehash_insert(type_t *type)
+{
+       return _typehash_insert(&typehash, type);
+}
diff --git a/type_hash.h b/type_hash.h
new file mode 100644 (file)
index 0000000..291cb38
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef TYPE_HASH_H
+#define TYPE_HASH_H
+
+#include "type.h"
+
+void init_typehash(void);
+void exit_typehash(void);
+
+type_t *typehash_insert(type_t *type);
+int     typehash_contains(type_t *type);
+
+#endif
index 6e05d31..9d2b61e 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -14,7 +14,6 @@ typedef enum {
        TYPE_COMPOUND_STRUCT,
        TYPE_COMPOUND_UNION,
        TYPE_ENUM,
-       TYPE_TYPEDEF,
        TYPE_METHOD,
        TYPE_POINTER
 } type_type_t;
@@ -49,8 +48,16 @@ typedef enum {
 #endif
 } atomic_type_type_t;
 
+typedef enum {
+       TYPE_QUALIFIER_CONST    = 1 << 0,
+       TYPE_QUALIFIER_RESTRICT = 1 << 1,
+       TYPE_QUALIFIER_VOLATILE = 1 << 2,
+       TYPE_QUALIFIER_INLINE   = 1 << 3,
+} type_qualifier_t;
+
 struct type_t {
        type_type_t  type;
+       unsigned     qualifiers;
 };
 
 struct atomic_type_t {
@@ -89,4 +96,10 @@ struct compound_type_t {
        source_position_t  source_position;
 };
 
+struct enum_type_t {
+       /* todo */
+       symbol_t          *symbol;
+       source_position_t  source_position;
+};
+
 #endif