]> git.draconx.ca Git - cdecl99.git/blobdiff - src/parse.y
Initial support for function declarators.
[cdecl99.git] / src / parse.y
index ac8524c4bd5d999faca3c17b9458d4d46f90f00f..63d5fa927dc4ec48e1289321798bcb68183a3acf 100644 (file)
@@ -25,6 +25,7 @@
 
 %{
 #include <assert.h>
+#include <stdbool.h>
 
 #include "scan.h"
 #include "cdecl.h"
@@ -57,6 +58,7 @@ int yyparse(struct cdecl **out);
 
 %union {
        uintmax_t uintval;
+       _Bool boolval;
        char *strval;
        struct cdecl_declspec *declspec;
        struct cdecl_declarator *declarator;
@@ -64,6 +66,8 @@ int yyparse(struct cdecl **out);
 }
 
 %{
+static void free_decl(struct cdecl *);
+
 static void free_declspec(struct cdecl_declspec *x)
 {
        struct cdecl_declspec *p;
@@ -94,6 +98,9 @@ static void free_declarator(struct cdecl_declarator *x)
                case CDECL_DECL_ARRAY:
                        free(x->u.array.vla);
                        break;
+               case CDECL_DECL_FUNCTION:
+                       free_decl(x->u.function.parameters);
+                       break;
                default:
                        assert(0);
                }
@@ -143,6 +150,7 @@ void cdecl_free(struct cdecl *decl)
 %token T_LBRACKET  "["
 %token T_RBRACKET  "]"
 %token T_COMMA     ","
+%token T_ELLIPSIS  "."
 
 %token T_TYPEDEF  "typedef"
 %token T_EXTERN   "extern"
@@ -173,12 +181,15 @@ void cdecl_free(struct cdecl *decl)
 %token T_ENUM     "enum"
 
 %type <strval>     vla_ident
+%type <boolval>    varargs
 %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> direct_declarator declarator pointer array
+%type <declarator> direct_declarator declarator pointer array parens postfix
+%type <declarator> direct_declarator_ish declarator_ish parameter_type_list
 %type <decl>       declaration declarators declarator_wrap
+%type <decl>       parameter parameters
 
 %%
 
@@ -296,6 +307,43 @@ array: T_LBRACKET T_UINT T_RBRACKET {
                .type = CDECL_DECL_ARRAY);
 }
 
+parameter: declspecs declarator {
+       ALLOC_STRUCT($$, struct cdecl,
+               .specifiers = $1,
+               .declarators = $2);
+}
+
+parameters: parameter | parameters T_COMMA parameter {
+       $$ = $3;
+       $$->next = $1;
+}
+
+varargs: { $$ = false; } | T_COMMA T_ELLIPSIS { $$ = true; }
+
+parameter_type_list: parameters varargs {
+       struct cdecl *p, *c, *n;
+
+       /* Parameters were accumulated in reverse order. */
+       for (p = NULL, c = $1; c; p = c, c = n) {
+               n = c->next;
+               c->next = p;
+       }
+
+       ALLOC_STRUCT($$, struct cdecl_declarator,
+               .type = CDECL_DECL_FUNCTION,
+               .u.function.parameters = p,
+               .u.function.variadic = $2);
+}
+
+parens: T_LPAREN parameter_type_list T_RPAREN {
+       $$ = $2;
+} | T_LPAREN declarator_ish T_RPAREN {
+       ALLOC_STRUCT($$, struct cdecl_declarator,
+               .type = CDECL_DECL_FUNCTION);
+       ALLOC_STRUCT($$->u.function.parameters, struct cdecl,
+               .declarators = $2);
+}
+
 pointer: T_ASTERISK qualifiers direct_declarator {
        ALLOC_STRUCT($$, struct cdecl_declarator,
                .type = CDECL_DECL_POINTER,
@@ -309,6 +357,16 @@ pointer: T_ASTERISK qualifiers direct_declarator {
 }
 
 declarator: direct_declarator | pointer
+declarator_ish: direct_declarator_ish | pointer
+postfix: array | parens
+
+direct_declarator_ish: {
+       ALLOC_STRUCT($$, struct cdecl_declarator,
+               .type = CDECL_DECL_NULL);
+} | direct_declarator_ish postfix {
+       $$ = $2;
+       $$->child = $1;
+}
 
 direct_declarator: {
        ALLOC_STRUCT($$, struct cdecl_declarator,
@@ -317,12 +375,10 @@ direct_declarator: {
        ALLOC_STRUCT($$, struct cdecl_declarator,
                .type = CDECL_DECL_IDENT,
                .u.ident = $1);
-} | direct_declarator array {
+} | direct_declarator postfix {
        $$ = $2;
        $$->child = $1;
-} | T_LPAREN declarator T_RPAREN {
-       $$ = $2;
-};
+}
 
 %%
 void yyerror(YYLTYPE *loc, struct cdecl **out, const char *err)