]> git.draconx.ca Git - cdecl99.git/blobdiff - src/parse-decl.c
libcdecl: Use macros for packing tokens into bytes.
[cdecl99.git] / src / parse-decl.c
index f156ba9f0052c23146cc2147f4b91b4f29b871a2..a6204a18a00c32b524d9bc5dc89cff67cc5b7905 100644 (file)
@@ -230,83 +230,81 @@ 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 int
-reduce_parentheses(struct cdecl_declarator **p, struct cdecl_declarator *d)
+static struct cdecl *fake_function_param(struct cdecl_declarator *d)
 {
        struct cdecl *param;
 
        if (d->type != CDECL_DECL_FUNCTION)
-               return 0;
+               return NULL;
 
        param = d->u.function.parameters;
-       if (param && param->specifiers == NULL) {
-               struct cdecl_declarator *decl;
+       if (!param || param->specifiers)
+               return NULL;
 
-               assert(!param->next);
+       assert(!param->next);
+       return param;
+}
 
-               decl = param->declarators;
-               if (decl->type == CDECL_DECL_NULL) {
-                       free(decl);
-                       free(param);
-                       d->u.function.parameters = NULL;
-                       return 0;
-               }
+static int
+reduce_parentheses(struct cdecl_declarator **p, struct cdecl_declarator *d)
+{
+       struct cdecl *param;
 
-               if (d->child->type != CDECL_DECL_NULL) {
-                       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;
 
-               free(d->child);
-               free(param);
-               free(d);
-               *p = decl;
+                       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;
+                               }
 
-               /*
-                * We may have replaced d with another fake function which
-                * also needs to be eliminated.
-                */
-               if (reduce_parentheses(p, decl) < 0)
-                       return -1;
+                               param->declarators = d;
+                               *p = d = decl;
+                       }
 
-               /*
-                * If the remaining declarator is a function, make sure it's
-                * valid by checking its reducibility.
-                */
-               decl = *p;
-               if (decl->type == CDECL_DECL_FUNCTION
-                   && decl->child->type == CDECL_DECL_NULL
-                   && !function_is_reducible(decl)) {
-                       cdecl__errmsg(CDECL__EMANYPAREN);
-                       return -1;
+                       cdecl__free(param);
                }
-
-               return 0;
-       }
+       } while (simplify_functions(p, d));
 
        return 0;
 }
@@ -512,8 +510,6 @@ static int do_postprocess(struct cdecl *decl, int english_mode)
                if (!english_mode) {
                        if (forall_declarators(i, reduce_parentheses) < 0)
                                return 0;
-                       if (forall_declarators(i, simplify_functions) < 0)
-                               return 0;
                }
 
                if (forall_declarators(i, postproc_common) < 0)
@@ -522,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;
                }