Uber Kluger
Uber Kluger

Reputation: 502

ECMAScript 2020 Exponentiation Grammar confusion

Checking the latest standard for ECMA-262 ECMAScript 2020 (or 11th Edition) and couldn't figure out the grammar production for exponentiation.

UpdateExpression[Yield, Await]:
 LeftHandSideExpression[?Yield, ?Await]
 LeftHandSideExpression[?Yield, ?Await][no LineTerminator here]++
 LeftHandSideExpression[?Yield, ?Await][no LineTerminator here]--
 ++UnaryExpression[?Yield, ?Await]
 --UnaryExpression[?Yield, ?Await]

UnaryExpression[Yield, Await]:
 UpdateExpression[?Yield, ?Await]
 delete UnaryExpression[?Yield, ?Await]
 void UnaryExpression[?Yield, ?Await]
 typeof UnaryExpression[?Yield, ?Await]
 +UnaryExpression[?Yield, ?Await]
 -UnaryExpression[?Yield, ?Await]
 ~UnaryExpression[?Yield, ?Await]
 !UnaryExpression[?Yield, ?Await]
 [+Await]AwaitExpression[?Yield]

ExponentiationExpression[Yield, Await]:
 UnaryExpression[?Yield, ?Await]
 UpdateExpression[?Yield, ?Await]**ExponentiationExpression[?Yield, ?Await]

So a UnaryExpression is an ExponentiationExpression thus allowing something like -x to pass up the parsing tree but to actually evaluate an exponentiation the LHS has to be an UpdateExpression (++x, --x, x++, x-- or just x). The RHS is an ExponentiationExpression so can therefore be a UnaryExpression. This means that parsing x ** -y is easy but how do you parse -x ** y. I thought of treating it as -(x ** y) but then had no way to get the unparenthesized x ** y from being an Expression back to an UpdateExpression to feed into UnaryExpression.

Or is it simply that -x ** y is disallowed and you have to get explicit by using

-(x ** y)

or

(-x) ** y

, both of which are easy to parse as follows:

(x ** y) is a ParenthesizedExpression so feeds in to UnaryExpression as a PrimaryExpression.

(-x) similarly feeds into UpdateExpression as a PrimaryExpression

Or am I missing something obvious.

Upvotes: 2

Views: 74

Answers (1)

rici
rici

Reputation: 241771

Or is it simply that -x ** y is disallowed and you have to get explicit by using

-(x ** y)

or

(-x) ** y

Precisely.

Or am I missing something obvious.

No, you got it right.

There are some useful links in this answer to a related question from 2017, including this email thread started by Brendan Eich on the es-discuss list in 2015, which proposes the current syntax.

Some concrete examples:

From the Firefox console:

-2**4
SyntaxError: unparenthesized unary expression can't appear on the left-hand side of '**'

From David Flanagan's "JavaScript: The Definitive Guide" (O'Reilly) (not an endorsement):

There is a natural ambiguity to expressions like -3 ** 2. Depending on the relative precedence of unary minus and exponentiation, that expression could mean (-3)**2 or -(3**2). Different languages handle this differently, and rather than pick sides, JavaScript simply makes it a syntax error to omit parentheses in this case, forcing you to write an unambiguous expression.

Of course, the real definitive guide is the grammar, which you have already quoted.

Upvotes: 1

Related Questions