Reason for strange ExponentiationExpression & UpdateExpression productions?

# Bradford Smith (8 years ago)

Can anyone explain the reasoning behind the strange "leapfrogging" behavior of the ExponentiationExpression tc39.github.io/ecma262/#prod-ExponentiationExpression and

UpdateExpression tc39.github.io/ecma262/#prod-UpdateExpression productions

in the current spec?

Simplified relevant productions in operator precedence order are:

ExponentiationExpression : UnaryExpression UpdateExpression ** ExponentiationExpression

UnaryExpression : UpdateExpression { delete | void | typeof | + | - | ~ | ! } UnaryExpression

UpdateExpression: { ++ | -- } UnaryExpression LeftHandSideExpression { ++ | -- }

Things that seem weird about this are:

  1. '-x ** y' is a syntax error, because UnaryExpression isn't allowed before ** You must write it as '(-x) ** y' I would expect the production right hand side to be UnaryExpression ** ExponentiationExpression That avoids this strange syntax error and is consistent with the pattern followed by productions for lower-precedence operators.

  2. Having UnaryExpression in the right hand side of UpdateExpression confuses precedence by going 'backward' to a lower-precedence non-terminal, and the only production of UnaryExpression that generates a valid argument for '++'/'--' is UnaryExpression => UpdateExpression =>

LeftHandSideExpression anyway.

I've just finished implementing these rules in the closure-compiler, where I had to implement logic to deal with this strange behavior. Is it at all possible that these are simply typos in the spec?

Thanks, Bradford

# Jordan Harband (8 years ago)

-x ** y is absolutely a SyntaxError because of the disagreement between many programming languages which treat that as (-x) ** y and math itself which treats it as -(x ** y).

To resolve the debate about "what will users expect", this early syntax error ensures that programmers get the joy of being required to be explicit about their precedence, saving countless amounts of time and money spent on linting rules and style arguments.

# Kevin Smith (8 years ago)

It's pretty weird.

# Bradford Smith (8 years ago)

Thanks for the quick response, Jordan. That does make sense for my question .#1.

Re #2, does anybody know why UpdateExpression loops back up to UnaryExpression?

Also, are the reasons for the decisions made when updating the spec documented anywhere? If so, maybe I could find the answer to questions like these myself in future.

Thanks, Bradford

# Jordan Harband (8 years ago)
# Bradford Smith (8 years ago)

Thanks! I'll know to look there in future. rwalden takes good notes.

No luck finding an answer to my question #2 though. Searches tried: ++ increment decrement unary UpdateExpression

# Rick Waldron (8 years ago)

Bradford,

Take a look at the tests that I wrote for that syntax, I think they will be helpful in understand what that syntax actually is: tc39/test262/blob/master/test/language/expressions/exponentiation/exp-operator-precedence-unary-expression-semantics.js#L34

# Bradford Smith (8 years ago)

Thanks! That does make behavior of ** in combination with unary operators very clear. I've made note of that repo for future reference.

A brief search didn't turn up any test cases that would enlighten me regarding why the rules for UpdateExpression are:

UpdateExpression : { ++ | -- } UnaryExpression LeftHandSideExpression { ++ | -- }

You can't increment or decrement anything that isn't a LeftHandSideExpression, so why does the syntax rule allow UnaryExpression as an argument for update in the prefix case?

Not a critical question, but I am very curious.

Thanks, Bradford

# Allen Wirfs-Brock (8 years ago)

On Jul 22, 2016, at 10:04 AM, Bradford Smith <bradfordcsmith at google.com> wrote:

A brief search didn't turn up any test cases that would enlighten me regarding why the rules for UpdateExpression are:

UpdateExpression : { ++ | -- } UnaryExpression LeftHandSideExpression { ++ | -- }

You can't increment or decrement anything that isn't a LeftHandSideExpression, so why does the syntax rule allow UnaryExpression as an argument for update in the prefix case?

It’s basically preserve legal syntax that extends all the way back to the ES1 specification: ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262, 1st edition, June 1997.pdf, ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262, 1st edition, June 1997.pdf

that syntax means that something like:

if (false) ++ -42;

Is syntactically valid. A program containing such a line will load and execute without error.

Changing the grammar (or static semantics rules) to make that illegal would be a ”breaking change” that might cause some valid existing scripts to suddenly fail to load.

# Bradford Smith (8 years ago)
# Rick Waldron (8 years ago)

The tests for that are here: tc39/test262/blob/master/test/language/expressions/exponentiation/exp-operator-precedence-update-expression-semantics.js

I'm glad the previous link was helpful—hopefully this will be equally as useful.