]> git.draconx.ca Git - cdecl99.git/commitdiff
Add an explanation for declaration specifier rules.
authorNick Bowler <nbowler@draconx.ca>
Tue, 18 Jul 2023 01:55:28 +0000 (21:55 -0400)
committerNick Bowler <nbowler@draconx.ca>
Tue, 18 Jul 2023 01:55:28 +0000 (21:55 -0400)
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

index e9df6cb62d9205272c358a6d767f88689d65c8b7..a386c086b9718abc413f515e5183008036ce3776 100644 (file)
@@ -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;