[net.lang] if statement ambiguity and the C preprocessor

jse (09/22/82)

There is a problem with the kind of syntax used for if statements
in languages like C that is well known,
but nobody seems to complain about it too much.  
The problem is the ambiguity of which if an else belongs to.
The standard way of dealing with this is to say that an else
matches with the closest unmatched if.
	I always thought the better way of dealing with the problem
was to use if..then..[else]..fi instead.

Like many C programmers, I have grown quite used to this, and it
rarely causes any problems.  I like C in general, and I also
like not having to type fi.

The following situation is one in which it does bother me occasionally.
Suppose I want to define a macro which is an if statement without an else,
e.g.:

	#define mymacro	if (e1) s1

Now I want to use it somewhere, e.g.:

	if (e2)
		mymacro;
	else
		s2;

Well, this will not do what I probably wanted it to do,
namely associate the else with "if (e2)".
You might think that the solution is to try

	#define	mymacro	{ if (e1) s1; }

but that won't help either, because then the else won't be associated
with any if statement at all because of the semicolon before the else.

Questions: Is there some way to do this cleanly in C?
Why do languages continue to be designed with this syntactical
ambiguity?  Does it bother anyone else?  (To be fair, it doesn't
really bother me that much; I just don't try to use that construction).

	Jan Edler		pyuxll!jse	(btl piscataway)
				cmcl2!edler	(nyu)

ark (09/23/82)

If I say the following:

	#define mymacro { if (e1) s1; }

and now I write

	if (e2)
		mymacro
	else
		s1;

this expands into:

	if (e2)
		{ if (e1) s1; }
	else
		s1;

which is legal.  What exactly is the trouble?

dmr (09/23/82)

Jan Edler wondered how to define a macro in C that expands to an if statement,
and doesn't cause trouble when it appears amid if's and else's.
The cleanest way to handle the if ambiguity
(or at least to push the dirt under the smallest rug) is to define your
macro as follows

	#define mymacro	if (e1) s1; else

Then both the uses

	if (e2)
		mymacro;
	foo();

and

	if (e2)
		mymacro;
	else
		goo();
	foo();

get parsed correctly and the user doesn't have to remember that the macro
is special syntactically.

	Dennis Ritchie
	  (with thanks to Doug McIlroy)

edler (09/23/82)

Let me clarify.
The problem (a minor one perhaps) is that I don't want to have
to leave off the semicolon from the invokation of mymacro.
Consider:
	#define mymacro	{ if (e1) s1; }

	if (e2)
		mymacro;
	else
		s2;

This expands to:

	if (e2)
		{ if (e1) s1; };
	else
		s2;

which is syntacticly incorrect.

The only real significance of this is where you want to present
a package for others to use, and you claim that a macro is
a function, when in reality it is not.  As this example shows,
it cannot even be invoked as if it were a function, since
it would be necessary to include the semicolon if it were a real
function.

	Jan Edler		cmcl2!edler	(nyu)
				pyuxll!jse	(btl piscataway)

lepreau (09/23/82)

The dangling else problem arises cause the if gen'ed by the macro
might grab an adjacent else.  So give the macro a nearer one: stick
a null else clause on the end of it.
-Jay Lepreau