From 6cc6418811ac7b38fbe1ceed1de949d33439b51c Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Tue, 27 Jun 2023 22:48:11 -0400 Subject: [PATCH] libcdecl: Merge both parser function implementations. 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 | 88 ++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 48 deletions(-) diff --git a/src/parse-decl.c b/src/parse-decl.c index 7e181c0..b9685ff 100644 --- a/src/parse-decl.c +++ b/src/parse-decl.c @@ -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) -- 2.43.2