Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the exact syntactic ambiguity that requires parentheses around a yield expression in an OR assignment?

The following code...
Assume that the yield is inside a generator function and that something and else are defined, etc.

const value = something || yield else();

...produces the following in V8 (Chrome or Nodejs):

                const start = initial || yield wait();
                                         ^^^^^
SyntaxError: Unexpected strict mode reserved word

...and this in Firefox:

SyntaxError: yield is a reserved identifier

I first noticed this in a bluebird coroutine I was writing. The fix is to wrap the yield wait() in a parentheses.

This error happens at parse time rather than at execution time; so, my first assumption is that this is because there's a syntactic ambiguity here. I looked at the yield keyword which defines it as:

[rv] = yield [expression];

yield takes an expression and returns a value. This does not happen without the || (OR) operator as const value = yield else();; so, I looked at operator precedence. The || (OR) operator is evaluated at 5 before the yield operator at 2. The precedence looks fine.

It looks like the || (OR) operator requires an expression on either side and while I assume that yield [expression] is an expression, perhaps that's not true? Why is it that I need to wrap that part in parentheses to make it explicitly an expression? What could || yield be ambiguous with? I'm sure I'm just missing it; or, is there some sneaky/deeper reason for this?

This question was also notoriously difficult to search for, so hopefully I'm not duping here.

(You can use this Plunker https://plnkr.co/edit/rNidnFuyIOFkRkkcyWRV to make the error happen if you'd like to see it.)

Thanks!

like image 219
Shibumi Avatar asked Apr 17 '17 19:04

Shibumi


1 Answers

If you want to figure out the syntax rules, you have to look at the spec.

A LogicalOrExpression is defined as

LogicalANDExpression:
  BitwiseORExpression
  LogicalANDExpression && BitwiseORExpression

LogicalORExpression:
  LogicalANDExpression
  LogicalORExpression || LogicalANDExpression

A LogicalANDExpression can only contain BitwiseORExpressions. But a YieldExpression is not a BitwiseORExpression, it's an AssignmentExpression:

AssignmentExpression:
  ConditionalExpression
  [+Yield] YieldExpression
  ArrowFunction
  LeftHandSideExpression = AssignmentExpression 
  LeftHandSideExpression AssignmentOperatorAssignmentExpression

It basically it is higher up in the expression hierarchy:

                 +--------------------------+                
                 |   AssignmentExpression   |                
                 +--------------------------+                
                               ^                             
                               |                             
              +----------------+---------------+             
              |                                |             
              |                                |             
+--------------------------+     +--------------------------+
|  ConditionalExpression   |     |     YieldExpression      |
+--------------------------+     +--------------------------+
              ^                                              
              |                                              
              |                                              
+--------------------------+                                 
|   LogicalORExpression    |                                 
+--------------------------+                                 
              ^                                              
              |                                              
              |                                              
+--------------------------+                                 
|   LogicalANDExpression   |                                 
+--------------------------+                                 
              ^                                              
              |                                              
              |                                              
+--------------------------+                                 
|   BitwiseORExpression    |                                 
+--------------------------+   

A possibly explanation for why the syntax is structured this way is that yield is also a valid identifier name (outside of generators or yield expressions). But for more details you probably want to ask on https://esdiscuss.org/.

like image 147
Felix Kling Avatar answered Sep 21 '22 20:09

Felix Kling