]> git.draconx.ca Git - cdecl99.git/blobdiff - src/parse.y
Add support for array declarators.
[cdecl99.git] / src / parse.y
index 7b73eae26d9a053066b2850fbc03513b18d77a4f..8840279b020b9ab8e945eb6ae812254a8297d759 100644 (file)
@@ -84,6 +84,10 @@ static void free_declarator(struct cdecl_declarator *x)
                        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:
                        abort();
                }
@@ -114,6 +118,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    "("
@@ -150,11 +156,12 @@ void cdecl_free(struct cdecl *decl)
 %token T_UNION    "union"
 %token T_ENUM     "enum"
 
+%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 pointer
 %type <declspec>   declspecs declspecs_noid
-%type <declarator> declarator declarators
+%type <declarator> direct_declarator declarator declarators array
 %type <decl>       declaration
 
 %%
@@ -249,15 +256,41 @@ declspec_noid: declspec_notype | typespec_noid
 
 pointer: T_ASTERISK qualifiers { $$ = $2; }
 
-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_IDENT,
-               .u.ident = $1);
-} | pointer 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);
+}
+
+declarator: direct_declarator | pointer direct_declarator {
        ALLOC_STRUCT($$, struct cdecl_declarator,
                .type = CDECL_DECL_POINTER,
                .u.pointer.qualifiers = $1,
                .u.pointer.declarator = $2);
+}
+
+direct_declarator: 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;
 };