+input: declaration {
+ *out = $1;
+};
+
+declaration: declspecs declarators T_SEMICOLON {
+ ALLOC_STRUCT($$, struct cdecl,
+ .specifiers = $1,
+ .declarators = $2);
+};
+
+declspecs: { $$ = NULL; } | declspecs declspec {
+ $$ = $2;
+ $$->next = $1;
+}
+
+declarators: declarator | declarator T_COMMA declarators {
+ $$ = $1;
+ $$->next = $3;
+};
+
+declspec_simple: T_VOID { $$ = CDECL_TYPE_VOID; }
+ | T_CHAR { $$ = CDECL_TYPE_CHAR; }
+ | T_SHORT { $$ = CDECL_TYPE_SHORT; }
+ | T_INT { $$ = CDECL_TYPE_INT; }
+ | T_LONG { $$ = CDECL_TYPE_LONG; }
+ | T_FLOAT { $$ = CDECL_TYPE_FLOAT; }
+ | T_DOUBLE { $$ = CDECL_TYPE_DOUBLE; }
+ | T_SIGNED { $$ = CDECL_TYPE_SIGNED; }
+ | T_UNSIGNED { $$ = CDECL_TYPE_UNSIGNED; }
+ | T_BOOL { $$ = CDECL_TYPE_BOOL; }
+ | T_COMPLEX { $$ = CDECL_TYPE_COMPLEX; }
+ | T_TYPEDEF { $$ = CDECL_STOR_TYPEDEF; }
+ | T_EXTERN { $$ = CDECL_STOR_EXTERN; }
+ | T_STATIC { $$ = CDECL_STOR_STATIC; }
+ | T_AUTO { $$ = CDECL_STOR_AUTO; }
+ | 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; }
+ ;
+
+declspec: declspec_simple {
+ ALLOC_STRUCT($$, struct cdecl_declspec, .type = $1);
+} | T_STRUCT T_IDENT {
+ ALLOC_STRUCT($$, struct cdecl_declspec,
+ .type = CDECL_TYPE_STRUCT,
+ .ident = $2);
+} | T_UNION T_IDENT {
+ ALLOC_STRUCT($$, struct cdecl_declspec,
+ .type = CDECL_TYPE_UNION,
+ .ident = $2);
+} | T_ENUM T_IDENT {
+ ALLOC_STRUCT($$, struct cdecl_declspec,
+ .type = CDECL_TYPE_ENUM,
+ .ident = $2);
+} | T_IDENT {
+ ALLOC_STRUCT($$, struct cdecl_declspec,
+ .type = CDECL_TYPE_IDENT,
+ .ident = $1);
+};
+
+declarator: T_IDENT {
+ ALLOC_STRUCT($$, struct cdecl_declarator,
+ .type = CDECL_DECL_IDENT,
+ .ident = $1);
+} | T_LPAREN declarator T_RPAREN {
+ $$ = $2;
+};