]> git.draconx.ca Git - cdecl99.git/commitdiff
libcdecl: Merge both parser function implementations.
authorNick Bowler <nbowler@draconx.ca>
Wed, 28 Jun 2023 02:48:11 +0000 (22:48 -0400)
committerNick Bowler <nbowler@draconx.ca>
Sun, 2 Jul 2023 00:16:06 +0000 (20:16 -0400)
The only remaining meaningful difference between the cdecl_parse_decl
and cdecl_parse_english implementations is the function-simplification
passes are only done for cdecl_parse_decl.

We can easily just make those conditional in a common parser function,
to reduce code duplication.

src/parse-decl.c

index 7e181c082f0f1610c3498f21604293b4ec9478d3..b9685ffc673d180a280d7da2bbbddfb478cbc7d1 100644 (file)
@@ -491,86 +491,78 @@ static struct cdecl *do_parse(const char *str, int english_mode)
        return decl;
 }
 
-struct cdecl *cdecl_parse_decl(const char *declstr)
+static int do_postprocess(struct cdecl *decl, int english_mode)
 {
        struct cdecl_declspec *norm_specs;
-       struct cdecl *decl;
-
-       if (!(decl = do_parse(declstr, false)))
-               return NULL;
+       struct cdecl *i;
 
        /*
-        * Since the top-level specifiers are shared between each top-level
-        * declarator, we need to normalize them once and then propagate the
-        * new specifier list.
+        * For a C declaration with more than one full declarator, the
+        * specifier list is common to all of them.  Normalize it once,
+        * then propagate that to all the linked cdecl structures.
+        *
+        * In english mode, the cdecl structure list always has exactly
+        * one entry so we don't need to do anything differently.
         */
        norm_specs = cdecl__normalize_specs(decl->specifiers);
-       for (struct cdecl *i = decl; i; i = i->next) {
+       for (i = decl; i; i = i->next)
                i->specifiers = norm_specs;
-       }
 
-       /* Now perform checks and simplifications on each declarator. */
-       for (struct cdecl *i = decl; i; i = i->next) {
-               if (!forall_declarators(i, reduce_parentheses))
-                       goto err;
-               if (!forall_declarators(i, simplify_functions))
-                       goto err;
+       for (i = decl; i; i = i->next) {
+               if (!english_mode) {
+                       if (!forall_declarators(i, reduce_parentheses))
+                               return 0;
+                       if (!forall_declarators(i, simplify_functions))
+                               return 0;
+               }
+
                if (!forall_declarators(i, check_parameters))
-                       goto err;
+                       return 0;
                if (!forall_declarators(i, check_rettypes))
-                       goto err;
+                       return 0;
                if (!forall_declarators(i, check_arrays))
-                       goto err;
+                       return 0;
                if (!forall_declarators(i, normalize_specs))
-                       goto err;
+                       return 0;
                if (!forall_declarators(i, check_qualifiers))
-                       goto err;
+                       return 0;
 
                if (!valid_declspecs(i, true))
-                       goto err;
+                       return 0;
 
                if (cdecl_is_abstract(i->declarators)
                    && (i != decl || i->next)) {
                        cdecl__errmsg(CDECL__EDECLTYPE);
-                       goto err;
+                       return 0;
                }
        }
 
-       return decl;
-err:
-       cdecl__free(decl);
-       return NULL;
+       return 1;
 }
 
-struct cdecl *cdecl_parse_english(const char *english)
+static struct cdecl *parse_common(const char *str, int english_mode)
 {
        struct cdecl *decl;
 
-       if (!(decl = do_parse(english, true)))
+       if (!(decl = do_parse(str, english_mode)))
                return NULL;
 
-       for (struct cdecl *i = decl; i; i = i->next) {
-               i->specifiers = cdecl__normalize_specs(i->specifiers);
-
-               if (!forall_declarators(i, check_parameters))
-                       goto err;
-               if (!forall_declarators(i, check_rettypes))
-                       goto err;
-               if (!forall_declarators(i, check_arrays))
-                       goto err;
-               if (!forall_declarators(i, normalize_specs))
-                       goto err;
-               if (!forall_declarators(i, check_qualifiers))
-                       goto err;
-
-               if (!valid_declspecs(i, true))
-                       goto err;
+       if (!do_postprocess(decl, english_mode)) {
+               cdecl__free(decl);
+               return NULL;
        }
 
        return decl;
-err:
-       cdecl__free(decl);
-       return NULL;
+}
+
+struct cdecl *cdecl_parse_decl(const char *declstr)
+{
+       return parse_common(declstr, false);
+}
+
+struct cdecl *cdecl_parse_english(const char *english)
+{
+       return parse_common(english, true);
 }
 
 void cdecl_free(struct cdecl *decl)