declaration/expression

Ellery Newcomer ellery-newcomer at utulsa.edu
Tue Jun 23 17:35:13 PDT 2009


Jarrett Billingsley wrote:
> On Tue, Jun 23, 2009 at 1:00 AM, Ellery
> Newcomer<ellery-newcomer at utulsa.edu> wrote:
>> Sorry for not posting this in learn, but I'd also like to hear the
>> Language Designer's input on this one.
>>
>> How does dmd resolve the declaration/expression ambiguity?
>>
>> My first instinct would be to try the declaration, and if it doesn't
>> work because the type doesn't exist or something like that then try the
>> expression, or vice versa. But that could easily lead to undefined and
>> unexpected behavior. what if both are valid?
> 
> You're right; if a statement begins with an identifier, the compiler
> requires arbitrary lookahead to determine whether it's looking at an
> expression or a declaration.  There's a good bit of duplicated code in
> DMD dedicated to parsing declarations.  IIRC there's one version of
> the parsing that just returns whether or not it's "probably" a
> declaration, and another version that does the exact same thing but
> which actually builds the AST.  Kind of icky.

Heh. I saw that. I also saw a toExpression function in various
declaration structs. Didn't look deeply into it though.
> 
> But that being said, I don't think there are actually any ambiguities
> in the grammar when it comes to this.  Neither of the "problem" lines
> in your example code could possibly be interpreted as declarations,
> and I don't think I can come up with any actually ambiguous code.

Wrong. Both are perfectly valid declarations (and did you miss my note?
the compiler *IS* interpreting the second as a declaration).
Okay, consider the rule declarator, which is (or should, if the grammar
wants to correctly reflect what the compiler is doing) defined like so

Declarator:
      BasicType2opt Identifier DeclaratorSuffixesopt
      BasicType2opt ( Declarator ) DeclaratorSuffixesopt

This is what allows D to accept C-style (forgot about those, didn't ya?)
declarations, and it's mostly what I'm referring to. Watch:

int(i); //compiles exactly the same as 'int i;'
int(*i)(int[]); //compiles the same as 'int function(int[]) i;'

So when I give something like

T(t);
t(*i)(i[]); //changed it a little, since 'int (i[])(int[])'
//            is semantically invalid

I intend a declaration and an expression. I get the opposite.
Fortunately, neither compiles, due to semantic errors.

To restate my question, if I'm a parser and I see

Identifier ( Identifier ) ;

which do I interpret it as?

Type ( NewSymbol ) ;
FunctionName ( Argument ) ;

If I see

Identifier . Identifier ( * Identifier ) ;

what do I resolve it as?

And it just goes downhill from there.



More information about the Digitalmars-d mailing list