The syntax simply says:
unary-expression: [some parts are missing here]
sizeof unary-expression
sizeof ( type-name )
I.e. in the form that needs ( ) they are part of the unary-expression
and they go round a type-name. It is true that a cast-expression is:
cast-expression:
unary-expression
( type-name ) cast-expression
but that does not make the ( type-name ) in the first example a cast.
Thanks, you are right. The syntax could be
unary-expression
sizeof unary-expression
sizeof cast-expression
This would not work right, since then we would have to write, e.g.:
size_t size_of_an_int = sizeof (int) 0;
to get the size of the "int" type. (Note that a cast-expression
that includes a cast -- i.e., that is not simply a unary-expression
to begin with -- consists of a cast *followed by* another
cast-expression, so for the recursion to terminate, the last
cast-expression must consist of a unary-expression, such as the
integer constant 0 in my example.)
But I guess the standard doesn't like such definitions.
It would be possible to factor out the token-sequence "left
parenthesis, type-name, right-parenthesis" into a new nonterminal
such as "cast-prefix", giving:
unary-expr:
postfix-expr
++ unary-expr
-- unary-expr
unary-operator cast-expr
sizeof unary-expr
sizeof cast-prefix
cast-expr:
unary-expr
cast-prefix unary-expr
cast-prefix:
( type-name )
The "cast-prefix" nonterminal would be useful in describing the
syntax for C99's compound literals as well.
(One can also rewrite the entire thing as an operator precedence
grammar, removing the need for many interior nonterminals, but of
course that requires adding operator precedence to the grammar.

)