From 9bbe3b9dc114473daf68153769495e6a4a50b7de Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Mon, 17 Jul 2023 21:55:28 -0400 Subject: [PATCH] Add an explanation for declaration specifier rules. It took me a while to wrap my head around WTF the declaration specifier parser rules were trying to accomplish. Let's add a big explanation so hopefully, if I try to read them again after another decade or so, they will make sense more easily. --- src/parse.y | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/parse.y b/src/parse.y index e9df6cb..a386c08 100644 --- a/src/parse.y +++ b/src/parse.y @@ -259,6 +259,22 @@ declaration: declspecs declarators semi { i->specifiers = $1; }; +/* + * We support parsing declarations using arbitrary identifiers as type + * specifiers (a la C typedef). To avoid confusion with identifiers that + * may also be used as declarators, note the following: + * + * (a) Every valid C declaration must have at least one type specifier, and + * (b) Valid declarations with typedef names have exactly one type specifier. + * + * So the rule applied when parsing specifiers is: an identifier is a type + * specifier only if we have not yet seen any type specifiers whatsoever + * (within one declaration specifier list). + * + * Treating identifiers as type specifiers by default can lead to strange and + * unexpected parses; libcdecl applies a simplification step to the resulting + * parse tree afterwards. + */ declspecs: declspec_notype declspecs { $$ = $1; $$->next = $2; -- 2.43.2