Why does a brace command group need spaces after the opening brace in POSIX Shell Grammar?

The difference between the curly braces and the parentheses are that the braces (and !) are reserved words, just like for, if, then etc. while parentheses are control operators. Words needs to be separated by whitespace.

This means that just like you can't have

foriin*; do

you can't have

{somecommand;} >file

or

if !somecommand; then

The spaces shown in the POSIX grammar are not spaces that needs to be there in the shell input data, but just a way of displaying the grammar itself. It is the fact that the braces are reserved words that implies that they have to be surrounded by whitespace, while the parentheses of a subshell don't.


That's a limitation of the way in which the shell breaks lines into tokens.

The shell reads lines from the input file and According to section 2 "Shell Introduction" converts them to either a word or an operator:

  1. The shell breaks the input into tokens: words and operators

{ is a reserved word

Some words are reserved words

Reserved words are words that have special meaning to the shell. The following words shall be recognized as reserved words:

! { } case do done elif else esac fi for if in then until while

Words, to be recognized as words, must be delimited.

Reserved words are recognized only when they are delimited ...

Mostly by blanks (point 7) and by operators.

  1. If the current character is an unquoted <blank>, any token containing the previous character is delimited and the current character shall be discarded.

( is an operator

Operators stand by themselves:

whereas operators are themselves delimiters.

Where "operators" are either:

3.260 Operator

In the shell command language, either a control operator or a redirection operator.

Redirection operators are:

Redirection Operator

In the shell command language, a token that performs a redirection function. It is one of the following symbols:

<     >     >|     <<     >>     <&     >&     <<-     <>

Control operators are:

3.113 Control Operator

In the shell command language, a token that performs a control function. It is one of the following symbols:

&   &&   (   )   ;   ;;   newline   |   ||

Conclusion

So, '(' and ')' are control operators while '{' '}' are reserved words.

And the exact same description of your question is inside the spec:

For instance, '(' and ')' are control operators, so that no <space> is needed in (list). However, '{' and '}' are reserved words in { list;}, so that in this case the leading <space> and <semicolon> are required.

Which exactly explains why an space (or some other delimiter) is required after a {.

This is valid:

{ echo yes;}

As is this:

{(echo yes);}

This:

{(echo yes)}

Or even this:

{>/dev/tty echo yes;}