[comp.lang.c] ANSI grammar questions

chekmate@athena.mit.edu (Adam Kao) (11/13/88)

I've been playing around with the (presumably) most recent ANSI C grammar.
Right now I'm just building a parse tree, eventually I'll do interesting
things with the tree.  I've got a couple of questions.
First, about declaration specifiers:

declaration_specifiers
	: storage_class_specifier
	| storage_class_specifier declaration_specifiers
	| type_specifier
	| type_specifier declaration_specifiers
	| type_qualifier
	| type_qualifier declaration_specifiers
	;

So you can stack any number of storage_class_spec, type_spec, and type_qual
in front of your declaration, in any order?  Things like:

void static fn();

and

void static extern int auto volatile fn();

With my C, the first compiles, while the second won't compile and won't
pass lint (rightly so!).  But both slide through the grammar fine.  Why?
Why didn't ANSI do this:

declaration_specifiers
	: storage_class_specifier
	| storage_class_specifier type_specifier
	| storage_clase_specifier type_qualifier
	| storage_class_specifier type_specifier type_qualifier
	| type_specifier
	| type_specifier type_qualifier
	| type_qualifier
	;

Yes, I know, now you can't put them in any order, but who would write
"void static fn();" anyway?  And if it's that important, another eight
lines will do it.  I'm considering using this specification for my parser.
Technically I would then be parsing a subset of ANSI, but who cares?
Should I?

Second, I've never seen the ellipsis ("...") before.  (Guess it's time to
buy K&R 2nd ed.)  As far as I can tell, the only uses for it are:

void static fn(int c, ...);

or

void static a (n, fn)
     int n;
     void fn(int c, ...);
{
	:
	:

Are these in fact the intended uses?  Are there any other uses?
Unfortunately, my C rejects both of these with "parameters only legal in
function definition" and "syntax error".  (Guess it's time to buy a new C.)

Thanks mulchy,
Adam

"Wherever you grow, there you are."
	Buckaroo Bonsai

chekmate@athena.mit.edu (Adam Kao) (11/14/88)

I just realized it's common in C to have things like "unsigned short int",
which my modification doesn't parse.  (A jellybean for whoever guesses how
long I've been using C.)  Still, I can think of a couple ways to parse these
cases without being as lax as the current grammar.  Why isn't this grammar
more precise?  It would only have to be a little more complicated.

By the way, I'm using the 9nov87 draft grammar.
Adam

bill@twwells.uucp (T. William Wells) (11/16/88)

In article <7938@bloom-beacon.MIT.EDU> chekmate@athena.mit.edu (Adam Kao) writes:
: declaration_specifiers
:       : storage_class_specifier
:       | storage_class_specifier declaration_specifiers
:       | type_specifier
:       | type_specifier declaration_specifiers
:       | type_qualifier
:       | type_qualifier declaration_specifiers
:       ;
:
: So you can stack any number of storage_class_spec, type_spec, and type_qual
: in front of your declaration, in any order?  Things like:
:
: void static fn();
:
: and
:
: void static extern int auto volatile fn();

Right. This is intentional. Believe it or not, there are situations
where this flexibility is useful.

As is typical in C, there are lots of things that the language
permits you to do, that could be restricted with little harm to the
language's utility, and aren't.

This is consistent with C's bias toward trusting the programmer.
This also means that it is more obviously the programmer's
responsibility to carefully use the facilities that C provides.  (I
was originally going to say "This also makes it the programmer's
responsibility..." till it occured to me that some might interpret
that to mean that other languages don't impose that responsibility.
Utter nonsense, of course: some of the worst programs I have seen
were written in Modula 2 and followed all the "structured
programming" guidelines.)

: Yes, I know, now you can't put them in any order, but who would write
: "void static fn();" anyway?

I might. Though I never have, I can imagine circumstances where doing
it that way might be clearer than the other.

:                              And if it's that important, another eight
: lines will do it.  I'm considering using this specification for my parser.
: Technically I would then be parsing a subset of ANSI, but who cares?
: Should I?

There is also another factor you should consider: adding those lines
to your grammar (and, by extension, lots of other lines for similar
purposes), can make the resulting grammar tables *huge*. It just
isn't worth it.

Especially since, if you *must* do this, there is a better way: do it
with attributes passed up the parse tree.

: Second, I've never seen the ellipsis ("...") before.  (Guess it's time to
: buy K&R 2nd ed.)  As far as I can tell, the only uses for it are:
:
: void static fn(int c, ...);
:
: or
:
: void static a (n, fn)
:      int n;
:      void fn(int c, ...);
: {
:       :
:       :
:
: Are these in fact the intended uses?  Are there any other uses?

The ... can also be used in the prototype with the definition of the
function:

void static fn(int c, ...)
{
}

---

If you're going to write a C compiler, or a reasonable facsimile
thereof, make it a *real* C compiler; don't add your stylistic
preferences to it. If you do have style preferences that can be
detected syntactically, have your lint detect them, but make it
optional. You'll thank yourself the first time you have to deal with
someone else's code.

---
Bill
{uunet|novavax}!proxftl!twwells!bill

guy@auspex.UUCP (Guy Harris) (11/18/88)

>: void static extern int auto volatile fn();
>
>Right. This is intentional. Believe it or not, there are situations
>where this flexibility is useful.

And those cases that are truly *illegal*, such as the one cited above,
can still be caught by the compiler even though they pass the grammar. 

henry@utzoo.uucp (Henry Spencer) (11/18/88)

In article <179@twwells.uucp> bill@twwells.UUCP (T. William Wells) writes:
>: So you can stack any number of storage_class_spec, type_spec, and type_qual
>: in front of your declaration, in any order?  Things like:
>:
>: void static fn();
>
>Right. This is intentional. Believe it or not, there are situations
>where this flexibility is useful.

However, beware:  the "future directions" section of the draft standard
explicitly flags putting the storage class in the middle as "obsolescent",
and implies that it is likely to be made illegal in future revisions.
-- 
Sendmail is a bug,             |     Henry Spencer at U of Toronto Zoology
not a feature.                 | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

karl@haddock.ima.isc.com (Karl Heuer) (11/18/88)

In article <179@twwells.uucp> bill@twwells.uucp (T. William Wells) writes:
>In article <7938@bloom-beacon.MIT.EDU> chekmate@athena.mit.edu (Adam Kao) writes:
>>So you can stack any number of storage_class_spec, type_spec, and type_qual
>>in front of your declaration, in any order?  Things like:
>>	void static fn();
>>	void static extern int auto volatile fn();
>
>Right. This is intentional. Believe it or not, there are situations
>where this flexibility is useful.

As I'm sure we all realize, the second is *not* legal C (it names two
conflicting types, and three conflicting storage classes).  More precisely,
although it satisfies the syntax rules, it violates the constraint rules.

Less well known, but perhaps of interest to y'all, is that the first
construct, though still legal, is obsolescent.  Don't use it in new programs.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
Followups to comp.std.c.

bill@twwells.uucp (T. William Wells) (11/19/88)

In article <467@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
: >: void static extern int auto volatile fn();
: >
: >Right. This is intentional. Believe it or not, there are situations
: >where this flexibility is useful.
:
: And those cases that are truly *illegal*, such as the one cited above,
: can still be caught by the compiler even though they pass the grammar.

Whoops! I didn't carefully read the examples, supposing that they were
all of the kind expressing reordering of the type-specifier and
storage-class. This last example has more than one storage class and
more than one type-specifier, so is illegal.

As an aside, catching this kind of error in the grammar can really
make the grammar *huge*. This is why one does it outside the grammar.

---
Bill
{uunet|novavax}!proxftl!twwells!bill

chekmate@athena.mit.edu (Adam Kao) (11/20/88)

Many thanks to all who responded, on the net and through mail.  I am newly
enlightened as to the ways of committee and will endeavor to bear the
standard :-).  Yacc is good, C is good, syntax sucks but you can't 
win them all.

Adam