archives

« Bugzilla Issues Index

#2011 — 14.4: Optional AssignmentExpression in YieldExpression leads to Shift/Reduce conflict?


AssignmentExpression in YieldExpression is now optional, see bug 1803. Modelling this change in the following toy grammar, a shift/reduce conflict can be observed.

SpiderMonkey (and Rhino) performs a lookahead after "yield" and tests whether the next token is not in the follow set (*) of AssignmentExpression. If the next token is not in the follow set and on the same line, it proceeds with the AssignmentExpression production rule. Otherwise it elides the AssignmentExpression.

(*) or rather a subset of the follow set, testing for the first set of AssignmentExpression makes more sense to me, for example to successfully parse the legacy array comprehension syntax `[yield for (a of b)]`.


---
%token CLASS "class"
%token EXTENDS "extends"
%token YIELD "yield"

%%

class: CLASS classTail ;

classTail: classHeritage '{' '}'
| '{' '}' ;

classHeritage: EXTENDS assignExpr ;

assignExpr: yieldExpr
| objectLiteral ;

yieldExpr: YIELD
| YIELD assignExpr ;

objectLiteral: '{' '}' ;

%%
---


[From es-discuss verbatim.]

Python has requirements for over-parenthesization which we were trying to avoid. Nevertheless, did you consider

5. Except on right of assignment and in actual argument position, yield expressions must be parenthesized

This is easy to do grammatically if we change the over-general

ClassHeritage :
| extends| AssignmentExpression

I say over-general because: do we really want this to be valid ES6?

class D extends B = C {
}

Using a higher-precedence expression non-terminal seems better. How about the next lower-precedence nonterminal that does not end in AssignmentExpression, namely LogicalORExpression?

Then any yield without parentheses would be a syntax error.

/be


fixed in rev22



the extends clause of a class is now restricted to being a LeftHandSideExpression