]> git.draconx.ca Git - cdecl99.git/blobdiff - src/parse.y
Kill the "horizontal" declarator chain.
[cdecl99.git] / src / parse.y
index 7d4c3dc0c889f88469c4905f9f8cf36fa685b33d..86091f9c33e71b609e8141fcf5be4e13d51f3651 100644 (file)
@@ -76,8 +76,10 @@ static void free_declspec(struct cdecl_declspec *x)
 static void free_declarator(struct cdecl_declarator *x)
 {
        struct cdecl_declarator *p;
+
        while (x) {
-               p = x->next;
+               p = x->child;
+
                switch (x->type) {
                case CDECL_DECL_NULL:
                        break;
@@ -94,23 +96,31 @@ static void free_declarator(struct cdecl_declarator *x)
                        assert(0);
                }
 
-               free_declarator(x->child);
                free(x);
                x = p;
        }
 }
 
-static void free_decl(struct cdecl *decl)
+static void free_decl(struct cdecl *x)
 {
-       free_declspec(decl->specifiers);
-       free_declarator(decl->declarators);
-       free(decl);
+       struct cdecl *p;
+
+       while (x) {
+               p = x->next;
+
+               /* The specifiers may be shared by an entire chain. */
+               if (!p || p->specifiers != x->specifiers)
+                       free_declspec(x->specifiers);
+
+               free_declarator(x->declarators);
+               free(x);
+               x = p;
+       }
 }
 
 void cdecl_free(struct cdecl *decl)
 {
-       if (decl)
-               free_decl(decl);
+       free_decl(decl);
 }
 %}
 
@@ -165,8 +175,8 @@ void cdecl_free(struct cdecl *decl)
 %type <declspec>   declspec_notype declspec_noid typespec_noid typespec
 %type <declspec>   qualifier qualifiers
 %type <declspec>   declspecs declspecs_noid
-%type <declarator> direct_declarator declarator declarators pointer array
-%type <decl>       declaration
+%type <declarator> direct_declarator declarator pointer array
+%type <decl>       declaration declarators declarator_wrap
 
 %%
 
@@ -175,9 +185,10 @@ input: declaration {
 };
 
 declaration: declspecs declarators T_SEMICOLON {
-       ALLOC_STRUCT($$, struct cdecl,
-               .specifiers = $1,
-               .declarators = $2);
+       $$ = $2;
+
+       for (struct cdecl *i = $$; i; i = i->next)
+               i->specifiers = $1;
 };
 
 declspecs: declspec_notype declspecs {
@@ -198,10 +209,14 @@ qualifiers: { $$ = NULL; } | qualifiers qualifier {
        $$->next = $1;
 }
 
-declarators: declarator | declarator T_COMMA declarators {
+declarators: declarator_wrap | declarator_wrap T_COMMA declarators {
        $$ = $1;
        $$->next = $3;
-};
+}
+
+declarator_wrap: declarator {
+       ALLOC_STRUCT($$, struct cdecl, .declarators = $1);
+}
 
 declspec_simple: T_AUTO { $$ = CDECL_STOR_AUTO;     }
        | T_TYPEDEF     { $$ = CDECL_STOR_TYPEDEF;  }