X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/05d0ced1aa6c1e685e3228e7c43aab3fbb1d88c3..21bc2db0ec83b235caec38d42f4d0812f473d766:/src/parse.y diff --git a/src/parse.y b/src/parse.y index ec7ea1b..ba9bf22 100644 --- a/src/parse.y +++ b/src/parse.y @@ -76,10 +76,10 @@ const char *cdecl__token_name(unsigned token); uintmax_t uintval; unsigned spectype; _Bool boolval; - char *strval; struct cdecl_declspec *declspec; struct cdecl_declarator *declarator; struct cdecl *decl; + struct parse_item *item; } %{ @@ -91,7 +91,6 @@ static void free_declspec(struct cdecl_declspec *x) struct cdecl_declspec *p; while (x) { p = x->next; - free(x->ident); free(x); x = p; } @@ -106,16 +105,13 @@ static void free_declarator(struct cdecl_declarator *x) switch (x->type) { case CDECL_DECL_NULL: - break; + x = NULL; case CDECL_DECL_IDENT: - free(x->u.ident); + case CDECL_DECL_ARRAY: break; case CDECL_DECL_POINTER: free_declspec(x->u.pointer.qualifiers); break; - case CDECL_DECL_ARRAY: - free(x->u.array.vla); - break; case CDECL_DECL_FUNCTION: free_decl(x->u.function.parameters); break; @@ -167,21 +163,27 @@ static void join_specs(struct cdecl_declspec *a, struct cdecl_declspec *b) * Alter an abstract declarator (type name) to declare an identifier instead, * used by the English parser rules to reduce "identifier as type" sequences. */ -static struct cdecl *insert_identifier(struct cdecl *decl, char *ident) +static struct cdecl *insert_identifier(struct cdecl *decl, struct parse_item *ident) { - struct cdecl_declarator *d = decl->declarators; - - while (d->child) - d = d->child; + struct cdecl_declarator *d, **p = &decl->declarators; - d->type = CDECL_DECL_IDENT; - d->u.ident = ident; + while ((d = *p)->child) + p = &d->child; + *p = &ident->u.declarator; return decl; } + +static struct cdecl_declarator *nulldecl(void) +{ + static const struct cdecl_declarator nulldecl = {0}; + return (void *)&nulldecl; +} +#define NULLDECL (nulldecl()) + %} -%destructor { free($$); } +%destructor { free($$); } %destructor { free_declspec($$); } %destructor { free_declarator($$); } %destructor { free_decl($$); } @@ -189,8 +191,8 @@ static struct cdecl *insert_identifier(struct cdecl *decl, char *ident) /* Magic tokens */ %token T_LEX_ERROR -%token T_IDENT "identifier" -%token T_UINT "integer constant" +%token T_IDENT "identifier" +%token T_UINT "integer constant" %token T_SEMICOLON ";" %token T_ASTERISK "*" @@ -244,7 +246,7 @@ static struct cdecl *insert_identifier(struct cdecl *decl, char *ident) %token T_AS "as" %token T_VLA "variable-length" -%type vla_ident +%type vla_ident %type array_length %type varargs %type declspec_simple qualifier_simple @@ -257,7 +259,7 @@ static struct cdecl *insert_identifier(struct cdecl *decl, char *ident) %type declaration declarators declarator_wrap %type parameter -%type english_vla +%type english_vla %type storage_func_specs post_specs %type type_qual_spec type_qual_specs typedef_name_qual %type english_declarator english_array english_function @@ -366,16 +368,19 @@ qualifier: qualifier_simple { } typespec: typespec_noid | typespec_tagged T_IDENT { - ALLOC_STRUCT($$, struct cdecl_declspec, - .type = $1, - .ident = $2); + /* Compiler should be able to elide this assignment. */ + $2->u.declspec.ident = $2->u.declarator.u.ident; + + $$ = &$2->u.declspec; + $$->type = $1; } declspec_noid: declspec_notype | typespec_noid vla_ident: T_IDENT | T_ASTERISK { - ALLOC($$, sizeof ""); - *$$ = 0; + if (!($$ = cdecl__alloc_item(1))) + YYERROR; + *$$->s = 0; } array: T_LBRACKET array_length T_RBRACKET { @@ -383,9 +388,10 @@ array: T_LBRACKET array_length T_RBRACKET { .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); + $$ = &$2->u.declarator; + $$->type = CDECL_DECL_ARRAY; + $$->u.array.vla = $$->u.ident; + $$->u.array.length = 0; } parameter: declspecs declarator { @@ -433,20 +439,16 @@ declarator_ish: direct_declarator_ish | pointer postfix: array | parens direct_declarator_ish: { - ALLOC_STRUCT($$, struct cdecl_declarator, - .type = CDECL_DECL_NULL); + $$ = NULLDECL; } | direct_declarator_ish postfix { $$ = $2; $$->child = $1; } direct_declarator: { - ALLOC_STRUCT($$, struct cdecl_declarator, - .type = CDECL_DECL_NULL); + $$ = NULLDECL; } | T_IDENT { - ALLOC_STRUCT($$, struct cdecl_declarator, - .type = CDECL_DECL_IDENT, - .u.ident = $1); + $$ = &$1->u.declarator; } | direct_declarator postfix { $$ = $2; $$->child = $1; @@ -495,8 +497,7 @@ english_declaration: storage_func_specs english_declarator post_specs { } english_declarator: { - ALLOC_STRUCT($$, struct cdecl_declarator, - .type = CDECL_DECL_NULL); + $$ = NULLDECL; } | english_declarator qualifiers T_POINTER T_TO { ALLOC_STRUCT($$, struct cdecl_declarator, .type = CDECL_DECL_POINTER, @@ -530,15 +531,16 @@ english_parameter_list: english_parameter varargs { } typedef_name_qual: T_IDENT qualifiers { - ALLOC_STRUCT($$, struct cdecl_declspec, - .type = CDECL_TYPE_IDENT, - .ident = $1, - .next = $2); + /* Compiler should be able to elide this assignment. */ + $1->u.declspec.ident = $1->u.declarator.u.ident; + + $$ = &$1->u.declspec; + $$->type = CDECL_TYPE_IDENT; + $$->next = $2; } null_decl: { - ALLOC_STRUCT($$, struct cdecl_declarator, - .type = CDECL_DECL_NULL); + $$ = NULLDECL; } /* @@ -564,9 +566,10 @@ english_parameter: english_declaration | typedef_name_qual null_decl { } english_array: T_VLA T_ARRAY english_vla T_OF { - ALLOC_STRUCT($$, struct cdecl_declarator, - .type = CDECL_DECL_ARRAY, - .u.array.vla = $3); + $$ = &$3->u.declarator; + $$->type = CDECL_DECL_ARRAY; + $$->u.array.vla = $$->u.ident; + $$->u.array.length = 0; } | T_ARRAY array_length T_OF { ALLOC_STRUCT($$, struct cdecl_declarator, .type = CDECL_DECL_ARRAY, @@ -580,8 +583,9 @@ array_length: T_UINT { } english_vla: T_IDENT | { - ALLOC($$, sizeof ""); - *$$ = 0; + if (!($$ = cdecl__alloc_item(1))) + YYERROR; + *$$->s = 0; } %%