Thread overview
Documented Grammar mistakes?
Oct 21, 2005
Walter Bright
October 12, 2005
I have been looking at the documented grammar recently, and I noticed a few things that look like they may be typos.

One is that PrimaryExpression has a rule for StringLiteral, which is defined as:

StringLiteral:
   WysiwygString
   AlternateWysiwygString
   DoubleQuotedString
   EscapeSequence
   HexString

I may be wrong, but it seems that PrimaryExpression should use something like StringLiterals, e.g.:

StringLiterals:
   StringLiteral
   StringLiterals StringLiteral

Since the following compiles:

printf("test" `test` r"" \n);

Lower down, should SliceExpression is defined as:

SliceExpression:
   PostfixExpression [ AssignExpression .. AssignExpression ]

Which does not seem to allow for "variable[]" - and that is also a valid (unless I'm confused) slice expression, right?

Just above that, PostfixExpression has this rule:

PostfixExpression ( ArgumentList )

But does not also have:

PostfixExpression ( )

Which would seem necessary unless ArgumentList is meant to have a "nothing" rule.

NewExpression, duplicated below, also seems to suffer from a few problems.  First I'll copy it over:

NewExpression:
   new BasicType Stars [ AssignExpression ] Declarator
   new BasicType Stars ( ArgumentList )
   new BasicType Stars
   new ( ArgumentList ) BasicType Stars [ AssignExpression ] Declarator
   new ( ArgumentList ) BasicType Stars ( ArgumentList )
   new ( ArgumentList ) BasicType Stars

The first problem is the pesky "Declarators" there.  I really think that's a typo, or I'm completely missing something.  Quite likely both.

Also somewhat trivial is those ArgumentLists again: unless it's meant to be nothing, it seems additional rules are necessary for each of the permutations where ArgumentList isn't there.  Likely something like this would simplify things:

NewArguments:
   new ( ArgumentList )
   new ( )
   new

Less trivial is that while BasicType Stars seems dandy, many other valid forms seem to exist, like:

int*[]*[] test = new int*[]*[0];
int*[1]*[] test = new int*[1]*[0];
int*[]** test = new int*[]*;

If I understand right, the last [] pair must contain a valid expression, and then stars.

And, while doing that, I found that dmd accepts:

C** c = new C*(1);

Which (afaict) does nothing, and C doesn't even have a constructor that takes an int.  But maybe this is valid, and I don't understand why...?

FunctionLiterals also have a few ( ParameterList ) without having empty parens allowed.

On the Declarations page, you'll see:

Decl:
   StorageClass Decl
   BasicType Declarators ;
   BasicType Declarator FunctionBody

That seems ambiguous to me, since all of the storage classes seem to also be attributes, so you get Declaration vs. Attribute DeclDefBlock (where DeclDefBlock can be a DeclDef, and hence a Declaration.)  But I'm new to grammars, so forgive me if I show that with the above comments.

BasicType2 and DeclaratorSuffix also miss parameter-less rules.

ParameterList, which is defined as:

ParameterList:
   Parameter
   Parameter , ParameterList
   ...

Is missing a rule for the new typesafe form, that is:

   Parameter ...

Then, referenced on that page are ArrayInitializer and StructInitializer, neither of which seem to be defined on any page.  I believe they should be:

ArrayInitializer:
   [ ArrayMemberInitializations ]
   [ ]

ArrayMemberInitializations:
   ArrayMemberInitialization
   ArrayMemberInitialization ,
   ArrayMemberInitialization , ArrayMemberInitializations

ArrayMemberInitialization:
   AssignExpression
   AssignExpression : AssignExpression

StructInitializer:
   { }
   { StructMemberInitializers }

StructMemberInitializers:
   StructMemberInitializer
   StructMemberInitializer ,
   StructMemberInitializer , StructMemberInitializers

StructMemberInitializer:
   AssignExpression
   Identifier : AssignExpression

Which *seems* to be what the compiler supports.

This is getting pretty long, so I'll just name two others...

AttributeElseSpecifier: where is this used?

EnumMember should use AssignExpression instead of Expression, since EnumMembers allows for commas.

Anyway, again as said above, I'm no expert on compilers or language grammars, so if I'm completely off base, just tell me.

Thanks,
-[Unknown]
October 13, 2005
Additionally, contracts seem to be entirely missing in the grammar, as is FunctionBody.  I believe the missing rules are or could be:

FunctionBody:
   BlockStatement
   ContractStatement

ContractStatement:
   BodyStatement
   InStatement BodyStatement
   OutStatement BodyStatement
   InStatement OutStatement BodyStatement
   OutStatement InStatement BodyStatement

InStatement:
   in BlockStatement

OutStatement:
   out BlockStatement
   out ( Identifier ) BlockStatement

BodyStatement:
   body BlockStatement

Where ContractStatement could be added to Statement's rules (when supported, I suppose.)  This is assuming a lone body statement would be allowed, which is the current behavior.

Following from this, all of the grammar on the class.html page is wrong.  For example, this:

Constructor:
   this ( ParameterList ) BlockStatement

Should be:

Constructor:
   this ( ParameterList ) FunctionBody

Or, at least I presume so.  This happens many times, for Constructor, Destructor, StaticConstructor, StaticDestructor, ClassInvariant, UnitTest, ClassAllocator, and ClassDeallocator.  In other words, every BlockStatement on that page.

In module.html, DeclDef uses "Unittest" instead of "UnitTest" which is (I think) the correct spelling - or, at least, one of them is.

StructAllocator and StructDeallocator are also missing from struct.html.  I imagine they're the same as the ClassAllocator and ClassDeallocator, respectively.

From what I was messing with, ConditionalDeclaration isn't very friendly with AttributeSpecifier, because of Attribute DeclDefBlock (much like the problem with StorageClasses.)  This is only the case when AttributeElseSpecifier is added alongside AttributeSpecifier (which isn't how it is, as current, of course.)

That's all I've run across so far (or at least, all I can recall now.)

-[Unknown]
October 21, 2005
"Unknown W. Brackets" <unknown@simplemachines.org> wrote in message news:dii53h$i5n$1@digitaldaemon.com...

Thanks for all these corrections.

> And, while doing that, I found that dmd accepts:
>
> C** c = new C*(1);
>
> Which (afaict) does nothing, and C doesn't even have a constructor that takes an int.  But maybe this is valid, and I don't understand why...?

It's a bug, and will no longer be accepted <g>.