X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/248d73924d6136eee0497a7456aba90bfef633e3..5383a8b913e74ebe5faa39ef3e570afb95779141:/src/parse-decl.c diff --git a/src/parse-decl.c b/src/parse-decl.c index 6ab624e..a6204a1 100644 --- a/src/parse-decl.c +++ b/src/parse-decl.c @@ -230,30 +230,40 @@ simplify_functions(struct cdecl_declarator **p, struct cdecl_declarator *d) free(d->child); free(d); - return 0; + return 1; } /* - * The parser's bias towards considering things as functions whenever possible - * makes nested parentheses tricky. (x) is considered to be part of a function - * declarator until simplify_functions converts it. The problem is that - * (((x))) is not valid as part of a function declarator, but it *is* valid - * as an identifier enclosed 3 times in parentheses. This is complicated by - * the fact that things like (((int))) are not valid anywhere. + * The main parser's bias towards considering things as functions whenever + * possible makes nested parentheses tricky. "(x)" is considered to be part + * of a function declarator until simplify_functions converts it. The problem + * is that "(((x)))" is not valid as part of a function declarator, but it _is_ + * valid as either an identifier enclosed thrice in parentheses, or an abstract + * function declarator enclosed twice in parentheses. + * + * To avoid ambiguities, the main parser actually returns a function declarator + * for every pair of parentheses. The ones we need to look at consist of a + * single parameter with an empty specifier list (noting that every real + * function parameter will have at least one type specifier). + * + * There are two cases: * - * To avoid ambiguities, the parser actually emits a "function" declarator for - * every pair of parentheses. The ones that can't reasonably be functions - * consist of a single "parameter" with no declaration specifiers (note that - * every valid function parameter will have at least one type specifier). + * - For (), the parser emits a parameter with a lone null declarator. + * This fake parameter simply gets deleted, leaving us with a normal + * function declarator with an empty identifier list. * - * This pass is to remove these fake functions from the parse tree. We take - * care to avoid turning invalid things like ((int)) into valid things like - * (int) by observing that the only valid function declarators that appear - * in these "fake" parentheses are those that have a non-null child declarator - * (for instance, int ((*)(int)) *or* those that will be eliminated by the - * simplify_functions pass. + * - Otherwise, the parameter's outermost declarator is not null. The + * function itself is deleted, replaced in the parse tree with the + * fake parameter's declarator. + * + * Repeating until there no fake parameters, this reduction transforms, for + * example, "(((x)))" into "(x)", an abstract function declarator. The result + * is then subject to the function simplification step, which will turn "(x)" + * into x (declaring an identifier). + * + * The whole process is repeated until no more changes are made to the parse + * tree, or a syntax error is detected. */ - static struct cdecl *fake_function_param(struct cdecl_declarator *d) { struct cdecl *param; @@ -273,34 +283,28 @@ static int reduce_parentheses(struct cdecl_declarator **p, struct cdecl_declarator *d) { struct cdecl *param; - int fake = 0; - - while ((param = fake_function_param(d))) { - struct cdecl_declarator *decl = param->declarators; - d->u.function.parameters = NULL; - - if (decl->type != CDECL_DECL_NULL) { - if (d->child->type != CDECL_DECL_NULL) { - /* Found fake parameter on real function. */ - d->u.function.parameters = param; - cdecl__errmsg(CDECL__EBADPARAM); - return -1; + + do { + d = *p; + while ((param = fake_function_param(d))) { + struct cdecl_declarator *decl = param->declarators; + d->u.function.parameters = NULL; + + if (decl->type != CDECL_DECL_NULL) { + if (d->child->type != CDECL_DECL_NULL) { + /* Fake parameter on real function. */ + d->u.function.parameters = param; + cdecl__errmsg(CDECL__EBADPARAM); + return -1; + } + + param->declarators = d; + *p = d = decl; } - param->declarators = d; - *p = d = decl; - fake = 1; + cdecl__free(param); } - - cdecl__free(param); - } - - simplify_functions(p, d); - if (fake && (*p)->type == CDECL_DECL_FUNCTION) { - /* Started with a fake function but ended with a real one. */ - cdecl__errmsg(CDECL__EMANYPAREN); - return -1; - } + } while (simplify_functions(p, d)); return 0; } @@ -514,8 +518,8 @@ static int do_postprocess(struct cdecl *decl, int english_mode) if (!valid_declspecs(i, true)) return 0; - if (cdecl_is_abstract(i->declarators) - && (i != decl || i->next)) { + if (decl->next && cdecl_is_abstract(i->declarators)) { + /* Abstract full declarators: there can only be one. */ cdecl__errmsg(CDECL__EDECLTYPE); return 0; }