Bart Schaefer wrote:
> misleading. The /bin/sh manual can get away with `while LIST do LIST done'
> because in /bin/sh the semicolon or newline at the end of a LIST is never
> optional (the definition of LIST *includes* the trailing separator in the
> /bin/sh manuals).
Then the /bin/sh manual is wrong. if (true) then (echo foo) fi works fine
in sh. Of course any corrections to the manual are welcome. The manual
now contains a more or less full formal description of the grammar, but I
agree, that it may be hard to interpret it correctly. In general, it is
not easy to describe the exact grammar of the shell in such a way that it
is easy to understand for the human readers. Note that ksh has the same
problems here as zsh. In sh/ksh the question is when is it possible to
omit the semicolon/newline before `then'. In zsh the brace syntax
complicates this a bit, but it is really the same problem. If the
newline/semicolon can be omitted in a while LIST do statement then the
while LIST { ... } syntax will work as well.
> > Zsh has to know that { is not a simple argument
> > to a command, but a reserved word.
>
> That's not a sufficient explanation either! It has to be not just a
> reserved word, but a reserved word in a spot where that particular word
> doesn't have an alternate meaning -- which means after )) or ]] or ) or },
> but NOT after semicolon or newline. Which is *not the same* as the rule
> for where `do' can appear, which IMHO should mean that the syntax summary
> should NOT be written `while LIST { LIST }'.
If you interpret LIST as the longest string which is synactically a list
than it is correct. In while true ; { echo foo } the longest possible list
is true ; { echo foo }. Zsh just parses the list as long as it can, and
when the list parses sees something that cannot continue a list it returns.
>
> The doc could define a CLOSED construct to be any of (( )) [[ ]] ( ) { },
> and define a CLOSEDLIST to be a LIST ending with a CLOSED but that is NOT
> followed by the optional separator. Then it could say:
>
> `if CLOSEDLIST { LIST } [ elif CLOSEDLIST { LIST } ] ... [ else { LIST } ]'
> `if CLOSEDLIST SUBLIST'
> `while CLOSEDLIST { LIST }'
> `until CLOSEDLIST { LIST }'
>
> And then I'd be happy.
Yes, but that would make the manual quite verbose repeating the same thing
many times.
> > The { echo } case works and seems to be
> > an exception to this rule but is really a pathologic special case handled
> > explicitely in lex.c and it only works if ignorebraces is not set.
>
> I don't know what you're talking about here at all, I fear. An exception
> to which rule? `}' is recognized *everywhere* when ignorebraces is not
} is a reserved word, and it should be recognized only in command position.
But it is recognized in other places as well.
> set. Which seems bizarre to me anyway -- if `{' is not recognized every-
> where, then `}' ought to be recognized only when an unmatched reserved `{'
> has preceded it. One more state flag in the lexer could fix that.
{ cannot mean command grouping in echo { ... } just line echo ( ... ) does
not do that. The later is a syntax error in sh. And I think it would be
even more confusing if echo } works but it stops working after you put it
into a while loop using { ... }.
Zoltan