Hi,

compiling this little code snippet

void main()
{
        int x = 1;
        int a = x++ ^^ 2; // ok
        int b = ++x ^^ 2; // error
        int c = -x ^^ 2;
}

dmd 2.053 produces this rather unexpected message:
testpow.d(6): Error: int __powtmp4 = x;
 , __powtmp4 * __powtmp4 is not an lvalue

Leaving the quality of the error message aside, why is it failing in the first place? Similar errors happen with unary *,~ and other operators.
This is caused by the way PowExpression is inserted into the grammar:

MulExpression:
        UnaryExpression
        MulExpression * UnaryExpression
        ... // more operators /,%

UnaryExpression:
        PowExpression
        ++ UnaryExpression
        -- UnaryExpression
        * UnaryExpression
        - UnaryExpression
... // some more rules recursing on UnaryExpression including +,&,!,~,delete,cast

PowExpression:
        PostfixExpression
        PostfixExpression ^^ UnaryExpression

PostfixExpression:
        PrimaryExpression
        PostfixExpression ++
        PostfixExpression --
        ... // some more rules
        
Which essentially means that the ^^ binds stronger than prefix increment, but not as strong as the postfix increment. So, "++x ^^ 2" is parsed as "++(x ^^ 2)" causing the error later. This was introduced to let "-x ^^ 2" in the example above yield negative results.

I think the desired way is that ^^ should only have higher precedence than the sign operators, but lower precedence than any of the other UnaryExpression operators. The best way I could find to express this in the grammar is

MulExpression:
        SignExpression
        MulExpression * SignExpression
        ... // more operators /,%

SignExpression:
        PowExpression
        + SignExpression
        - SignExpression

PowExpression:
        UnaryExpression2
        UnaryExpression2 ^^ SignExpression

UnaryExpression:
        UnaryExpression2
        + SignExpression
        - SignExpression
        
UnaryExpression2:
        PostfixExpression
        ++ UnaryExpression
        -- UnaryExpression
        * UnaryExpression
... // some more rules including &,!,~,delete,cast should recurse on UnaryExpression

I even dare to say that "- a * b" should also be parsed as "- (a * b)" to be mathematically correct, but that would break compatibility with the way it is done in C/C++ (I tried 3 different compilers, it was always parsed as "(-a) * b"). It might also only make a difference in case of abused operator overloading.

I'm not so sure whether ! and ~ belong to the same group of operators as + and - and should also be added to SignExpression.

What do you think?

Rainer

Reply via email to