The parser has two rules which join two lists. Let's add a helper
to do that instead of duplicating the code for list concatenation.
Furthermore, in both cases one of the lists is known to be nonempty;
the implementation can be slightly simplified with that assumption.
+
+/*
+ * Join two declaration specifier lists into a single list, with "a" being the
+ * head of the new list.
+ *
+ * The list "a" is assumed to be nonempty.
+ */
+static void join_specs(struct cdecl_declspec *a, struct cdecl_declspec *b)
+{
+ while (a->next)
+ a = a->next;
+ a->next = b;
+}
%}
%destructor { free($$); } <strval>
%}
%destructor { free($$); } <strval>
* together three different specifiers lists.
*/
post_specs: qualifiers typespec type_qual_specs {
* together three different specifiers lists.
*/
post_specs: qualifiers typespec type_qual_specs {
+ $2->next = $3;
+ join_specs($2, $1);
- $$->next = $1;
- for (struct cdecl_declspec *s = $$; s; s = s->next) {
- if (!s->next) {
- s->next = $3;
- break;
- }
- }
}
english_declaration: storage_func_specs english_declarator post_specs {
}
english_declaration: storage_func_specs english_declarator post_specs {
ALLOC_STRUCT($$, struct cdecl,
.specifiers = $3,
.declarators = $2);
ALLOC_STRUCT($$, struct cdecl,
.specifiers = $3,
.declarators = $2);
-
- for (struct cdecl_declspec *s = $$->specifiers; s; s = s->next) {
- if (!s->next) {
- s->next = $1;
- break;
- }
- }