Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Bug in case stmt with '('



Greetings:--

I don't have the time to examine how zsh's lex.c and parse.c work,
so I can't comment technically on Bart Schaefer and Zoltan Hidvegi's
respective patches.  However, the thought occurred to me that the
lexer and/or parser might be simplified if we revise our outlook on
the case-statement grammar.  Instead of the syntax of each case-
clause's prefix being

{A}	[(] pat-1 | ... | pat-n )

(which requires the troublesome analysis of deciding whether an
initial '(' is the optional '(' of the case-clause syntax or simply
a glob-type '(' belonging to pat-1 proper), why not extend the syntax
to be

{B1}	pat-1 | ... | pat-n [)]

?  Thus (presuming that normal zsh globbing is in effect), an
initial '(' would _always_ be a glob-type parenthesis (making
the entire case-clause prefix into one big grouped pat-1 that
is not followed by the optional trailing ')').

This should not break existing code, since currently a trailing
')' is always required.  Moreover, sh, ksh, and zsh all disallow
blanks in any pat-i, as the following console listing demonstrates,
so there is no valid case-clause (of the form, say, 'a b) c;;')
such that omitting the ')' would result in an ambiguous or misparsed
case-clause (such as 'a b c;;').

If one were reluctant to depart so far from traditional case-statement 
syntax as {B1} does, one could make the trailing ')' optional only
when pat-n itself ends in ')', and to stay even more compatible with
POSIX syntax, additionally require that n = 1.  However, zsh already has
so many extensions that I don't seem the harm in letting the trailing
')' always be optional:  each pat-i would be unambiguously terminated by
(possibly optional whitespace preceding) '|', ')', or the first token
of the case-clause body (which cannot be '|' or ')' in any case).

The above all presumes that '(' is a globbing character, which is
normally so.  If it isn't (such as when the NO_GLOB [or SH_GLOB ?]
option is in effect), then {B1}, although still necessary, is
insufficient, and must obviously be supplemented with the alternative

{B2}	( pat-1 | ... | pat-n )

.  In this case, the ')' is mandatory:  traditional case-clause syntax
requires us to tolerate an unmatched trailing ')', but there is no
reason to allow an unmatched leading '('.

The only remaining issue is how to describe case-prefix syntax in 
the zshmisc man pages.  It is unnecessary to mention the
implementation detail that when '(' is a globbing character,
the lexer or parser treats {B2} as a special case of {B1}.
To be rigorous, one could state that the case-prefix syntax 
is {B1} | {B2}.  However, this is somewhat tedious, and instead
it might be preferable to present the syntax simply as

{C}	[(] pat-1 | ... | pat-n [)]

and mention in the accompanying English-language text that if the
leading '(' is supplied then the trailing ')' is required as well.
__________________________________

By the way, my previous posting shows that with the buggy behavior
of zsh-3.0-pre{1,3}, when executing ". case3let.ksh", the interpreter
erroneously falls through to the next case-clause instead of exiting
the entire case-statement (see lines 68-75 of that posting's console
listing).  In addition, when executing "zsh case3let.ksh", version
3.0-pre3 (but not -pre1) gets a segmentation fault (see lines 62-67).
These would seem to be problems aside from the incorrect parsing
of the case-clause prefix.

-- Morrie Siegel
__________________________________

$(0) 13:08:37 {5} head case[45]sp.ksh
==> case4sp.ksh <==
case 'a z' in
#a z )	echo 'a z )' ;;
a\ z )	echo 'a\\ z )' ;;
a[ ]z )	echo 'a[ ]z )' ;;
a* )	echo 'a* )' ;;
* )	echo '* )' ;;
esac
==> case5sp.ksh <==
case 'a z' in
a z )	echo 'a z )' ;;
a\ z )	echo 'a\\ z )' ;;
a[ ]z )	echo 'a[ ]z )' ;;
a* )	echo 'a* )' ;;
* )	echo '* )' ;;
esac
$(0) 13:08:53 {6} /bin/sh case4sp.ksh
case4sp.ksh: syntax error at line 4: `]z' unexpected
zsh: 17070 exit 2     /bin/sh case4sp.ksh
$(2) 13:09:15 {7} r 4=5
/bin/sh case5sp.ksh
case5sp.ksh: syntax error at line 2: `z' unexpected
zsh: 17071 exit 2     /bin/sh case5sp.ksh
$(2) 13:09:22 {8} /bin/ksh case4sp.ksh
case4sp.ksh: syntax error at line 4 : `]z' unexpected
zsh: 17072 exit 2     /bin/ksh case4sp.ksh
$(2) 13:09:36 {9} r 4=5
/bin/ksh case5sp.ksh
case5sp.ksh: syntax error at line 2 : `z' unexpected
zsh: 17074 exit 2     /bin/ksh case5sp.ksh
$(2) 13:09:42 {10} zsh3p1 case4sp.ksh
case4sp.ksh: parse error near `]z' [4]
case4sp.ksh: parse error near `)' [5]
case4sp.ksh: parse error near `)' [6]
case4sp.ksh: parse error near `esac' [7]
$(0) 13:10:08 {11} r 4=5
zsh3p1 case5sp.ksh
case5sp.ksh: parse error near `z' [2]
case5sp.ksh: parse error near `)' [3]
case5sp.ksh: parse error near `)' [4]
case5sp.ksh: parse error near `)' [5]
case5sp.ksh: parse error near `)' [6]
case5sp.ksh: parse error near `esac' [7]
$(0) 13:10:44 {12} exit
__________________________________



Messages sorted by: Reverse Date, Date, Thread, Author