]> git.draconx.ca Git - cdecl99.git/blobdiff - src/parse-decl.c
libcdecl: Merge both parser function implementations.
[cdecl99.git] / src / parse-decl.c
index 1b38153216e16b588324318c851a3c660f327a5a..b9685ffc673d180a280d7da2bbbddfb478cbc7d1 100644 (file)
@@ -25,6 +25,7 @@
 #include "cdecl-internal.h"
 #include "parse.h"
 #include "scan.h"
+#include "errmsg.h"
 
 /*
  * We can represent type specifiers as a bitmap, which gives us a finite
@@ -63,9 +64,9 @@ static int valid_typespec(struct cdecl_declspec *s)
 
                if (map & bit) {
                        if (bit == 1ul << MAP_LLONG_BIT)
-                               cdecl__err(CDECL_EBADTYPE, _("too many long specifiers"));
+                               cdecl__errmsg(CDECL__ETOOLONG);
                        else
-                               cdecl__err(CDECL_EBADTYPE, _("duplicate type specifier"));
+                               cdecl__errmsg(CDECL__EDUPTYPE);
                        return false;
                }
                map |= bit;
@@ -75,9 +76,9 @@ static int valid_typespec(struct cdecl_declspec *s)
                return true;
 
        if (map == 0)
-               cdecl__err(CDECL_EBADTYPE, _("no type specified"));
+               cdecl__errmsg(CDECL__ENOTYPE);
        else
-               cdecl__err(CDECL_EBADTYPE, _("invalid type specified"));
+               cdecl__errmsg(CDECL__EBADTYPE);
 
        return false;
 }
@@ -103,23 +104,23 @@ static bool valid_declspecs(struct cdecl *decl, bool top)
                        if (c->type == CDECL_TYPE_VOID &&
                            (d->type == CDECL_DECL_IDENT
                             || d->type == CDECL_DECL_ARRAY)) {
-                               cdecl__err(CDECL_EBADTYPE, _("invalid declaration of type void"));
+                               cdecl__errmsg(CDECL__EBADVOID);
                                return false;
                        }
                        continue;
                case CDECL_SPEC_STOR:
                        if (top && abstract) {
-                               cdecl__err(CDECL_EBADSTOR, _("type names cannot have storage-class specifiers"));
+                               cdecl__errmsg(CDECL__ETYPESTOR);
                                return false;
                        }
 
                        if (!top && c->type != CDECL_STOR_REGISTER) {
-                               cdecl__err(CDECL_EBADSTOR, _("function parameters may only have register storage"));
+                               cdecl__errmsg(CDECL__EFUNCSTOR);
                                return false;
                        }
 
                        if (++num_storage > 1) {
-                               cdecl__err(CDECL_EBADSTOR, _("too many storage-class specifiers"));
+                               cdecl__errmsg(CDECL__EMANYSTOR);
                                return false;
                        }
                        break;
@@ -129,20 +130,16 @@ static bool valid_declspecs(struct cdecl *decl, bool top)
                         * pointer qualifier list, which isn't checked here.
                         */
                        if (c->type == CDECL_QUAL_RESTRICT) {
-                               cdecl__err(CDECL_EBADQUAL, _("only pointer types can be restrict-qualified"));
+                               cdecl__errmsg(CDECL__EBADQUAL);
                                return false;
                        }
                        break;
                case CDECL_SPEC_FUNC:
-                       if (abstract) {
-                               cdecl__err(CDECL_ENOTFUNC, _("type names cannot have function specifiers"));
+                       if (abstract || !top || d->type != CDECL_DECL_FUNCTION) {
+                               cdecl__errmsg(CDECL__ENOTFUNC);
                                return false;
                        }
 
-                       if (!top || d->type != CDECL_DECL_FUNCTION) {
-                               cdecl__err(CDECL_ENOTFUNC, _("only function declarations can have function specifiers"));
-                               return false;
-                       }
                        break;
                default:
                        assert(0);
@@ -280,7 +277,7 @@ reduce_parentheses(struct cdecl_declarator **p, struct cdecl_declarator *d)
                }
 
                if (d->child->type != CDECL_DECL_NULL) {
-                       cdecl__err(CDECL_EBADPARAMS, _("invalid function parameter"));
+                       cdecl__errmsg(CDECL__EBADPARAM);
                        return -1;
                }
 
@@ -304,7 +301,7 @@ reduce_parentheses(struct cdecl_declarator **p, struct cdecl_declarator *d)
                if (decl->type == CDECL_DECL_FUNCTION
                    && decl->child->type == CDECL_DECL_NULL
                    && !function_is_reducible(decl)) {
-                       cdecl__err(CDECL_EBADPARAMS, _("too many parentheses in function"));
+                       cdecl__errmsg(CDECL__EMANYPAREN);
                        return -1;
                }
 
@@ -339,13 +336,13 @@ check_parameters(struct cdecl_declarator **p, struct cdecl_declarator *d)
                                continue;
 
                        if (spec != param->specifiers || spec->next != NULL) {
-                               cdecl__err(CDECL_EVOIDPARAM, _("void parameter cannot have extra specifiers"));
+                               cdecl__errmsg(CDECL__EVOIDPARAM);
                                return -1;
                        } else if (d->u.function.parameters->next) {
-                               cdecl__err(CDECL_EVOIDPARAM, _("void parameter must stand alone"));
+                               cdecl__errmsg(CDECL__EVOIDPARAM);
                                return -1;
                        } else if (d->u.function.variadic) {
-                               cdecl__err(CDECL_EVOIDPARAM, _("variadic function cannot have void parameter"));
+                               cdecl__errmsg(CDECL__EVOIDPARAM);
                                return -1;
                        }
                }
@@ -366,10 +363,10 @@ check_rettypes(struct cdecl_declarator **p, struct cdecl_declarator *d)
 
        switch (d->type) {
        case CDECL_DECL_FUNCTION:
-               cdecl__err(CDECL_EBADRETURN, _("functions cannot return functions"));
+               cdecl__errmsg(CDECL__ERETFUNC);
                return -1;
        case CDECL_DECL_ARRAY:
-               cdecl__err(CDECL_EBADRETURN, _("functions cannot return arrays"));
+               cdecl__errmsg(CDECL__ERETARRAY);
                return -1;
        }
 
@@ -384,7 +381,7 @@ check_arrays(struct cdecl_declarator **p, struct cdecl_declarator *d)
 
        switch (d->type) {
        case CDECL_DECL_FUNCTION:
-               cdecl__err(CDECL_EBADARRAY, _("array members cannot be functions"));
+               cdecl__errmsg(CDECL__EFUNCARRAY);
                return -1;
        }
 
@@ -425,7 +422,7 @@ check_qualifiers(struct cdecl_declarator **p, struct cdecl_declarator *d)
        for (spec = ptr->qualifiers; spec; spec = spec->next) {
                if (spec->type == CDECL_QUAL_RESTRICT
                    && d->type == CDECL_DECL_FUNCTION) {
-                       cdecl__err(CDECL_EBADPOINTER, _("function pointers cannot be restrict-qualified"));
+                       cdecl__errmsg(CDECL__ERESTRICTFUNC);
                        return -1;
                }
        }
@@ -494,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__err(CDECL_EBADDECL, _("mixing type names and declarations is not allowed"));
-                       goto err;
+                       cdecl__errmsg(CDECL__EDECLTYPE);
+                       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)