]> git.draconx.ca Git - cdecl99.git/blobdiff - src/parse.y
Fix pointer declarators.
[cdecl99.git] / src / parse.y
index 394c12a083e1fb30ebbb9bb3e63381ee165654e2..06cbc07d96418508f6a951271819ac38095258f2 100644 (file)
@@ -22,6 +22,8 @@
 %locations
 
 %{
+#include <assert.h>
+
 #include "scan.h"
 #include "cdecl.h"
 
@@ -76,7 +78,21 @@ static void free_declarator(struct cdecl_declarator *x)
        struct cdecl_declarator *p;
        while (x) {
                p = x->next;
-               free(x->ident);
+               switch (x->type) {
+               case CDECL_DECL_IDENT:
+                       free(x->u.ident);
+                       break;
+               case CDECL_DECL_POINTER:
+                       free_declspec(x->u.pointer.qualifiers);
+                       free_declarator(x->u.pointer.declarator);
+                       break;
+               case CDECL_DECL_ARRAY:
+                       free(x->u.array.vla);
+                       free_declarator(x->u.array.declarator);
+                       break;
+               default:
+                       assert(0);
+               }
                free(x);
                x = p;
        }
@@ -104,6 +120,8 @@ void cdecl_free(struct cdecl *decl)
 %token T_LEX_ERROR
 
 %token <strval> T_IDENT "identifier"
+%token <uintval> T_UINT "integer constant"
+
 %token T_SEMICOLON ";"
 %token T_ASTERISK  "*"
 %token T_LPAREN    "("
@@ -140,10 +158,12 @@ void cdecl_free(struct cdecl *decl)
 %token T_UNION    "union"
 %token T_ENUM     "enum"
 
-%type <uintval>    declspec_simple typespec_simple
+%type <strval>     vla_ident
+%type <uintval>    declspec_simple typespec_simple qualifier_simple
 %type <declspec>   declspec_notype declspec_noid typespec_noid typespec
+%type <declspec>   qualifier qualifiers
 %type <declspec>   declspecs declspecs_noid
-%type <declarator> declarator declarators
+%type <declarator> direct_declarator declarator declarators pointer array
 %type <decl>       declaration
 
 %%
@@ -171,6 +191,11 @@ declspecs_noid: { $$ = NULL; } | declspec_noid declspecs_noid {
        $$->next = $2;
 }
 
+qualifiers: { $$ = NULL; } | qualifiers qualifier {
+       $$ = $2;
+       $$->next = $1;
+}
+
 declarators: declarator | declarator T_COMMA declarators {
        $$ = $1;
        $$->next = $3;
@@ -181,9 +206,6 @@ declspec_simple: T_AUTO { $$ = CDECL_STOR_AUTO;     }
        | T_EXTERN      { $$ = CDECL_STOR_EXTERN;   }
        | T_STATIC      { $$ = CDECL_STOR_STATIC;   }
        | T_REGISTER    { $$ = CDECL_STOR_REGISTER; }
-       | T_RESTRICT    { $$ = CDECL_QUAL_RESTRICT; }
-       | T_VOLATILE    { $$ = CDECL_QUAL_VOLATILE; }
-       | T_CONST       { $$ = CDECL_QUAL_CONST;    }
        | T_INLINE      { $$ = CDECL_FUNC_INLINE;   }
 
 typespec_simple: T_VOID { $$ = CDECL_TYPE_VOID;     }
@@ -198,7 +220,11 @@ typespec_simple: T_VOID { $$ = CDECL_TYPE_VOID;     }
        | T_BOOL        { $$ = CDECL_TYPE_BOOL;     }
        | T_COMPLEX     { $$ = CDECL_TYPE_COMPLEX;  }
 
-declspec_notype: declspec_simple  {
+qualifier_simple: T_CONST { $$ = CDECL_QUAL_CONST;    }
+       | T_RESTRICT      { $$ = CDECL_QUAL_RESTRICT; }
+       | T_VOLATILE      { $$ = CDECL_QUAL_VOLATILE; }
+
+declspec_notype: qualifier | declspec_simple {
        ALLOC_STRUCT($$, struct cdecl_declspec, .type = $1);
 }
 
@@ -206,6 +232,10 @@ typespec_noid: typespec_simple {
        ALLOC_STRUCT($$, struct cdecl_declspec, .type = $1);
 }
 
+qualifier: qualifier_simple {
+       ALLOC_STRUCT($$, struct cdecl_declspec, .type = $1);
+}
+
 typespec: typespec_noid | T_STRUCT T_IDENT {
        ALLOC_STRUCT($$, struct cdecl_declspec,
                .type = CDECL_TYPE_STRUCT,
@@ -226,10 +256,52 @@ typespec: typespec_noid | T_STRUCT T_IDENT {
 
 declspec_noid: declspec_notype | typespec_noid
 
-declarator: T_IDENT {
+vla_ident: T_IDENT | T_ASTERISK {
+       ALLOC($$, sizeof "");
+       strcpy($$, "");
+}
+
+array: T_LBRACKET T_UINT T_RBRACKET {
+       if ($2 == 0)
+               FAIL("array length must be positive");
+
+       ALLOC_STRUCT($$, struct cdecl_declarator,
+               .type = CDECL_DECL_ARRAY,
+               .u.array.length = $2);
+} | T_LBRACKET vla_ident T_RBRACKET {
+       ALLOC_STRUCT($$, struct cdecl_declarator,
+               .type = CDECL_DECL_ARRAY,
+               .u.array.vla = $2);
+} | T_LBRACKET T_RBRACKET {
+       ALLOC_STRUCT($$, struct cdecl_declarator,
+               .type = CDECL_DECL_ARRAY);
+}
+
+pointer: T_ASTERISK qualifiers direct_declarator {
+       ALLOC_STRUCT($$, struct cdecl_declarator,
+               .type = CDECL_DECL_POINTER,
+               .u.pointer.qualifiers = $2,
+               .u.pointer.declarator = $3);
+} | T_ASTERISK qualifiers pointer {
+       ALLOC_STRUCT($$, struct cdecl_declarator,
+               .type = CDECL_DECL_POINTER,
+               .u.pointer.qualifiers = $2,
+               .u.pointer.declarator = $3);
+}
+
+declarator: direct_declarator | pointer;
+
+direct_declarator: {
        ALLOC_STRUCT($$, struct cdecl_declarator,
                .type = CDECL_DECL_IDENT,
-               .ident = $1);
+               .u.ident = NULL);
+} | T_IDENT {
+       ALLOC_STRUCT($$, struct cdecl_declarator,
+               .type = CDECL_DECL_IDENT,
+               .u.ident = $1);
+} | direct_declarator array {
+       $$ = $2;
+       $$->u.array.declarator = $1;
 } | T_LPAREN declarator T_RPAREN {
        $$ = $2;
 };