[comp.sources.d] possible operator precedence bug?

jfh@rpp386.Dallas.TX.US (The Beach Bum) (10/07/88)

In article <751@mcrware.UUCP> jejones@mcrware.UUCP (James Jones) writes:
>A recently-posted C program that generates random mazes gives me cause to
>wonder about C operator precedence.
>
>I include the source here for reference--it's very short:

[ and I un - >'d it so I could throw some stuff at it ... ]

char*M,A,Z,E=40,J[40],T[40];main(C){for(*J=A=scanf(M="%d",&C);
--            E;             J[              E]             =T
[E   ]=  E)   printf("._");  for(;(A-=Z=!Z)  ||  (printf("\n|"
)    ,   A    =              39              ,C             --
)    ;   Z    ||    printf   (M   ))M[Z]=Z[A-(E   =A[J-Z])&&!C
&    A   ==             T[                                  A]     
|6<<27<rand()||!C&!Z?J[T[E]=T[A]]=E,J[T[A]=A-Z]=A,"_.":" |"];}


>The inner loop of this program contains an expression, which, as far as
>I can tell after feeding through cb, has the form
>
>	M[Z]=Z[<hairy expression> ? <expression>, <expression>, "_." : " |"];

This is the fully parenthised expression, as reported by "cparen".  Every
one should have this sucker - just after having "cdecl".

(M[Z])=
	(Z[(((A-(E=(A[J-Z])))&&(((!C)&(A==(T[A])))|((6<<27)<(rand()))))||
((!C)&(!Z)))?
	((((J[(T[E])=(T[A])])=E),((J[(T[A])=(A-Z)])=A)),"_.") :
	"|"])

>The question is this: why does this make it through the compiler at all?
>K&R says that the comma operator has the lowest priority, so shouldn't
>the following be required for the code to correctly parse?
>	M[Z]=Z[<hairy expression> ? (<expression>, <expression>, "_.") : " |"];
>	                            ^                                ^

No, as you can see above, the grammar groups the expression in the "correct"
fashion without the explicit parentheses.

Here is a snip from a YACC grammar which conforms to the 11/9/87 ANSI Draft.

conditional_expr
	: logical_or_expr
	| logical_or_expr '?' expr ':' conditional_expr
	;

assignment_expr
	: conditional_expr
	| unary_expr assignment_operator assignment_expr
	;

expr
	: assignment_expr
	| expr ',' assignment_expr
	;

As we see, conditional_expr is of a higher precedence, but the first
expression is an <expr>.  So, we luck out.  Watch this:

	a ? b : c , d , e

becomes

	((a ? b : c) , d) , e

Notice that you now get the behaviour you expected - ',' is of a
lower precendence and the left hand side groups to reflect this.
But the code of the form

	a ? b , c , d : e

becomes

	a ? ((b , c) , d) : e

because the grammar specifies the left hand side of ":" as a full-blown
expression.  Which implies that ? :'s nest the same way as if-then-elses
do.  Watch -

	a ?  b ? c : d : e	and
	v ?  w : x ? y : z

becomes [ you should be able to guess this one ;-) ]

	a ?  (b ? c : d) : e	and
	v ?  w : (x ? y : z)

10 points if you got it correct ...
-- 
John F. Haugh II (jfh@rpp386.Dallas.TX.US)                   HASA, "S" Division

      "Why waste negative entropy on comments, when you could use the same
                   entropy to create bugs instead?" -- Steve Elias