On Sun, 2005-12-11 at 22:54 +1100, Manuel M T Chakravarty wrote:
> Duncan Coutts:
> > On Fri, 2005-12-09 at 11:23 +0000, Duncan Coutts wrote:
> >
> > > However the change to the grammar to make this possible is non-trivial.
> > >
> > > The grammar I was working from originally makes the same mistake.
> > > http://www.lysator.liu.se/c/ANSI-C-grammar-y.html> > >
> > > The gcc grammar has a very complex way of partitioning the typedef and
> > > non-typedef cases to allow a typedefed name to be reused as an
> > > identifier in the right context.
> > >
> > > I'm still looking into it.
> >
> > I've spent quite some time trying to fix this using the gcc grammar as a
> > guide however I can't make a grammar that is free of reduce/reduce
> > conflicts.
>> What did you try to do? Adding a new case to the direct_declarator
> definition that parses a `typedef' instead of an `ident'?
That leads to 7 extra shift/reduce conflicts.
The reason for the extra conflicts is that in allowing tyidents we are
actually making the grammar too general. We should only allow tyidents
in a direct_declarator if we have not already seen a type specifier
earlier in the declaration.
The gcc grammar has a note about it's "typed_declspecs" production:
/* Declspecs which contain at least one type specifier or typedef name.
(Just `const' or `volatile' is not enough.)
A typedef'd name following these is taken as a name to be declared. */
It then partitions the grammar so we can have a decl that has a type
specifier name at the beginning (typed_declspecs) followed by initdecls
that may not contain a typedef name. Or it can have a decl that does not
contain a type specifer followed by initdecls which may not contain a
typedef name (notype_initdecls):
decl:
typed_declspecs setspecs initdecls ';'
| declmods setspecs notype_initdecls ';'
typed_declspecs:
typespec reserved_declspecs
| declmods typespec reserved_declspecs
Then after this each production comes in two forms:
initdecls:
initdcl
| initdecls ',' initdcl
notype_initdecls:
notype_initdcl
| notype_initdecls ',' initdcl
initdcl:
declarator '=' init
| declarator
notype_initdcl:
notype_declarator '=' init
| notype_declarator
An ordinary declarator can have either typedef names or non-typedef
names, but the notype_initdcl can only have non-typedef names.
declarator:
after_type_declarator
| notype_declarator
after_type_declarator:
...
| TYPENAME
notype_declarator:
...
| IDENTIFIER
I've tried to use this technique but the details are tricky to follow
and all my attempts so far end up with reduce/reduce ambiguities in the
grammar.
Duncan